✅ 자동결제는 다른 이름으로 빌링, 또는 정기결제로 불리는 결제 방식입니다. 카드 등록창에서 고객의 카드를 처음 한 번 등록하고 나면, 이후 별도의 고객 인증 없이 간편하게 결제를 요청할 수 있습니다.
✅ 토스페이먼츠 결제창 SDK로 자동결제(빌링)를 연동할 수 있습니다.
✅ 만약 정기적으로 발생하는 결제가 아니라 원하는 시점에 결제를 내고 싶다면 자체 간편결제 서비스인 브랜드페이를 연동하세요.
토스페이먼츠에 회원가입하기 전이라면, 문서 테스트 키로 자동결제를 연동하세요.
토스페이먼츠에 회원가입했다면, 로그인 후 내 테스트 키로 자동결제를 연동하고 개발자센터에서 테스트 결제내역을 확인하세요. 회원가입 후 자동결제를 추가로 계약해야 내 테스트 키로 테스트 할 수 있습니다.
// 문서 테스트 키
// 토스페이먼츠에 회원 가입하기 전이라면 아래 키로 자동결제를 연동하세요.
const clientKey = 'test_ck_D5GePWvyJnrK0W0k6q8gLzN97Eoq'
const secretKey = 'test_sk_zXLkKEypNArWmo50nX3lmeaxYG5R'
// 내 테스트 키
// 토스페이먼츠에 회원 가입하고 자동결제를 추가 계약한 뒤 아래 키로 자동결제를 연동하세요.
// 로그인하면 문서의 API 키가 모두 내 테스트 키로 변경됩니다.
const clientKey = 'test_ck_D5GePWvyJnrK0W0k6q8gLzN97Eoq'
const secretKey = 'test_sk_zXLkKEypNArWmo50nX3lmeaxYG5R'
자동결제는 추가 계약 후 테스트 및 라이브 환경에서 사용할 수 있습니다. 추가 계약을 하고 싶다면 토스페이먼츠 고객센터(1544-7772, support@tosspayments.com)로 문의해주세요.
큰 흐름은 다음과 같습니다.
- 카드 등록창 호출 (Client): SDK로 카드 등록창을 띄우고 고객의 카드 정보를 인증, 등록하세요.
- 빌링키 발급 API 요청 (Server): API로 빌링키를 발급하고 데이터베이스에 저장하세요.
- 빌링 결제 승인 요청 (Server): API로 발급한 빌링키로 원하는 주기, 시점에 자동결제를 실행하세요. 스케줄링 기능은 직접 구현해야 합니다.
이제 각 단계를 자세히 알아볼게요.
자동결제를 실행하려면 먼저 고객의 카드를 등록해서 빌링키를 발급해야 합니다. 아래 예제 코드를 실행하면 다음과 같은 카드 등록창을 띄울 수 있습니다.
<head>
<title>결제하기</title>
<meta charset="utf-8" />
<!-- 토스페이먼츠 결제창 SDK 추가 -->
<script src="https://js.tosspayments.com/v1/payment"></script>
</head>
<body>
<script>
// ------ 클라이언트 키로 객체 초기화 ------
var clientKey = 'test_ck_D5GePWvyJnrK0W0k6q8gLzN97Eoq'
var tossPayments = TossPayments(clientKey)
tossPayments.requestBillingAuth('카드', { // 결제수단 파라미터 (자동결제는 카드만 지원합니다.)
// 결제 정보 파라미터
customerKey: '', // 고객 ID로 상점에서 만들어야 합니다. 빌링키와 매핑됩니다. 자세한 파라미터 설명은 파라미터 설명을 참고하세요: https://docs.tosspayments.com/reference/js-sdk#결제-정보-5
successUrl: "https://my-store.com/success", // 카드 등록에 성공하면 이동하는 페이지(직접 만들어주세요)
failUrl: "https://my-store.com/fail", // 카드 등록에 실패하면 이동하는 페이지(직접 만들어주세요)
})
.catch(function (error) {
if (error.code === 'USER_CANCEL') {
// 결제 고객이 결제창을 닫았을 때 에러 처리
}
})
</script>
</body>
SDK를 추가한 뒤 클라이언트 키를 사용해 객체를 초기화합니다. 초기화된 객체로 requestBillingAuth('카드')
를 실행하면 카드 등록창이 뜹니다.
고객이 카드 등록창에 카드 정보를 입력하고 휴대폰 본인인증을 성공적으로 마치면 successUrl
로 이동합니다. successUrl
에는 쿼리 파라미터가 포함되어 있습니다. 이 파라미터를 이용해 빌링키를 발급 받습니다.
테스트 환경에서는 본인인증 문자가 발송되지 않습니다. 본인인증창이 뜨면 인증번호로
000000
을 입력하세요.테스트 환경에서는 카드 번호의 앞 여섯 자리(BIN 번호)만 유효해도 자동결제가 등록됩니다. 라이브 환경에서는 전체 카드 번호가 유효해야 등록됩니다.
해외카드, 해외결제는 지원하지 않습니다.
자동결제에 사용할 카드 정보를 등록할 카드 등록창을 띄울 수 있는 메서드예요. 카드 등록창을 띄우려면 파라미터에 카드
, 결제 정보를 추가해야 해요.
1️⃣ 현재 자동결제 결제수단은 국내에서 발급한 카드만 지원해요. 그래서 첫 번째 파라미터는 항상 카드
로 고정되어 있어요.
2️⃣ 결제 정보는 두 번째 파라미터로 추가하세요. 고객을 특정하는 customerKey
는 필수 파라미터에요. successUrl
과 failUrl
은 카드 등록에 성공하거나 실패했을 때 이동하는 페이지에요. customerKey
와 이동할 페이지는 직접 만들어야 해요. 파라미터에 대한 자세한 설명은 JavaScript SDK 레퍼런스를 참고하세요.
카드 등록 요청 결과를 확인할 차례에요. 카드 등록 요청이 성공하면 requestBillingAuth()
의 파라미터로 설정했던 (successUrl
)을 통해 빌링키 요청 성공 페이지로 이동합니다. 성공 리다이렉트 URL을 나타내는 success
뒤에 customerKey
, authKey
두 가지 쿼리 파라미터가 들어있습니다.
https://my-store.com/success?customerKey={CUSTOMER_KEY}&authKey={AUTH_KEY}
customerKey
: 상점에서 만든 고객의 고유 ID입니다.authKey
: 빌링키를 발급할 때 사용하는 일회성 인증 키입니다. 최대 길이는 300자입니다.
받은 쿼리 파라미터를 이용해 빌링키 발급 API를 호출할 수 있습니다.
requestBillingAuth()
의 파라미터로 설정했던 customerKey
값과 리다이렉트 URL에 있는 customerKey
값이 같은지 확인해보세요. 값이 같다면 빌링키를 발급할 준비가 되었습니다.
카드 등록 요청이 실패하면 다음과 같이 failUrl
로 이동합니다. 에러 목록을 확인하세요.
https://my-store.com/fail?code={ERROR_CODE}&message={ERROR_MESSAGE}&orderId={ORDER_ID}
이제 빌링키를 발급할 차례예요. 고객이 등록한 카드 정보는 저장할 수 없기 때문에 암호화해서 결제를 실행할 때 대신 사용합니다.
먼저 API 인증을 위해 아래와 같이 인증 헤더 값을 만듭니다.
시크릿 키 뒤에 :
을 추가하고 base64로 인코딩합니다. :
을 빠트리지 않도록 주의하세요.
base64('test_sk_zXLkKEypNArWmo50nX3lmeaxYG5R:')
─────────────────┬───────────────── ┬
secretKey :
발급받은 시크릿 키 콜론
아래 명령어를 터미널에서 실행하면 인코딩된 값을 얻을 수 있습니다.
echo -n 'test_sk_zXLkKEypNArWmo50nX3lmeaxYG5R:' | base64
인코딩된 값을 Basic 인증 헤더에 넣고 요청 본문도 추가하세요. 앞 단계에서 리다이렉트 URL로 받은 authKey
, customerKey
값을 카드 자동결제 빌링키 발급 요청 API의 요청 본문으로 보냅니다.
curl --request POST \
--url https://api.tosspayments.com/v1/billing/authorizations/issue \
--header 'Authorization: Basic dGVzdF9za196WExrS0V5cE5BcldtbzUwblgzbG1lYXhZRzVSOg==' \
--header 'Content-Type: application/json' \
--data '{"authKey":"EmoeWFQ-8nujSOG8Jj4le","customerKey":"BMWQ4aujbKvrJ_6qAdY8A"}'
API 호출 결과로 HTTP 200 OK
를 받으면 빌링키 발급 성공입니다. 응답 본문에 포함된 billingKey
를 이용해 자동결제가 이루어집니다. 이 값은 가맹점에서 저장해두고 원하는 시점에 이 값을 가지고 결제 승인을 요청하면 자동결제가 이루어집니다.
{
"mId": "tosspayments",
"customerKey": "",
"authenticatedAt": "2021-01-01T10:00:00+09:00",
"method": "카드",
"billingKey": "Z_t5vOvQxrj4499PeiJcjen28-V2RyqgYTwN44Rdzk0=",
"card": {
"issuerCode": "61",
"acquirerCode": "31",
"number": "43301234****123*",
"cardType": "신용",
"ownerType": "개인"
}
}
자동결제 계약이 안 되어 있는 클라이언트 키로 연동하면 발생합니다. 자동결제 계약이 되어있는 클라이언트 키를 사용하거나 토스페이먼츠 고객센터(1544-7772, support@tosspayments.com)로 문의해주세요.
빌링키를 고객을 특정하는 customerKey
와 매핑해서 서버에 저장하세요. 한 번 발급된 빌링키는 다시 조회할 수 없습니다. 저장한 키 값으로 자동결제를 요청해주세요.
빌링키의 유효기간은 빌링키와 연결된 카드 유효기간과 같습니다. 발급된 빌링키를 삭제하는 기능은 제공하지 않습니다. 발급된 빌링키가 더 이상 필요하지 않으면 데이터베이스에서 삭제하고 더 이상 사용하지 않으면 됩니다. 혹시 누군가가 빌링키 정보를 알고 있더라도 빌링키와 맵핑된 customerKey
를 모른다면 결제가 불가능합니다. 빌링키를 사용한 결제는 빌링키를 발급할 때 같이 전달된 customerKey
와 매핑이 되어있기 때문에, 결제 요청을 할 때 빌링키와 customerKey
가 같이 전달되어야 결제가 진행됩니다.
새로운 카드 정보로 빌링키를 다시 발급하세요. 별도로 빌링키를 갱신하는 과정은 없습니다.
발급한 billingKey
를 카드 자동결제 승인 API의 Path 파라미터로 추가합니다. 요청 본문에는 주문 정보와 함께 customerKey
를 포함합니다.
curl --request POST \
--url https://api.tosspayments.com/v1/billing/{billingKey} \
--header 'Authorization: Basic dGVzdF9za196WExrS0V5cE5BcldtbzUwblgzbG1lYXhZRzVSOg==' \
--header 'Content-Type: application/json' \
--data '{"customerKey":"BMWQ4aujbKvrJ_6qAdY8A","amount":4900,"orderId":"80GGp1UFAQrwnOcb5k2wE","orderName":"토스 프라임 구독","customerEmail":"customer@email.com","customerName":"박토스","taxFreeAmount":0}'
customerkey
와 매핑되지 않은 billingKey
를 사용하면 발생합니다.
토스페이먼츠에서는 자체적으로 스케줄링 기능을 제공하지 않습니다. 따라서 가맹점에서 직접 스케줄링 기능을 구현해서 원하는 주기, 시점에 결제를 실행해야 합니다.
만약 Node.js 애플리케이션에 스케줄링 로직을 추가하려면, node-cron
과 같은 패키지를 사용할 수 있습니다. 이 패키지를 사용하면 스케쥴을 정의하고 그에 따라 특정 작업을 자동으로 실행할 수 있습니다. 각 언어나 프레임워크에서 제공하는 스케줄링 기능을 사용하세요.
먼저 node-cron
패키지를 설치해야 합니다. 프로젝트의 루트 디렉토리에서 다음 명령어를 실행하세요.
npm install --save node-cron
이제 node-cron
을 사용하여 매월 1일에 자동결제를 진행하는 스케쥴러를 설정할 수 있습니다. 아래 코드는 기존 routes/index.js
파일에 스케쥴러를 추가하는 방법을 보여줍니다:
var express = require("express");
var got = require("got");
var cron = require("node-cron"); // 스케줄링을 위해 cron 잡을 수행할 수 있는 node-cron 패키지 추가
var uuid = require("uuid").v4;
var router = express.Router();
router.get("/", function (req, res) {
res.render("index");
});
router.get("/billing_confirm", function (req, res) {
// ...
}
// 매 달 1일 01:00에 스케줄링을 수행하는 cron 잡 추가
cron.schedule("0 0 1 * *", function() {
console.log("매월 1일 01:00에 결제 실행하기");
got.post("https://api.tosspayments.com/v1/billing/" + billingKey, {
headers: {
Authorization:
"Basic " + Buffer.from(secretKey + ":").toString("base64"),
"Content-Type": "application/json",
},
json: {
customerKey: "test_customer_key",
amount: 50000,
orderId: uuid(),
orderName: ‘토스 프라임 구독’,
customerEmail: "customer@email.com",
customerName: "박토스",
taxFreeAmount: 0
},
responseType: "json",
})
.then(function (response) {
console.log(response.body);
})
.catch(function (error) {
console.log(‘Error:’, error);
});
})
// ...
위 코드는 매월 1일에 billingKey
`를 사용하여 자동결제를 진행하는 스케쥴러입니다. 이러한 방식으로 스케줄링 로직을 추가하면, 매월 1일마다 자동으로 지정된 결제가 진행됩니다. 실제 서비스에서는 에러 처리, 로깅, 데이터베이스와의 통신 등이 추가로 필요할 수 있습니다.
다음 결제일에 구독을 취소한 고객의 빌링키, 고객키로 카드 자동결제 승인 API를 호출하지 않으면 됩니다.
카드 자동결제 승인 API를 호출할 때 amount
파라미터를 변경된 결제 금액으로 설정하면 됩니다.
카드 자동결제 승인 API를 호출하는 주기를 변경해주세요.
API 호출 결과로 HTTP 200 OK
를 받으면 결제 승인 성공입니다. 상태 코드와 함께 Payment 객체가 응답으로 돌아옵니다. 자동결제는 card
필드가 포함되어 있어야 합니다.
{
"mId": "tosspayments",
"version": "2022-11-16",
"paymentKey": "",
"status": "DONE",
"lastTransactionKey": "",
"orderId": "",
"orderName": "토스 프라임 구독",
"requestedAt": "2022-06-08T15:40:09+09:00",
"approvedAt": "2022-06-08T15:40:49+09:00",
"useEscrow": false,
"cultureExpense": false,
"card": {
"issuerCode": "61",
"acquirerCode": "31",
"number": "43301234****123*",
"installmentPlanMonths": 0,
"isInterestFree": false,
"interestPayer": null,
"approveNo": "00000000",
"useCardPoint": false,
"cardType": "신용",
"ownerType": "개인",
"acquireStatus": "READY",
"amount": 4900
},
"virtualAccount": null,
"transfer": null,
"mobilePhone": null,
"giftCertificate": null,
"cashReceipt": null,
"cashReceipts": null,
"discount": null,
"cancels": null,
"secret": null,
"type": "BILLING",
"easyPay": null,
"country": "KR",
"failure": null,
"isPartialCancelable": true,
"receipt": {
"url": "https://dashboard.tosspayments.com/sales-slip?transactionId=KAgfjGxIqVVXDxOiSW1wUnRWBS1dszn3DKcuhpm7mQlKP0iOdgPCKmwEdYglIHX&ref=PX"
},
"checkout": {
"url": "https://api.tosspayments.com/v1/payments//checkout"
},
"currency": "KRW",
"totalAmount": 4900,
"balanceAmount": 4900,
"suppliedAmount": 4455,
"vat": 455,
"taxFreeAmount": 0,
"taxExemptionAmount": 0,
"method": "카드"
}
✔️ 응답 객체에 card
필드가 있는지 확인하세요.
✔️ 응답 객체의 method
가 '카드'인지 확인하세요.
👉 구독결제 간단히 구현하기 콘텐츠도 참고해보세요.