Appearance
Payment API
토스 프론트에서 결제 및 환불을 처리하기 위한 API입니다. 카드, 애플페이, 삼성페이, 현금 영수증, 간편결제 등 다양한 결제 수단을 지원합니다.
주의 사항
프론트에서 카드 결제 테스트 시 실제 승인이 발생하여 주의가 필요합니다.
주의 사항
[카드 결제 테스트 시]
- 테스트 후 반드시 즉시 취소 처리 필요
- 결제 응답의
paymentKey,approvalNumber,timestamp등 승인 취소를 위한 값을 저장하여 취소에 활용
[권장 테스트 방법]
- 동작 확인 목적이라면 현금 결제 > 현금영수증 미발급으로 테스트 권장
- 실제 금전적 부담 없이 결제 플로우 확인 가능
Methods
requestPayment
통합 결제를 요청합니다.
Parameters
| 파라미터 | 타입 | 필수 | 기본값 | 설명 |
|---|---|---|---|---|
paymentKey | string | ✓ | - | 중복되지 않는 고유한 결제 식별자 |
tax | number | ✓ | - | 세금 (일반적으로 Math.floor(price / 11), 면세인 경우 0) |
supplyValue | number | ✓ | - | 공급가액 (결제 금액 - 세금) |
tip | number | ✓ | - | 봉사료 |
timeoutMs | number | 60000 | 타임아웃 (ms 단위) | |
localeCode | 'ko' | 'en' | 'ko' | 언어 설정 | |
excludePaymentTypes | ['CASH'] | - | 제외할 결제 수단 (현재 현금만 지원) |
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,
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
카드/삼성페이/애플페이 결제
js
{
type: 'SUCCESS',
response: {
paymentMethod: 'CARD',
card: {
van: string, // VAN사 코드
timestamp: number, // 승인 시간
approvalNumber: string, // 승인번호
acquirerName: string, // 매입사 명
acquirerCode: string, // 매입사 코드
issuerName: string, // 발급사 명
issuerCode: string, // 발급사 코드
cardType: string, // 카드 종류
balance: number, // 선불카드 잔액
installment: number, // 할부 개월
maskedCardNumber: string, // 마스킹된 카드 번호 (bin 8자리만 표시)
},
},
}현금 영수증
js
// 현금영수증 발급 시
{
type: 'SUCCESS',
response: {
paymentMethod: 'CASH',
cash: {
isCashReceipt: true,
cashReceipt: {
van: string, // VAN사 코드
timestamp: number, // 승인 시간
issuerType: 'CONSUMER' | 'BUSINESS', // 발급 대상 유형
issuanceType: 'PHONE' | 'BUSINESS_NUMBER' | 'CARD', // 발급 방식
identityNumber: string, // 현금영수증 번호 값
maskedIdentityNumber: string, // 현금영수증 번호 값 (일부 별표 처리)
approvalNumber: string, // 승인번호
isSelfIssuance: boolean, // 자진 발급 여부
},
},
},
}
// 현금영수증 미발급 시
{
type: 'SUCCESS',
response: {
paymentMethod: 'CASH',
cash: {
isCashReceipt: false,
},
},
}간편결제
js
{
type: 'SUCCESS',
response: {
paymentMethod: 'BARCODE',
barcode: {
van: string, // VAN사 코드
timestamp: number, // 승인 시간
approvalNumber: string, // 승인번호
acquirerName: string, // 매입사 명
acquirerCode: string, // 매입사 코드
issuerName: string, // 발급사 명
issuerCode: string, // 발급사 코드
cardType: string, // 카드 종류
balance: number, // 선불카드 잔액
installment: number, // 할부 개월
shopCode: string, // 가맹점 번호 (숫자 9자리)
},
extraData: {
vanTransactionManagementId: string, // 알리페이/위챗페이 취소 시 필요
},
},
}requestBarcodePayment
QR, 바코드를 인식하는 간편결제를 요청합니다.
Parameters
| 파라미터 | 타입 | 필수 | 기본값 | 설명 |
|---|---|---|---|---|
paymentKey | string | ✓ | - | 중복되지 않는 고유한 결제 식별자 |
tax | number | ✓ | - | 세금 |
supplyValue | number | ✓ | - | 공급가액 |
tip | number | ✓ | - | 봉사료 |
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,
tip: 0,
timeoutMs: 60000,
localeCode: "ko", // "ko" or "en" default "ko"
});
if (result.type === "CANCELED" || result.type === "TIMEOUT") {
return;
}
console.log(result.response.barcode);requestCashPayment
현금 결제 후 현금영수증 발급을 요청합니다.
Parameters
| 파라미터 | 타입 | 필수 | 기본값 | 설명 |
|---|---|---|---|---|
paymentKey | string | ✓ | - | 중복되지 않는 고유한 결제 식별자 |
tax | number | ✓ | - | 세금 |
supplyValue | number | ✓ | - | 공급가액 |
tip | number | ✓ | - | 봉사료 |
timeoutMs | number | 60000 | 타임아웃 (ms 단위) | |
localeCode | 'ko' | 'en' | 'ko' | 언어 설정 | |
identityNumber | string | - | 현금영수증 번호 (휴대폰번호 또는 사업자번호) | |
issuerType | 'CONSUMER' | 'BUSINESS' | - | 소득 구분 |
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,
tip: 0,
timeoutMs: 60000,
localeCode: "ko", // "ko" or "en" default "ko"
identityNumber: "01000000000",
});
if (result.type === "CANCELED" || result.type === "TIMEOUT") {
return;
}
console.log(result.response.cash);requestPaymentCancel
승인된 결제에 대한 환불을 요청합니다.
Parameters
| 파라미터 | 타입 | 필수 | 기본값 | 설명 |
|---|---|---|---|---|
paymentKey | string | ✓ | - | 원본 결제의 식별자 |
paymentMethod | 'CARD' | 'CASH' | 'BARCODE' | ✓ | - | 원본 결제 수단 |
tax | number | ✓ | - | 취소할 세금 |
supplyValue | number | ✓ | - | 취소할 공급가액 |
tip | number | ✓ | - | 취소할 봉사료 |
timestamp | number | ✓ | - | 원본 결제의 승인 시간 |
approvalNumber | string | ✓ | - | 원본 결제의 승인번호 |
installment | number | ✓ | - | 원본 결제의 할부 개월 |
timeoutMs | number | 60000 | 타임아웃 (ms 단위) | |
localeCode | 'ko' | 'en' | 'ko' | 언어 설정 | |
extraData.vanTransactionManagementId | string | - | 알리페이/위챗페이 취소 시 필요한 값 | |
isSelfIssuance | boolean | - | 현금영수증 자진발급 여부 | |
excludePaymentTypes | ['CASH'] | - | 제외할 결제 수단 |
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,
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;
}사용 예시
결제 관리 클래스
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",
});
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,
});
}