✅ 결제와 거래의 차이를 이해하고 결제 흐름에 따른 객체의 변화를 알 수 있어요.
거래는 결제와 어떻게 다르고, 어떻게 구분해야 할까요? 거래에는 결제 거래, 부분 취소 거래, 취소 거래가 있어요. 즉 모든 결제는 거래이고, 모든 취소도 거래죠. 최초의 결제 거래 이후에 생기는 거래는 '결제 상태 변화'로 이해할 수도 있어요. '결제 승인' 상태였던 거래가 '부분 취소' 혹은 '취소' 상태가 된 것으로요. 이렇게 결제와 거래는 각각 Payment 객체와 Transaction 객체로 표현돼요. Payment 객체는 결제 거래에 대한 자세한 정보를 가지고 있어요. Transaction 객체는 결제 거래, 취소 거래 각각에 대한 정보를 담고 있어요.
결제와 취소 예제를 통해 더 자세히 이해해 볼게요.
최초 결제 거래가 일어나면 결제 상태를 나타내는 status
값은 Payment 객체, Transaction 객체 둘 다 결제 승인을 나타내는 DONE
이에요.
결제가 요청되는 순간 Payment 객체가 생겨요. 이 결제를 특정하기 위해 토스페이먼츠에서 paymentKey
를 만들어요.
요청된 결제가 승인되면 Transaction 객체도 생기고 이 거래를 특정하는 transactionKey
도 만들어져요. 이 값은 Payment 객체의 lastTransactionKey
에 할당되죠.
{
"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"
},
"transactionKey": "D830460735FF8B6C8DFCF515F6AF31B8",
"currency": "KRW",
"totalAmount": 15000,
"balanceAmount": 15000,
"suppliedAmount": 13636,
"vat": 1364,
"taxFreeAmount": 0,
"method": "카드",
"version": "2022-11-16"
}
[
{
"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
}
]
이후 일부 금액만 취소하는 '부분 취소 거래'가 일어나면 Payment.cancels
에 취소된 거래 객체가 배열로 추가됩니다.
이때 '결제 거래'를 특정하던 lastTransactionKey
가 '부분 취소 거래'를 특정하는 transactionKey
로 대체됩니다.
결제 승인 거래 객체에 더해 취소 거래 객체가 하나 더 추가됩니다.
{
"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
}
],
"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"
}
[
{
"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
}
]
마지막으로 한 번 더 '부분 취소 거래'가 일어나면, Payment.cancels
에 취소 객체가 하나 더 추가됩니다.
마찬가지로 '부분 취소 거래'를 특정하는 새로운 transactionKey
가 lastTransactionKey
에 할당됩니다.
한 번의 결제 거래와 두 번의 부분 취소 거래로 Transaction 객체는 총 세 개가 됩니다. 즉, 하나의 결제에 대해 세 개의 거래가 생긴 것이죠.
{
"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
},
{
"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
}
],
"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"
}
[
{
"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
로 대체돼요.