Appearance
Payment API
토스 프론트에서 결제 및 환불을 처리하기 위한 API예요. 카드, 애플페이, 삼성페이, 현금 영수증, 간편결제 등 다양한 결제 수단을 지원해요.
주의 사항
프론트에서 카드 결제 테스트 시 실제 승인이 발생하여 주의가 필요해요.
주의 사항
[카드 결제 테스트 시]
- 테스트 후 반드시 즉시 취소 처리 필요
- 결제 응답의
paymentKey,approvalNumber,timestamp,vanTransactionKey등 승인 취소를 위한 값을 저장하여 취소에 활용
[권장 테스트 방법]
- 동작 확인 목적이라면 현금 결제 > 현금영수증 미발급으로 테스트 권장
- 실제 금전적 부담 없이 결제 플로우 확인 가능
Methods
requestPayment
통합 결제를 요청해요.
진행 중인 통합결제창을 닫으려면 cancelPayment를 사용해요. 결제창이 닫히면 대기 중이던 requestPayment가 { type: "CANCELED" }를 반환해요.
Parameters
| 파라미터 | 타입 | 필수 | 기본값 | 설명 |
|---|---|---|---|---|
paymentKey | string | ✓ | - | 중복되지 않는 고유한 결제 식별자 |
tax | number | ✓ | - | 세금 (일반적으로 Math.floor(price / 11), 면세인 경우 0) |
supplyValue | number | ✓ | - | 공급가액 (결제 금액 - 세금) |
taxExemptValue | number | - | 면세 금액 | |
tip | number | ✓ | - | 봉사료 |
installment | number | 0 | 할부 개월 | |
tid | string | - | 결제 TID (CAT ID) | |
timeoutMs | number | 60000 | 타임아웃 (ms 단위) | |
localeCode | 'ko' | 'en' | 'ko' | 언어 설정 | |
excludePaymentTypes | ['CASH'] | - | 제외할 결제 수단 (현재 현금만 지원) |
면세 금액 설정
- 과세·면세가 함께 포함된 결제에서는
supplyValue에 면세 금액을 포함하고,taxExemptValue에 면세 금액을 입력해요. taxExemptValue를 생략하면tax가 0인 경우supplyValue전체를 면세로 처리하고,tax가 0보다 크면 면세 금액을 0으로 처리해요.- 결제를 취소할 때는 원거래와 동일한
tax,supplyValue,taxExemptValue를 전달해요.
paymentKey는 파트너가 직접 만들어요
paymentKey는 토스에서 발급하는 값이 아니라 파트너가 만들어 전달하는 중복되지 않는 결제 식별자예요. 64자 이하로 만들어주세요.
결제를 취소하거나 영수증을 출력할 때 같은 값을 다시 사용하니, 결제를 요청할 때 쓴 값을 저장해 두세요.
이미 쓴 paymentKey를 새 결제에 다시 쓰면 승인 자체는 진행되지만, getPayment이 읽는 승인 결과가 나중 결제 것으로 덮어써져요. 먼저 한 결제의 결과는 다시 조회할 수 없으니 결제마다 새 값을 만들어주세요.
Example
js
/**
* 통합 결제 요청
* @param {Object} params 통합 결제 요청 파라미터
* @returns {Object} 결제 결과
*/
const price = 10000;
const tax = Math.floor(price / 11);
const supplyValue = price - tax;
const result = await sdk.payment.requestPayment({
paymentKey: "paymentKey",
tax,
supplyValue,
taxExemptValue: 0, // 면세 금액
tip: 0,
timeoutMs: 60000,
localeCode: "ko", // "ko" or "en" default "ko"
excludePaymentTypes: ["CASH"], // 현금 결제 제외
});
if (result.type === "CANCELED" || result.type === "TIMEOUT") {
return;
}
switch (result.response.paymentMethod) {
case "CARD":
console.log(result.response.card);
break;
case "CASH":
console.log(result.response.cash);
break;
case "BARCODE":
console.log(result.response.barcode);
break;
}Response
공통 간편결제 정보
성공 응답(type: 'SUCCESS')의 response에는 다음 간편결제 정보가 포함될 수 있어요. 결제 수단별 응답이 공유하는 선택 필드이며, 결제 승인·취소 및 결과 조회 응답에 적용돼요.
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
easyPay | object | 간편결제 정보 | |
easyPay.provider | string | 간편결제사 이름. 예: '토스페이', '네이버페이', '카카오페이' |
provider는 전달받은 문자열을 그대로 반환해요. 위 이름은 예시이며, 고정된 값 목록은 아니에요.
앱 지원 여부를 확인해주세요
실제 프론트 단말기에서는 간편결제 정보를 전달하는 앱의 지원이 필요해요. 지원하지 않는 앱 버전이나 정보가 없는 결제에서는 easyPay가 생략될 수 있고, provider도 선택 값이에요. result.type === 'SUCCESS'를 확인한 뒤 result.response.easyPay?.provider로 읽어주세요.
카드/삼성페이/애플페이 결제
js
{
type: 'SUCCESS',
response: {
paymentMethod: 'CARD',
tid?: string, // 결제 TID (CAT ID)
vanTransactionKey?: string, // VAN 거래 일련번호 (무카드 취소 시 사용)
card: {
van: 'NICE' | 'KIS' | 'KOVAN' | 'KFTC' | 'SMARTRO' | 'KSNET' | 'DAOU' | 'NICEPAY',
timestamp: number, // 승인 시간
approvalNumber: string, // 승인번호
acquirerName: string, // 매입사 명
acquirerCode: string, // 매입사 코드
issuerName: string, // 발급사 명
issuerCode: string, // 발급사 코드
cardType: 'CREDIT_CARD' | 'CHECK_CARD' | 'PREPAID_CARD',
balance: number, // 선불카드 잔액
installment: number, // 할부 개월
shopCode?: string, // 가맹점 번호 (숫자 9자리)
maskedCardNumber?: string, // 마스킹된 카드 번호 (bin 8자리만 표시)
},
},
}현금 영수증
js
// 현금영수증 발급 시
{
type: 'SUCCESS',
response: {
paymentMethod: 'CASH',
tid?: string, // 결제 TID (CAT ID)
vanTransactionKey?: string, // VAN 거래 일련번호
cash: {
isCashReceipt: true,
cashReceipt: {
van: 'NICE' | 'KIS' | 'KOVAN' | 'KFTC' | 'SMARTRO' | 'KSNET' | 'DAOU' | 'NICEPAY',
timestamp: number, // 승인 시간
issuerType: 'CONSUMER' | 'BUSINESS', // 발급 대상 유형
issuanceType: 'PHONE' | 'BUSINESS_NUMBER' | 'CARD', // 발급 방식
identityNumber: string, // 현금영수증 번호 값
maskedIdentityNumber: string, // 현금영수증 번호 값 (일부 별표 처리)
approvalNumber: string, // 승인번호
isSelfIssuance: boolean, // 자진 발급 여부
shopCode: null, // 현금영수증에는 없는 값이라 항상 null이에요
},
},
},
}
// 현금영수증 미발급 시
{
type: 'SUCCESS',
response: {
paymentMethod: 'CASH',
tid?: string, // 결제 TID (CAT ID)
vanTransactionKey?: string, // VAN 거래 일련번호
cash: {
isCashReceipt: false,
},
},
}간편결제
js
{
type: 'SUCCESS',
response: {
paymentMethod: 'BARCODE',
easyPay?: {
provider?: string,
},
tid?: string, // 결제 TID (CAT ID)
vanTransactionKey?: string, // VAN 거래 일련번호
barcode: {
van: 'NICE' | 'KIS' | 'KOVAN' | 'KFTC' | 'SMARTRO' | 'KSNET' | 'DAOU' | 'NICEPAY',
timestamp: number, // 승인 시간
approvalNumber: string, // 승인번호
acquirerName: string, // 매입사 명
acquirerCode: string, // 매입사 코드
issuerName: string, // 발급사 명
issuerCode: string, // 발급사 코드
cardType: 'CREDIT_CARD' | 'CHECK_CARD' | 'PREPAID_CARD',
balance: number, // 선불카드 잔액
shopCode: string, // 가맹점 번호 (숫자 9자리)
},
extraData?: {
vanTransactionManagementId: string, // 알리페이/위챗페이 취소 시 필요
},
},
}vanTransactionKey 안내
vanTransactionKey는 무카드 취소에 필요한 VAN 거래 일련번호예요. 선택 값이라 VAN사·결제 환경에 따라 내려오지 않을 수 있으니, 값이 있으면 저장해두었다가 취소에 활용해주세요.
requestBarcodePayment
QR, 바코드를 인식하는 간편결제를 요청해요.
Parameters
| 파라미터 | 타입 | 필수 | 기본값 | 설명 |
|---|---|---|---|---|
paymentKey | string | ✓ | - | 중복되지 않는 고유한 결제 식별자 |
tax | number | ✓ | - | 세금 |
supplyValue | number | ✓ | - | 공급가액 |
taxExemptValue | number | - | 면세 금액 | |
tip | number | ✓ | - | 봉사료 |
installment | number | 0 | 할부 개월 | |
tid | string | - | 결제 TID (CAT ID) | |
timeoutMs | number | 60000 | 타임아웃 (ms 단위) | |
localeCode | 'ko' | 'en' | 'ko' | 언어 설정 |
Example
js
/**
* 간편결제 요청
* @param {Object} params 간편결제 요청 파라미터
* @returns {Object} 결제 결과
*/
const price = 10000;
const tax = Math.floor(price / 11);
const supplyValue = price - tax;
const result = await sdk.payment.requestBarcodePayment({
paymentKey: "barcodePaymentKey",
tax,
supplyValue,
taxExemptValue: 0, // 면세 금액
tip: 0,
timeoutMs: 60000,
localeCode: "ko", // "ko" or "en" default "ko"
});
if (result.type === "CANCELED" || result.type === "TIMEOUT") {
return;
}
console.log(result.response.barcode);Response
requestPayment Response의 간편결제와 같아요. paymentMethod는 항상 'BARCODE'예요.
requestCashPayment
결제수단을 현금으로 고정해 승인을 요청해요. requestPayment의 결제수단 선택 화면을 건너뛰고 바로 현금 결제로 진입해요. 현금영수증 발행도 이 요청 안에서 함께 처리해요.
이미 끝난 결제에 현금영수증만 추가로 발행하는 API가 아니에요
현금영수증 발행은 현금 결제 승인과 같은 요청 안에서 이뤄져요. 프론트 플러그인 SDK에는 이미 승인된 결제 건을 참조해 현금영수증만 따로 발행하는 API가 없어요.
그래서 현금영수증을 발행하지 않고(isCashReceipt: false) 끝난 현금 결제는, 나중에 그 건에 대해 발행할 수 없어요. 현금 결제 취소가 발행된 현금영수증 승인을 취소하는 방식으로 동작하는 것도 같은 이유예요.
결제가 끝난 뒤에 고객이 현금영수증을 요청하는 상황의 처리 방법은 개발자 포럼에 문의해 주세요. 고객 정보와 결제정보는 공개 글에 포함하지 마세요.
- 개발자 포럼: https://forum.tossplace.com
Parameters
| 파라미터 | 타입 | 필수 | 기본값 | 설명 |
|---|---|---|---|---|
paymentKey | string | ✓ | - | 중복되지 않는 고유한 결제 식별자 |
tax | number | ✓ | - | 세금 |
supplyValue | number | ✓ | - | 공급가액 |
taxExemptValue | number | - | 면세 금액 | |
tip | number | ✓ | - | 봉사료 |
installment | number | 0 | 할부 개월 | |
tid | string | - | 결제 TID (CAT ID) | |
timeoutMs | number | 60000 | 타임아웃 (ms 단위) | |
localeCode | 'ko' | 'en' | 'ko' | 언어 설정 | |
identityNumber | string | - | 현금영수증 번호 (휴대폰번호 또는 사업자번호) | |
issuerType | 'CONSUMER' | 'BUSINESS' | - | 소득 구분 (소득공제 / 지출증빙) |
identityNumber와 issuerType은 함께 전달해야 해요
두 값을 모두 전달해야 입력 화면 없이 바로 승인을 진행해요. 하나라도 빠지면 프론트 단말기에 현금영수증 번호 입력 화면이 떠서 고객이 직접 입력해요.
POS가 미리 받은 번호로 입력 화면 없이 진행하려면 반드시 둘 다 넣어주세요. 반대로 고객이 단말기에서 직접 입력하게 하려면 둘 다 생략하면 돼요.
입력 화면에서 발급안하기를 선택했을 때의 동작은 프론트 설정 > 결제정보 > 현금영수증 자진 발급 항상 적용 설정에 따라 달라져요.
- 설정이 꺼져 있으면 현금영수증 없이 현금 결제만 끝나고, 응답의
cash.isCashReceipt가false로 내려와요. - 설정이 켜져 있으면 금액과 관계없이 자진발급을 요청해요. 발급에 성공하면
cash.isCashReceipt와cash.cashReceipt.isSelfIssuance가 모두true로 내려와요.
이 설정을 켜도 번호 입력 화면은 표시돼요. 발급안하기를 선택했을 때 자진발급 여부를 결정하는 설정이에요.
현금영수증 번호 형식
identityNumber는 숫자만 인식해요.010-1234-5678처럼 하이픈을 넣어도 자동으로 제거돼요.- 휴대폰번호는
010이면 뒤에 4자리·4자리,011·016·017·018·019면 3~4자리·4자리를 받아요. 사업자번호는 검증 규칙까지 통과하는 10자리예요. 자릿수만 맞고 검증에 실패하는 번호는 사업자번호로 인식하지 않아요. - 두 형식 중 어느 쪽에도 맞지 않는 값을 넣으면 오류 없이 휴대폰번호로 처리돼요. 잘못된 번호로 발행되지 않도록 POS에서 먼저 검증해주세요.
issuerType은 전달한 값을 그대로 사용해요. 번호 형식과 어긋나도 교정하지 않으니, 사업자번호에'CONSUMER'를 넣는 것처럼 짝이 맞지 않는 조합이 되지 않도록 번호와 함께 검증해주세요.
Example
js
/**
* 현금 결제 요청
* @param {Object} params 현금 결제 요청 파라미터
* @returns {Object} 결제 결과
*/
const price = 10000;
const tax = Math.floor(price / 11);
const supplyValue = price - tax;
const result = await sdk.payment.requestCashPayment({
paymentKey: "cashPaymentKey",
tax,
supplyValue,
taxExemptValue: 0, // 면세 금액
tip: 0,
timeoutMs: 60000,
localeCode: "ko", // "ko" or "en" default "ko"
identityNumber: "01000000000",
issuerType: "CONSUMER", // identityNumber와 함께 넣어야 입력 화면을 건너뛰어요
});
if (result.type === "CANCELED" || result.type === "TIMEOUT") {
return;
}
console.log(result.response.cash);Response
requestPayment Response의 현금 영수증과 같아요. paymentMethod는 항상 'CASH'이고, 현금영수증 발급 여부에 따라 cash 안의 필드가 달라져요.
issuanceType은 전달한 번호 형식에 따라 정해져요. 휴대폰번호면 'PHONE', 사업자번호면 'BUSINESS_NUMBER'예요. 'CARD'는 고객이 단말기에서 현금영수증 카드를 사용했을 때만 내려와요.
isSelfIssuance는 따로 전달하는 값이 아니라 identityNumber에서 파생돼요. 자진발급 번호(0100001234)로 발행하면 true, 그 외에는 false예요.
canCancelPayment
진행 중인 통합결제창을 cancelPayment로 닫을 수 있는지 확인해요. 결제 상태를 변경하지 않으므로 여러 번 호출할 수 있어요.
Parameters
파라미터가 없어요.
Response
Promise<{ canCancel: boolean }>을 반환해요.
| 필드 | 타입 | 설명 |
|---|---|---|
canCancel | boolean | 결제창을 닫을 수 있으면 true, 닫을 수 없으면 false예요. |
다음 경우에는 canCancel이 false예요.
- VAN 승인 중일 때
- 승인이 끝난 완료 화면일 때
- 결제창이 없을 때
- 프론트 앱 버전이 2.71 미만일 때
requestPayment 요청 직후 결제창이 만들어지기 전에도 잠시 false일 수 있어요. 이 경우 잠시 후 다시 확인해주세요. 확인 후 결제 상태가 바뀔 수 있으므로 실제로 닫혔는지는 cancelPayment의 canceled로 확인해요.
Example
js
/**
* 진행 중인 통합결제창을 닫을 수 있는지 확인해요.
*/
try {
const { canCancel } = await sdk.payment.canCancelPayment();
console.log("결제창 닫기 가능 여부:", canCancel);
} catch (error) {
console.error("결제창 상태 확인 중 오류가 발생했어요:", error);
}cancelPayment
진행 중인 통합결제창을 닫아요. 이미 승인된 결제를 되돌리려면 requestPaymentCancel을 사용해주세요.
Parameters
파라미터가 없어요.
Response
Promise<{ canceled: boolean }>을 반환해요.
| 필드 | 타입 | 설명 |
|---|---|---|
canceled | boolean | 결제창을 닫았으면 true, 닫지 못했으면 false예요. |
canceled가 true이면 대기 중이던 requestPayment가 { type: "CANCELED" }를 반환해요. VAN 승인 중이거나 승인이 끝난 완료 화면일 때, 결제창이 없을 때는 닫히지 않고 false를 반환해요. 프론트 앱 버전이 2.71 미만이어도 false를 반환해요.
화면 전환은 requestPayment의 결과 분기에서 처리해주세요
cancelPayment 응답과 requestPayment의 CANCELED 응답은 도착 순서를 보장하지 않아요. 두 응답을 받는 곳에서 각각 화면을 전환하면 화면이 두 번 바뀔 수 있어요. 화면 전환은 requestPayment의 결과 분기 한 곳에서만 처리해주세요.
Example
통합결제창이 열린 상태에서 파트너 POS의 취소 요청을 받으면 호출해요.
js
/**
* 진행 중인 통합결제창을 닫아요.
* 화면 전환은 대기 중인 requestPayment의 결과 분기에서 처리해요.
*/
try {
const { canceled } = await sdk.payment.cancelPayment();
if (!canceled) {
console.log("현재 결제창을 닫을 수 없어요.");
}
} catch (error) {
console.error("결제창 닫기 중 오류가 발생했어요:", error);
}requestPaymentCancel
승인된 결제에 대한 환불을 요청해요.
현금 결제 취소는 현금영수증 승인을 취소해요
현금 결제 취소는 현금영수증 승인을 취소하는 방식으로 동작해요. 그래서 현금영수증을 발행하지 않은 현금 결제는 취소할 대상이 없어요.
Parameters
| 파라미터 | 타입 | 필수 | 기본값 | 설명 |
|---|---|---|---|---|
paymentKey | string | ✓ | - | 원본 결제에 전달했던 paymentKey |
paymentMethod | 'CARD' | 'CASH' | 'BARCODE' | ✓ | - | 원본 결제 수단 |
tax | number | ✓ | - | 취소할 세금 |
supplyValue | number | ✓ | - | 취소할 공급가액 |
taxExemptValue | number | - | 취소할 면세 금액 | |
tip | number | ✓ | - | 취소할 봉사료 |
timestamp | number | ✓ | - | 원본 결제의 승인 시간 |
approvalNumber | string | ✓ | - | 원본 결제의 승인번호 |
installment | number | 0 | 원본 결제의 할부 개월 | |
tid | string | - | 결제 TID (CAT ID) | |
timeoutMs | number | 60000 | 타임아웃 (ms 단위) | |
localeCode | 'ko' | 'en' | 'ko' | 언어 설정 | |
extraData.vanTransactionManagementId | string | - | 알리페이/위챗페이 취소 시 필요한 값 | |
identityNumber | string | - | 원본 결제의 현금영수증 번호. 입력 화면을 건너뛰려면 issuerType과 함께 전달해요. | |
issuerType | 'CONSUMER' | 'BUSINESS' | - | 원본 결제의 소득 구분 (소득공제 / 지출증빙). 자진발급 취소 시 생략하면 'CONSUMER'로 처리해요. | |
isSelfIssuance | boolean | false | 현금영수증 자진발급 여부 | |
excludePaymentTypes | ['CASH'] | - | 제외할 결제 수단 |
현금 결제 취소도 번호를 넘기면 입력 화면을 건너뛰어요
현금 결제를 취소할 때 아래 순서로 취소할 현금영수증을 정해요.
isSelfIssuance가true면identityNumber대신 자진발급 번호(0100001234)로 바로 취소해요.issuerType은 전달한 값을 사용하고, 생략하면'CONSUMER'로 처리해요.- 자진발급 취소가 아니면
identityNumber와issuerType을 모두 전달해야 그 번호로 바로 취소해요.identityNumber는 숫자만 사용하며, 숫자를 제외한 문자를 제거한 뒤에도 번호가 남아 있어야 해요. - 위 조건에 해당하지 않으면 프론트 단말기에 현금영수증 번호 입력 화면이 떠요.
원본 결제를 자진발급으로 발행했다면 isSelfIssuance에 true를 넣어주세요. 승인 응답의 cash.cashReceipt.isSelfIssuance 값을 그대로 쓰면 돼요.
Example
js
/**
* 결제 취소 요청
* @param {Object} params 결제 취소 요청 파라미터
* @returns {Object} 취소 결과
*/
const price = 10000;
const tax = Math.floor(price / 11);
const supplyValue = price - tax;
const result = await sdk.payment.requestPaymentCancel({
paymentKey: "결제했던 paymentKey",
paymentMethod: "CARD", // "CASH" 또는 "BARCODE"
tax,
supplyValue,
taxExemptValue: 0, // 원거래의 면세 금액
tip: 0,
timestamp: 1723628943812, // 승인 시 timestamp
approvalNumber: "000000000", // 승인 시 approvalNumber
installment: 0, // 승인 시 installment
timeoutMs: 60000,
extraData: {
vanTransactionManagementId: string, // 알리/위챗 승인 시 값
},
isSelfIssuance: false, // 현금영수증 자진발급여부
localeCode: "ko",
});
if (result.type === "CANCELED" || result.type === "TIMEOUT") {
return;
}
switch (result.response.paymentMethod) {
case "CARD":
console.log(result.response.card);
break;
case "CASH":
console.log(result.response.cash);
break;
case "BARCODE":
console.log(result.response.barcode);
break;
}Response
requestPayment의 Response와 동일해요. 원본 결제 수단에 따라 paymentMethod가 'CARD', 'CASH', 'BARCODE' 중 하나로 와요.
requestCardlessPaymentCancel
승인된 카드 결제를 카드 인식 없이 취소해요(무카드 취소). VAN 거래 일련번호(vanTransactionKey)로 취소를 진행하며, 프론트 단말기에 취소 화면이 표시되지 않고 백그라운드로 처리돼요.
참고
- 지원 VAN: NICE
- 지원 결제수단: 카드(
CARD)
Parameters
requestPaymentCancel의 파라미터에 vanTransactionKey가 추가된 형태예요.
| 파라미터 | 타입 | 필수 | 기본값 | 설명 |
|---|---|---|---|---|
paymentKey | string | ✓ | - | 원본 결제에 전달했던 paymentKey |
paymentMethod | 'CARD' | ✓ | - | 원본 결제 수단 (현재 카드만 지원) |
tax | number | ✓ | - | 취소할 세금 |
supplyValue | number | ✓ | - | 취소할 공급가액 |
taxExemptValue | number | - | 취소할 면세 금액 | |
tip | number | ✓ | - | 취소할 봉사료 |
timestamp | number | ✓ | - | 원본 결제의 승인 시간 |
approvalNumber | string | ✓ | - | 원본 결제의 승인번호 |
vanTransactionKey | string | ✓ | - | 원본 결제 응답의 vanTransactionKey 값 |
installment | number | 0 | 원본 결제의 할부 개월 | |
tid | string | - | 결제 TID (CAT ID) | |
timeoutMs | number | 60000 | 타임아웃 (ms 단위) | |
localeCode | 'ko' | 'en' | 'ko' | 언어 설정 |
Example
js
/**
* 무카드 취소 요청
* @param {Object} params 무카드 취소 요청 파라미터
* @returns {Object} 취소 결과
*/
const price = 10000;
const tax = Math.floor(price / 11);
const supplyValue = price - tax;
const result = await sdk.payment.requestCardlessPaymentCancel({
paymentKey: "결제했던 paymentKey",
paymentMethod: "CARD",
tax,
supplyValue,
taxExemptValue: 0, // 원거래의 면세 금액
tip: 0,
timestamp: 1723628943812, // 승인 시 timestamp
approvalNumber: "000000000", // 승인 시 approvalNumber
vanTransactionKey: "000000000000", // 승인 시 전달받은 VAN 거래 일련번호
installment: 0, // 승인 시 installment
timeoutMs: 60000,
localeCode: "ko",
});
if (result.type === "CANCELED" || result.type === "TIMEOUT") {
return;
}
console.log(result.response.card);Response
js
{
type: 'SUCCESS',
response: {
paymentMethod: 'CARD',
tid?: string, // 결제 TID (CAT ID)
vanTransactionKey: string, // VAN 거래 일련번호
card: {
van: 'NICE' | 'KIS' | 'KOVAN' | 'KFTC' | 'SMARTRO' | 'KSNET' | 'DAOU' | 'NICEPAY',
timestamp: number, // 승인 시간
approvalNumber: string, // 승인번호
acquirerName: string, // 매입사 명
acquirerCode: string, // 매입사 코드
issuerName: string, // 발급사 명
issuerCode: string, // 발급사 코드
cardType: 'CREDIT_CARD' | 'CHECK_CARD' | 'PREPAID_CARD',
balance: number, // 선불카드 잔액
installment: number, // 할부 개월
shopCode?: string, // 가맹점 번호 (숫자 9자리)
maskedCardNumber?: string, // 마스킹된 카드 번호 (bin 8자리만 표시)
},
},
}getPayment
최근 승인 결과를 조회해요. requestPayment의 데이터를 유실했을 때, 같은 paymentKey로 단말 로컬 캐시에 저장된 승인 결과를 다시 읽어와요.
참고
- 용도:
requestPayment의 결과 복구용 API예요. WebView reload, 페이지 이동, JS 런타임 재초기화 등으로 데이터를 유실했을 경우 사용해요. - 단말기 기반 동작: 결제를 요청한 단말기에서만 조회할 수 있어요. 다른 단말기나 서버에서는 조회할 수 없어요.
- 캐시 정책: TTL 14일, 최대 1,000건이 저장돼요.
SUCCESS결과만 캐시되며,CANCELED,TIMEOUT, 승인 실패 결과는 캐시되지 않아요.
Parameters
| 파라미터 | 타입 | 필수 | 기본값 | 설명 |
|---|---|---|---|---|
paymentKey | string | ✓ | - | 승인 결과를 조회할 결제 식별자 |
Example
js
const result = await sdk.payment.getPayment({
paymentKey: "paymentKey",
});
if (result.type === "CANCELED" || result.type === "TIMEOUT") {
return;
}
switch (result.response.paymentMethod) {
case "CARD":
console.log(result.response.card);
break;
case "CASH":
console.log(result.response.cash);
break;
case "BARCODE":
console.log(result.response.barcode);
break;
}Response
requestPayment의 Response와 동일해요.
Error
| 에러 메시지 | 설명 |
|---|---|
INVALID_PARAMS | paymentKey가 누락되었거나 빈 문자열인 경우 |
PAYMENT_NOT_FOUND | 캐시된 승인 결과가 없는 경우. 아직 캐시가 생성되지 않았거나, 결과가 TIMEOUT, 승인 실패였거나, 캐시 TTL(14일)이 만료된 경우에 발생해요. |
getPaymentCancel
최근 취소 결과를 조회해요. requestPaymentCancel의 데이터를 유실했을 때, 같은 paymentKey로 단말 로컬 캐시에 저장된 취소 결과를 다시 읽어와요.
참고
- 용도:
requestPaymentCancel의 결과 복구용 API예요. WebView reload, 페이지 이동, JS 런타임 재초기화 등으로 데이터를 유실했을 경우 사용해요. - 단말기 기반 동작: 취소를 요청한 단말기에서만 조회할 수 있어요. 다른 단말기나 서버에서는 조회할 수 없어요.
- 캐시 정책: TTL 14일, 최대 1,000건이 저장돼요.
SUCCESS결과만 캐시되며,CANCELED,TIMEOUT, 승인 취소 실패 결과는 캐시되지 않아요. - 승인 캐시와 독립: 같은
paymentKey에 대해 승인 결과와 취소 결과는 별도로 저장돼요. 취소 성공 이후에도getPayment는 기존 승인 결과를 반환할 수 있어요.
Parameters
| 파라미터 | 타입 | 필수 | 기본값 | 설명 |
|---|---|---|---|---|
paymentKey | string | ✓ | - | 취소 결과를 조회할 결제 식별자 |
Example
js
const result = await sdk.payment.getPaymentCancel({
paymentKey: "paymentKey",
});
if (result.type === "CANCELED" || result.type === "TIMEOUT") {
return;
}
switch (result.response.paymentMethod) {
case "CARD":
console.log(result.response.card);
break;
case "CASH":
console.log(result.response.cash);
break;
case "BARCODE":
console.log(result.response.barcode);
break;
}Response
requestPaymentCancel의 Response와 동일해요.
Error
| 에러 메시지 | 설명 |
|---|---|
INVALID_PARAMS | paymentKey가 누락되었거나 빈 문자열인 경우 |
PAYMENT_NOT_FOUND | 캐시된 취소 결과가 없는 경우. 아직 캐시가 생성되지 않았거나, 결과가 TIMEOUT, 승인 취소 실패였거나, 캐시 TTL(14일)이 만료된 경우에 발생해요. |
사용 예시
결제 관리 클래스
js
class PaymentManager {
/**
* 통합 결제 요청
* @param {number} amount 통합 결제 금액
* @param {string} paymentKey 통합 결제 식별자
*/
async requestPayment(amount, paymentKey) {
const tax = Math.floor(amount / 11);
const supplyValue = amount - tax;
try {
const result = await sdk.payment.requestPayment({
paymentKey,
tax,
supplyValue,
tip: 0,
timeoutMs: 60000,
localeCode: "ko",
});
if (result.type === "SUCCESS") {
return this.handlePaymentSuccess(result.response);
} else {
return this.handlePaymentFailure(result.type);
}
} catch (error) {
console.error("결제 요청 실패:", error);
throw error;
}
}
/**
* 결제 취소 요청
* @param {string} paymentKey 결제 식별자
* @param {string} paymentMethod 결제 수단
* @param {number} amount 취소 금액
* @param {Object} originalPayment 원본 결제 정보
*/
async requestPaymentCancel(
paymentKey,
paymentMethod,
amount,
originalPayment,
) {
const tax = Math.floor(amount / 11);
const supplyValue = amount - tax;
try {
const result = await sdk.payment.requestPaymentCancel({
paymentKey,
paymentMethod,
tax,
supplyValue,
tip: 0,
timestamp: originalPayment.timestamp,
approvalNumber: originalPayment.approvalNumber,
installment: originalPayment.installment,
timeoutMs: 60000,
});
if (result.type === "SUCCESS") {
return this.handleCancelSuccess(result.response);
} else {
return this.handleCancelFailure(result.type);
}
} catch (error) {
console.error("결제 취소 실패:", error);
throw error;
}
}
/**
* 간편결제 요청
* @param {number} amount 결제 금액
* @param {string} paymentKey 결제 식별자
*/
async requestBarcodePayment(amount, paymentKey) {
const tax = Math.floor(amount / 11);
const supplyValue = amount - tax;
try {
const result = await sdk.payment.requestBarcodePayment({
paymentKey,
tax,
supplyValue,
tip: 0,
timeoutMs: 60000,
localeCode: "ko",
});
if (result.type === "SUCCESS") {
return this.handleBarcodePaymentSuccess(result.response);
} else {
return this.handlePaymentFailure(result.type);
}
} catch (error) {
console.error("간편결제 요청 실패:", error);
throw error;
}
}
/**
* 현금 결제 요청
* @param {number} amount 결제 금액
* @param {string} paymentKey 결제 식별자
*/
async requestCashPayment(amount, paymentKey) {
const tax = Math.floor(amount / 11);
const supplyValue = amount - tax;
try {
const result = await sdk.payment.requestCashPayment({
paymentKey,
tax,
supplyValue,
tip: 0,
timeoutMs: 60000,
localeCode: "ko",
identityNumber: "01000000000",
issuerType: "CONSUMER",
});
if (result.type === "SUCCESS") {
return this.handleCashPaymentSuccess(result.response);
} else {
return this.handlePaymentFailure(result.type);
}
} catch (error) {
console.error("현금 결제 요청 실패:", error);
throw error;
}
}
handlePaymentSuccess(response) {
// 결제 성공 처리
console.log("결제 성공:", response);
}
handleBarcodePaymentSuccess(response) {
// 간편결제 성공 처리
console.log("간편결제 성공:", response);
}
handleCashPaymentSuccess(response) {
// 현금 결제 성공 처리
console.log("현금 결제 성공:", response);
}
handlePaymentFailure(type) {
// 결제 실패 처리
console.log("결제 실패:", type);
}
handleCancelSuccess(response) {
// 취소 성공 처리
console.log("취소 성공:", response);
}
handleCancelFailure(type) {
// 취소 실패 처리
console.log("취소 실패:", type);
}
}
// 사용 예시
async function processPayment() {
const paymentManager = new PaymentManager();
// 통합 결제 요청
await paymentManager.requestPayment(10000, "payment-123");
// 바코드 간편결제 요청
await paymentManager.requestBarcodePayment(10000, "barcode-payment-456");
// 현금 결제 요청
await paymentManager.requestCashPayment(10000, "cash-payment-789");
// 결제 취소
await paymentManager.requestPaymentCancel("payment-123", "CARD", 10000, {
timestamp: 1723628943812,
approvalNumber: "000000000",
installment: 0,
});
}