목차

2023년 8월 23일 ・ 읽는 시간 7분

결제와 거래 일러스트

결제와 거래

는 결제와 어떻게 다르고, 어떻게 구분해야 할까요? 거래에는 결제 거래, 부분 취소 거래, 취소 거래가 있어요. 즉 모든 결제는 거래이고, 모든 취소도 거래죠.

최초의 결제 거래 이후에 생기는 거래는 결제 상태 변화로 이해할 수도 있어요. '결제 승인' 상태였던 거래가 '부분 취소' 혹은 '취소' 상태가 된 것으로요. 이렇게 결제와 거래는 각각 Payment 객체Transaction 객체로 표현돼요. Payment 객체는 결제 거래에 대한 자세한 정보를 가지고 있어요. Transaction 객체는 결제 거래, 취소 거래 각각에 대한 정보를 담고 있어요.

거래 흐름과 객체 변화

결제와 취소 예제를 통해 더 자세히 이해해 볼게요. 이 가이드는 최신 API 버전 2022-11-16을 기반으로 합니다.

1️⃣ 결제 거래

최초 결제 거래가 일어나면 결제 상태를 나타내는 status 값은 Payment 객체, Transaction 객체 둘 다 결제 승인을 나타내는 DONE이에요.

결제가 요청되는 순간 Payment 객체가 생겨요. 이 결제를 특정하기 위해 토스페이먼츠에서 paymentKey를 만들어요.

Payment
JSON
{
"mId": "ttosspayments",
"lastTransactionKey": "D830460735FF8B6C8DFCF515F6AF31B8",
"paymentKey": "dJv2eBNjG0Poxy1XQL8RJM5AenNplX87nO5Wmlg96RKwZz4Y",
"orderId": "2c0lhlsxtMlGKUC5GOyik",
"orderName": "토스 티셔츠 외 2건",
"taxExemptionAmount": 0,
"status": "DONE",
"requestedAt": "2023-08-21T19:47:13+09:00",
"approvedAt": "2023-08-21T19:48:07+09:00",
// ...
"receipt": {
"url": "https://dashboard.tosspayments.com/receipt/redirection?transactionId=ttoss202308211948077oYh3&ref=PX"
},
"checkout": {
"url": "https://api-staging.tosspayments.com/v1/payments/dJv2eBNjG0Poxy1XQL8RJM5AenNplX87nO5Wmlg96RKwZz4Y/checkout"
},
"currency": "KRW",
"totalAmount": 15000,
"balanceAmount": 15000,
"suppliedAmount": 13636,
"vat": 1364,
"taxFreeAmount": 0,
"method": "카드",
"version": "2022-11-16"
}

요청된 결제가 승인되면 Transaction 객체도 생기고 이 거래를 특정하는 transactionKey도 만들어져요. 이 값은 Payment 객체의 lastTransactionKey에 할당되죠.

Transaction
JSON
[
{
"mId": "ttosspayments",
"transactionKey": "D830460735FF8B6C8DFCF515F6AF31B8",
"paymentKey": "dJv2eBNjG0Poxy1XQL8RJM5AenNplX87nO5Wmlg96RKwZz4Y",
"orderId": "2c0lhlsxtMlGKUC5GOyik",
"method": "카드",
"customerKey": null,
"useEscrow": false,
"receiptUrl": "https://dashboard.tosspayments.com/receipt/redirection?transactionId=ttoss202308211948077oYh3&ref=PX",
"status": "DONE",
"transactionAt": "2023-08-21T19:48:07+09:00",
"currency": "KRW",
"amount": 15000
}
]

2️⃣ 부분 취소 거래

이후 일부 금액만 취소하는 '부분 취소 거래'가 일어나면 Payment.cancels에 취소된 거래 객체가 배열로 추가됩니다.

Payment
JSON
{
"mId": "ttosspayments",
"lastTransactionKey": "52996EABEAF10BB18820DFDE3595D98E",
"paymentKey": "dJv2eBNjG0Poxy1XQL8RJM5AenNplX87nO5Wmlg96RKwZz4Y",
"orderId": "2c0lhlsxtMlGKUC5GOyik",
"orderName": "토스 티셔츠 외 2건",
"taxExemptionAmount": 0,
"status": "PARTIAL_CANCELED",
"requestedAt": "2023-08-21T19:47:13+09:00",
"approvedAt": "2023-08-21T19:48:07+09:00",
// ...
"cancels": [
{
"transactionKey": "52996EABEAF10BB18820DFDE3595D98E",
"cancelReason": "고객 변심",
"taxExemptionAmount": 0,
"canceledAt": "2023-08-21T19:48:42+09:00",
"easyPayDiscountAmount": 0,
"receiptKey": null,
"cancelAmount": 5000,
"taxFreeAmount": 0,
"taxAmount": null,
"refundableAmount": 10000,
"cancelStatus": "DONE",
"cancelRequestId": null
}
],
"receipt": {
"url": "https://dashboard.tosspayments.com/receipt/redirection?transactionId=ttoss202308211948077oYh3&ref=PX"
},
"checkout": {
"url": "https://api-staging.tosspayments.com/v1/payments/dJv2eBNjG0Poxy1XQL8RJM5AenNplX87nO5Wmlg96RKwZz4Y/checkout"
},
"currency": "KRW",
"totalAmount": 15000,
"balanceAmount": 10000,
"suppliedAmount": 9091,
"vat": 909,
"taxFreeAmount": 0,
"method": "카드",
"version": "2022-11-16"
}

이때 '결제 거래'를 특정하던 lastTransactionKey가 '부분 취소 거래'를 특정하는 transactionKey로 대체됩니다.

결제 승인 거래 객체에 더해 취소 거래 객체가 하나 더 추가됩니다.

Transaction
JSON
[
{
"mId": "ttosspayments",
"transactionKey": "D830460735FF8B6C8DFCF515F6AF31B8",
"paymentKey": "dJv2eBNjG0Poxy1XQL8RJM5AenNplX87nO5Wmlg96RKwZz4Y",
"orderId": "2c0lhlsxtMlGKUC5GOyik",
"method": "카드",
"customerKey": null,
"useEscrow": false,
"receiptUrl": "https://dashboard.tosspayments.com/receipt/redirection?transactionId=ttoss202308211948077oYh3&ref=PX",
"status": "DONE",
"transactionAt": "2023-08-21T19:48:07+09:00",
"currency": "KRW",
"amount": 15000
},
{
"mId": "ttosspayments",
"paymentKey": "dJv2eBNjG0Poxy1XQL8RJM5AenNplX87nO5Wmlg96RKwZz4Y",
"orderId": "2c0lhlsxtMlGKUC5GOyik",
"method": "카드",
"customerKey": null,
"useEscrow": false,
"receiptUrl": "https://dashboard.tosspayments.com/receipt/redirection?transactionId=ttoss202308211948077oYh3&ref=PX",
"status": "PARTIAL_CANCELED",
"transactionAt": "2023-08-21T19:48:42+09:00",
"currency": "KRW",
"amount": 5000
}
]

3️⃣ 두 번째 부분 취소 거래

마지막으로 한 번 더 '부분 취소 거래'가 일어나면, Payment.cancels에 취소 객체가 하나 더 추가됩니다. 마찬가지로 '부분 취소 거래'를 특정하는 새로운 transactionKeylastTransactionKey에 할당됩니다.

Payment
JSON
{
"mId": "ttosspayments",
"lastTransactionKey": "9CE7696841E7C7B3C3B5020F80ABC9E0",
"paymentKey": "dJv2eBNjG0Poxy1XQL8RJM5AenNplX87nO5Wmlg96RKwZz4Y",
"orderId": "2c0lhlsxtMlGKUC5GOyik",
"orderName": "토스 티셔츠 외 2건",
"taxExemptionAmount": 0,
"status": "PARTIAL_CANCELED",
"requestedAt": "2023-08-21T19:47:13+09:00",
"approvedAt": "2023-08-21T19:48:07+09:00",
//...
"cancels": [
{
"transactionKey": "52996EABEAF10BB18820DFDE3595D98E",
"cancelReason": "고객 변심",
"taxExemptionAmount": 0,
"canceledAt": "2023-08-21T19:48:42+09:00",
"easyPayDiscountAmount": 0,
"receiptKey": null,
"cancelAmount": 5000,
"taxFreeAmount": 0,
"taxAmount": null,
"refundableAmount": 10000,
"cancelStatus": "DONE",
"cancelRequestId": null
},
{
"transactionKey": "9CE7696841E7C7B3C3B5020F80ABC9E0",
"cancelReason": "고객 변심",
"taxExemptionAmount": 0,
"canceledAt": "2023-08-21T19:49:07+09:00",
"easyPayDiscountAmount": 0,
"receiptKey": null,
"cancelAmount": 10000,
"taxFreeAmount": 0,
"taxAmount": null,
"refundableAmount": 0,
"cancelStatus": "DONE",
"cancelRequestId": null
}
],
"receipt": {
"url": "https://dashboard.tosspayments.com/receipt/redirection?transactionId=ttoss202308211948077oYh3&ref=PX"
},
"checkout": {
"url": "https://api-staging.tosspayments.com/v1/payments/dJv2eBNjG0Poxy1XQL8RJM5AenNplX87nO5Wmlg96RKwZz4Y/checkout"
},
"currency": "KRW",
"totalAmount": 15000,
"balanceAmount": 0,
"suppliedAmount": 0,
"vat": 0,
"taxFreeAmount": 0,
"method": "카드",
"version": "2022-11-16"
}

한 번의 결제 거래와 두 번의 부분 취소 거래로 Transaction 객체는 총 세 개가 됩니다. 즉, 하나의 결제에 대해 세 개의 거래가 생긴 것이죠.

Transaction
JSON
[
{
"mId": "ttosspayments",
"transactionKey": "D830460735FF8B6C8DFCF515F6AF31B8",
"paymentKey": "dJv2eBNjG0Poxy1XQL8RJM5AenNplX87nO5Wmlg96RKwZz4Y",
"orderId": "2c0lhlsxtMlGKUC5GOyik",
"method": "카드",
"customerKey": null,
"useEscrow": false,
"receiptUrl": "https://dashboard.tosspayments.com/receipt/redirection?transactionId=ttoss202308211948077oYh3&ref=PX",
"status": "DONE",
"transactionAt": "2023-08-21T19:48:07+09:00",
"currency": "KRW",
"amount": 15000
},
{
"mId": "ttosspayments",
"transactionKey": "52996EABEAF10BB18820DFDE3595D98E",
"paymentKey": "dJv2eBNjG0Poxy1XQL8RJM5AenNplX87nO5Wmlg96RKwZz4Y",
"orderId": "2c0lhlsxtMlGKUC5GOyik",
"method": "카드",
"customerKey": null,
"useEscrow": false,
"receiptUrl": "https://dashboard.tosspayments.com/receipt/redirection?transactionId=ttoss202308211948077oYh3&ref=PX",
"status": "PARTIAL_CANCELED",
"transactionAt": "2023-08-21T19:48:42+09:00",
"currency": "KRW",
"amount": 5000
},
{
"mId": "ttosspayments",
"transactionKey": "9CE7696841E7C7B3C3B5020F80ABC9E0",
"paymentKey": "dJv2eBNjG0Poxy1XQL8RJM5AenNplX87nO5Wmlg96RKwZz4Y",
"orderId": "2c0lhlsxtMlGKUC5GOyik",
"method": "카드",
"customerKey": null,
"useEscrow": false,
"receiptUrl": "https://dashboard.tosspayments.com/receipt/redirection?transactionId=ttoss202308211948077oYh3&ref=PX",
"status": "PARTIAL_CANCELED",
"transactionAt": "2023-08-21T19:49:07+09:00",
"currency": "KRW",
"amount": 10000
}
]

즉, Payment 객체의 paymentKey는 변하지 않고, lastTransactionKey는 매 거래마다 새로 만들어진 transactionKey로 대체돼요.

거래 조회 API 사용 케이스

거래 조회 API를 사용하는 여러 방법을 알아봅니다.

1️⃣ 하루 동안의 거래 기록을 조회하고 싶을 때

하루 동안의 거래 기록을 조회하려면 startDateendDate에 초 단위까지 시간 정보에 포함해서 요청해야 합니다.

예를 들어 2022년 1월 1일 하루 동안의 기록 전체를 조회하려면 아래와 같이 startDate2022-01-01T00:00:00로, endDate2022-01-01T23:59:59로 설정해야 합니다.

응답으로 2022-01-01T00:00:00 부터 2022-01-02T00:00:00 전까지의 기록이 돌아옵니다.

만약 거래 기록 조회의 Query 파라미터에 날짜 정보만 있다면 시간은 자동으로 00:00:00으로 설정된다는 점을 유의하세요.

위와 같이 startDateendDate가 시간 정보 없이 같은 날짜로 설정되어 있다면 자동 시간 설정으로 인해 동일한 날짜와 시간을 가리키게 됩니다. 따라서 위 2022년 1월 1일 0시 0분 0초 정각에 난 거래만 조회됩니다.

2️⃣ 특정 거래 기록 이후부터 조회하고 싶을 때

특정 거래 기록 이후부터 조회하고 싶다면 startingAfter에 특정하고 싶은 거래의 transactionKey 값을 넣어주면 됩니다.

예를 들어 아래 요청은 2022년 1월 1일부터 1월 10일 사이의 거래 기록 중 paymentKey5OhJr1hOealGAknFDLN16인 기록 다음 건부터 거래 기록을 조회합니다.

3️⃣ 같은 paymentKey를 가진 거래 기록이 있을 때

거래 조회 응답에서 paymentKey가 같고 transactionKey는 다른 여러 개의 거래 기록이 배열로 들어올 수 있습니다. 하나의 결제 건에서 금액 지불, 결제 취소, 결제 부분 취소와 같이 여러 번의 거래가 일어날 수 있기 때문입니다.

응답으로 돌아온 객체의 status 값을 보면 어떤 거래가 이루어졌는지 알 수 있습니다.

응답
JSON
// paymentKey가 ''인 결제에서 각각 지불/취소된 거래 기록 응답 예시
[
{
"mId": "tosspayments",
"transactionKey": "",
"paymentKey": "",
"orderId": "",
"method": "카드",
"customerKey": "",
"useEscrow": false,
"receiptUrl": "https://dashboard.tosspayments.com/receipt/redirection?transactionId=tosspayments&ref=PX",
"status": "DONE", // 결제 금액 지불 완료
"transactionAt": "2022-01-01T01:23:56+09:00",
"currency": "KRW",
"amount": 1000
},
{
"mId": "tosspayments",
"transactionKey": "",
"paymentKey": "",
"orderId": "",
"method": "카드",
"customerKey": "",
"useEscrow": false,
"receiptUrl": "https://dashboard.tosspayments.com/receipt/redirection?transactionId=tosspayments&ref=PX",
"status": "CANCELED", // 결제 취소
"transactionAt": "2022-01-01T01:23:58+09:00",
"currency": "KRW",
"amount": 1000
}
]

Writer 한주연 Graphic 이은호, 이나눔


📍 함께 읽으면 좋을 콘텐츠

  • 더 궁금한 내용이 있나요?
  • 코드 샘플을 참고하세요
  • 기술지원이 필요한가요?
    실시간 문의|이메일 보내기