승인된 결제를 취소하려면 토스페이먼츠 결제 취소 API를 호출하세요. 결제 금액 전액 또는 일부를 고객에게 환불할 수 있습니다.
결제 수단 | 취소 기한 | 취소 소요 기간 |
---|---|---|
카드 | 취소 기한은 없지만, 카드사 별로 결제 데이터 보관 기간이 달라서 1년을 초과하면 취소가 안될 수 있어요. | 결제가 매입되기 전에는 취소 직후 환불됩니다. 매입 이후 또는 부분 취소는 요청 후 영업일 기준 3~4일이 소요됩니다. |
계좌이체 | 180일 이내의 거래만 취소 가능합니다. | 실시간으로 환불됩니다. |
가상계좌 | 상점마다 설정이 다를 수 있으나 보통 365일 동안 취소가 가능합니다. | 영입일 기준 총 2일이 소요됩니다. |
휴대폰 | 통신사 정책으로 결제가 발생한 당월에만 취소가 가능합니다. | 당일 취소됩니다. |
해외 간편결제(PayPal) | 180일 이내의 거래만 취소 가능합니다. | 영업일 기준 최대 5일이 소요됩니다. 일부 환불은 카드 회사에 따라 최대 30일이 소요될 수 있습니다. |
승인된 결제를 취소하려면 결제 키와 결제를 취소하는 이유를 결제 취소 API 파라미터로 추가해서 호출합니다.
- API 엔드포인트에 결제 승인 API 요청 결과로 받은
paymentKey
를 Path 파라미터로 추가하세요. - 취소 이유를
cancelReason
파라미터로 요청 본문에 추가하세요. - 응답의
cancels
필드를 확인하세요. 결제 취소 정보 객체가 배열 안에 돌아옵니다. 각 취소 거래마다 거래를 구분하는transactionKey
를 가지고 있습니다.
curl --request POST \
--url https://api.tosspayments.com/v1/payments/rBUT3zwo6w230zaSGzBsX/cancel \
--header 'Authorization: Basic dGVzdF9za196WExrS0V5cE5BcldtbzUwblgzbG1lYXhZRzVSOg==' \
--header 'Content-Type: application/json' \
--data '{"cancelReason":"고객이 취소를 원함"}'
{
"mId": "tosspayments",
"version": "2022-11-16",
"lastTransactionKey": "",
"paymentKey": "",
"orderId": "",
"orderName": "토스 티셔츠 외 2건",
"currency": "KRW",
"method": "카드",
"status": "CANCELED",
"requestedAt": "2022-01-01T11:31:29+09:00",
"approvedAt": "2022-01-01T11:31:51+09:00",
"useEscrow": false,
"cultureExpense": false,
"checkout": {
"url": "https://api.tosspayments.com/v1/payments//checkout"
},
"card": {
"issuerCode": "33",
"acquirerCode": "31",
"number": "12341234****123*",
"installmentPlanMonths": 0,
"isInterestFree": false,
"interestPayer": null,
"approveNo": "00000000",
"useCardPoint": false,
"cardType": "신용",
"ownerType": "개인",
"acquireStatus": "READY"
},
"virtualAccount": null,
"transfer": null,
"mobilePhone": null,
"giftCertificate": null,
"cashReceipt": null,
"cashReceipts": null,
"discount": null,
"cancels": [
{
"cancelReason": "고객이 취소를 원함",
"canceledAt": "2022-01-01T11:32:04+09:00",
"cancelAmount": 10000,
"taxFreeAmount": 0,
"taxExemptionAmount": 0,
"refundableAmount": 0,
"easyPayDiscountAmount": 0,
"transactionKey": "8B4F646A829571D870A3011A4E13D640",
"receiptKey": "V4AJ6AhSWsGN0RocizZQlagPLN8s2IahJLXpfSHzQBTKoDG7"
}
],
"secret": null,
"type": "NORMAL",
"easyPay": "토스페이",
"country": "KR",
"failure": null,
"totalAmount": 10000,
"balanceAmount": 0,
"suppliedAmount": 0,
"vat": 0,
"taxFreeAmount": 0,
"taxExemptionAmount": 0
}
멱등키를 요청 헤더에 추가하면 중복 취소 없이 안전하게 처리됩니다.
결제 금액 중 일부만 취소하려면 cancelAmount
에 취소할 금액을 추가해서 결제 취소 API를 요청합니다. cancelAmount
에 값을 넣지 않으면 전액 취소됩니다.
curl --request POST \
--url https://api.tosspayments.com/v1/payments/AZPfZsU-vgb1IOllmLzWJ/cancel \
--header 'Authorization: Basic dGVzdF9za196WExrS0V5cE5BcldtbzUwblgzbG1lYXhZRzVSOg==' \
--header 'Content-Type: application/json' \
--data '{"cancelReason":"고객이 취소를 원함","cancelAmount":1000}'
부분 취소를 여러 번 하면 아래와 같이 cancels
필드에 취소 객체가 여러 개 돌아옵니다.
// Payment 객체
{
// ...
"cancels": [
{
"cancelAmount": 1000,
"cancelReason": "고객이 취소를 원함",
"taxFreeAmount": 0,
"taxExemptionAmount": 0,
"refundableAmount": 9000,
"easyPayDiscountAmount": 0,
"canceledAt": "2022-01-01T23:23:52+09:00",
"transactionKey": "8B4F646A829571D870A3011A4E13D640",
"receiptKey": "CuskOnzZEf0Xbwo8eMZ56slTAXbJ8jUjTX3n6SNuvY5d7Fpf"
},
{
"cancelAmount": 1000,
"cancelReason": "고객이 다른 품목도 취소를 원함",
"taxFreeAmount": 0,
"taxExemptionAmount": 0,
"refundableAmount": 8000,
"easyPayDiscountAmount": 0,
"canceledAt": "2022-01-02T20:00:00+09:00",
"transactionKey": "6673C15BF350C3F9BF45CEFC48C7A24E",
"receiptKey": "PLDm1CZSQxTBvYrHytz3yt3MU09Nx57IoCxIEJ8HPzOyIRos"
}
]
// ...
}
가상계좌 결제를 취소하면 취소일+2일에 은행에서 결제 고객의 계좌로 입금 처리를 해줍니다. 따라서 가상계좌 결제를 취소할 때는 환불받을 고객의 계좌 정보를 결제 취소 API 요청에 포함해야 합니다.
refundReceiveAccount
에 환불받을 고객의 계좌 정보를 포함해서 결제 취소를 요청하세요. 환불 계좌의 번호와 예금주의 유효성이 확인되면 해당 계좌로 취소 금액이 환불됩니다.
curl --request POST \
--url https://api.tosspayments.com/v1/payments/uHUwkDXJigvtJXDW65oko/cancel \
--header 'Authorization: Basic dGVzdF9za196WExrS0V5cE5BcldtbzUwblgzbG1lYXhZRzVSOg==' \
--header 'Content-Type: application/json' \
--data '{"cancelReason":"고객이 취소를 원함","cancelAmount":10000,"refundReceiveAccount":{"bank":"20","accountNumber":"1000123456789","holderName":"김토페"}}'
응답은 다른 취소 요청과 동일하게 Payment 객체의 cancels
로 돌아옵니다.
{
"mId": "tvivarepublica",
"version": "2022-11-16",
"lastTransactionKey": "",
"paymentKey": "",
"orderId": "",
"orderName": "토스 티셔츠 외 2건",
"currency": "KRW",
"method": "가상계좌",
"status": "PARTIAL_CANCELED",
"requestedAt": "2022-01-01T11:48:53+09:00",
"approvedAt": "2022-01-01T11:49:35+09:00",
"useEscrow": false,
"cultureExpense": false,
"checkout": {
"url": "https://api.tosspayments.com/v1/payments//checkout"
},
"card": null,
"virtualAccount": {
"accountNumber": "X6505831718354",
"accountType": "일반",
"bankCode": "20",
"customerName": "김토스",
"dueDate": "2022-01-03T11:48:53+09:00",
"expired": true,
"settlementStatus": "INCOMPLETED",
"refundStatus": "NONE",
"refundReceiveAccount": null
},
"transfer": null,
"mobilePhone": null,
"giftCertificate": null,
"cashReceipt": null,
"cashReceipts": null,
"discount": null,
"cancels": [
{
"cancelReason": "고객 변심",
"canceledAt": "2022-01-01T11:51:04+09:00",
"cancelAmount": 10000,
"taxFreeAmount": 0,
"taxExemptionAmount": 0,
"refundableAmount": 0,
"easyPayDiscountAmount": 0,
"transactionKey": "ND38Q0IGWUG7UC02G6G1GL1XJRG2BO5N",
"receiptKey": "aIHE2heVz6hwRIWsu0msyxjF6xhPtn9T44fij4BF9bNUN64G"
}
],
"secret": null,
"type": "NORMAL",
"easyPay": null,
"country": "KR",
"failure": null,
"totalAmount": 10000,
"balanceAmount": 0,
"suppliedAmount": 0,
"vat": 0,
"taxFreeAmount": 0,
"taxExemptionAmount": 0
}
결제위젯 어드민 > 기능 > 가상계좌 메뉴에서 가상계좌 환불 정보 입력 > 사용함을 선택했다면 고객이 환불 계좌 정보를 입력하는 UI를 사용할 수 있어요.
환불 계좌 정보는 결제 승인으로 받은 Payment 객체의 virtualAccount.refundReceiveAccount
필드에서 확인할 수 있어요.
다만 해당 정보는 결제창을 띄운 시점부터 30분 동안만 조회할 수 있기 때문에 결제 승인 직후 응답을 저장해주세요. 30분이 지나면 refundReceiveAccount
필드의 값은 null
로 내려옵니다.
저장한 정보를 결제 취소 API의 파라미터로 사용하세요. 결제위젯에서 고객의 환불 정보를 받는 UI만 제공하기 때문에 환불 계좌 정보를 입력 받아도 해당 계좌로 자동 환불되지 않습니다.
{
// Payment 객체
// ...
"virtualAccount": {
"accountNumber": "X6505636518308",
"accountType": "일반",
"bankCode": "20",
"customerName": "박토스",
"dueDate": "2022-01-10T21:05:09+09:00",
"expired": false,
"settlementStatus": "INCOMPLETED",
"refundStatus": "NONE",
"refundReceiveAccount": {
"bankCode": "20",
"accountNumber": "001012341342",
"holderName": "박토스"
}
},
// ...
}