유효한 빌링키인지 조회해요. 빌링키가 유효하지 않으면 결제를 요청할 수 없으며, 처음부터 다시 발급받아야 해요.
핵심 요약
- 최초 발급 직후에는
receipt_id로 조회해billing_key를 확인해요. - 이미 저장된 빌링키의 상태를 확인할 때는
billing_key로 조회해요. - 조회 응답의 카드/계좌 정보는 사용자 화면 표시용으로만 저장해야 해요.
- 유효하지 않은 빌링키는 재사용하지 말고 다시 발급받아요.
조회 기준
| 상황 | 조회 키 | 다음 단계 |
|---|---|---|
| 프론트엔드 발급 직후 | receipt_id |
billing_key를 DB에 저장 |
| 저장된 빌링키 상태 확인 | billing_key |
결제 요청 가능 여부 판단 |
| 카드 변경 후 새 빌링키 확인 | 새 발급 receipt_id |
기존 빌링키 revoked, 새 빌링키 active |
receipt_id로 조회
빌링키 발급 시 받은 영수증 ID로 조회해요. 이 엔드포인트는 발급 요청(Receipt) 기준으로 응답을 만들어요.
https://api.bootpay.co.kr/v2/subscribe/billing_key/:receipt_idBasic Auth| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
receipt_id |
String | 필수 | 빌링키 발급 시 받은 영수증 ID (URL 파라미터) |
/v2/subscribe/billing_key/:id는 메서드에 따라 :id에 넣는 값이 달라요. GET은 발급 시 받은 receipt_id를 넣고, DELETE(빌링키 삭제)는 발급된 billing_key를 넣어야 해요.
billing_key로 조회
이미 발급받은 빌링키로 조회해요. 이 엔드포인트는 빌링키(BillingKey) 기준으로 응답을 만들어요.
https://api.bootpay.co.kr/v2/billing_key/:billing_keyBasic Auth| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
billing_key |
String | 필수 | 부트페이에서 부여한 빌링키 (URL 파라미터) |
최초 발급 시에는 billing_key 값을 알 수 없으므로, receipt_id로 조회해야 해요.
두 엔드포인트의 응답 차이
같은 빌링키를 가리키더라도 두 엔드포인트가 내려주는 필드는 서로 달라요.
| 항목 | receipt_id 조회 |
billing_key 조회 |
|---|---|---|
| 기준 | 발급 요청(Receipt) | 빌링키(BillingKey) |
receipt_id |
있음 | 없음 |
subscription_id |
있음 | 없음 |
status_locale |
있음 ("빌링키발급완료") |
없음 |
status |
발급 진행 상태 — 11이 발급완료 |
빌링키 사용 여부 — 1(사용가능) / 0(사용불가) |
pg · method · method_symbol |
있음 | 있음 |
method_origin · method_origin_symbol |
있음 | 없음 |
version · revoked_at |
없음 | 있음 |
sandbox |
API 버전 3부터만 | 항상 있음 |
published_at |
있음 | 있음 |
billing_key · billing_data · billing_expire_at |
있음 | 있음 |
두 응답 모두 status 키를 쓰지만 의미가 달라요. receipt_id 조회의 11은 "빌링키 발급이 완료됨"이고, billing_key 조회의 1은 "이 빌링키를 지금 결제에 쓸 수 있음"이에요. 저장된 빌링키가 아직 살아 있는지 판단할 때는 billing_key 조회의 status === 1을 봐야 해요.
코드 예제
import { Bootpay } from '@bootpay/backend-js'
Bootpay.setConfiguration({
client_key: '[ Client Key ]',
secret_key: '[ Secret Key ]'
})
try {
const response = await Bootpay.lookupSubscribeBillingKey(
'[ receipt_id ]'
)
// billing_key를 데이터베이스에 저장
console.log(response)
} catch (e) {
console.log(e)
}javascriptfrom bootpay_backend import BootpayBackend
bootpay = BootpayBackend(client_key='CLIENT_KEY', secret_key='SECRET_KEY')
response = bootpay.lookup_subscribe_billing_key('[ receipt_id ]')
print(response)pythonuse Bootpay\ServerPhp\BootpayApi;
BootpayApi::setClientKeyConfiguration('CLIENT_KEY', 'SECRET_KEY');
$response = BootpayApi::lookupSubscribeBillingKey('[ receipt_id ]');
print_r($response);phpimport kr.co.bootpay.pg.Bootpay;
Bootpay bootpay = Bootpay.withClientKey("CLIENT_KEY", "SECRET_KEY");
var response = bootpay.lookupBillingKey("[ receipt_id ]");
System.out.println(response);javabootpay = Bootpay::Api.new(client_key: 'CLIENT_KEY', secret_key: 'SECRET_KEY')
response = bootpay.request(
method: :get,
uri: 'subscribe/billing_key/[ receipt_id ]'
)
puts response.datarubyimport "github.com/bootpay/backend-go/v2"
api := bootpay.NewAPIWithClientKey("CLIENT_KEY", "SECRET_KEY", nil, "")
response, err := api.LookupBillingKey("[ receipt_id ]")
if err != nil {
log.Fatal(err)
}
fmt.Println(response)gousing Bootpay;
var bootpay = BootpayApi.WithClientKey("CLIENT_KEY", "SECRET_KEY");
var response = await bootpay.LookupBillingKey("[ receipt_id ]");
Console.WriteLine(response);csharp응답
빌링키 조회 결과는 status로 발급 상태를 확인해요. receipt_id로 조회하면 status가 Number 11일 때 빌링키 발급이 완료된 상태예요.
{
"receipt_id": "6261104e1fc19202e6f9420e",
"subscription_id": "sub_1705289520000",
"gateway_url": "https://api.bootpay.co.kr/...",
"metadata": {
"user_id": "1234"
},
"pg": "나이스페이먼츠",
"method": "카드자동",
"method_symbol": "card_rebill",
"method_origin": "카드자동",
"method_origin_symbol": "card_rebill",
"published_at": "2025-01-15T14:32:00+09:00",
"requested_at": "2025-01-15T14:31:52+09:00",
"status_locale": "빌링키발급완료",
"status": 11,
"billing_key": "615d00f0197c300036b4fef5",
"billing_data": {
"card_company": "하나카드",
"card_no": "5570-****-****-1074",
"card_company_code": "046",
"card_type": 0,
"card_hash": "f5b2a..."
},
"billing_expire_at": "2027-01-01T00:00:00+09:00"
}json{
"billing_key": "615d00f0197c300036b4fef5",
"billing_data": {
"card_company": "하나카드",
"card_no": "5570-****-****-1074",
"card_company_code": "046",
"card_type": 0,
"card_hash": "f5b2a..."
},
"billing_expire_at": "2027-01-01T00:00:00+09:00",
"pg": "나이스페이먼츠",
"method": "카드자동결제",
"method_symbol": "card_rebill",
"sandbox": 0,
"version": 2,
"revoked_at": null,
"published_at": "2025-01-15T14:32:00+09:00",
"status": 1
}jsonprice를 0보다 크게 넣어 빌링키 발급과 첫 결제를 함께 요청했다면, receipt_id 조회 응답에 그 결제 건의 결제 정보가 receipt_data 객체로 함께 들어와요.
응답 파라미터
| 파라미터 | 타입 | 설명 |
|---|---|---|
| receipt_id | String | 빌링키 발급 요청의 영수증 ID (receipt_id 조회에만 포함) |
| subscription_id | String | 요청 시 넣은 가맹점 고유 구독 번호 (receipt_id 조회에만 포함) |
| pg | String | PG사명 |
| method | String | 결제수단명 |
| method_symbol | String | 결제수단 영문 심볼 |
| method_origin | String | 원 결제수단명 (receipt_id 조회에만 포함) |
| method_origin_symbol | String | 원 결제수단 영문 심볼 (receipt_id 조회에만 포함) |
| gateway_url | String | 게이트웨이 URL (receipt_id 조회에만 포함) |
| metadata | Object | 요청 시 넣은 커스텀 데이터 (receipt_id 조회에만 포함) |
| requested_at | Date | 발급 요청 시간 (ISO 8601, receipt_id 조회에만 포함) |
| published_at | Date | 빌링키 발급 시간 (ISO 8601) |
| status_locale | String | 빌링키 발급 상태 한글 ("빌링키발급완료", receipt_id 조회에만 포함) |
| status | Number | receipt_id 조회: 발급 상태(11 = 발급완료) / billing_key 조회: 사용 여부(1 = 사용가능, 0 = 사용불가) |
| billing_key | String | 빌링키 — 반드시 데이터베이스에 저장 |
| billing_data | Object | 빌링키와 연결된 카드/계좌 정보 |
| billing_data.card_company | String | 카드사명 (자동카드결제) |
| billing_data.card_no | String | 마스킹된 카드번호 (자동카드결제) |
| billing_data.card_company_code | String | PG사 정의 카드사 코드 (자동카드결제) |
| billing_data.card_type | Number | 카드 종류 (0: 신용카드, 1: 체크카드) |
| billing_data.card_hash | String | 카드번호 SHA-256 해시. KCP를 제외한 대부분의 PG(나이스페이먼츠·토스페이먼츠·이니시스·다날·웰컴페이먼츠·페이앱·키움페이·라이트페이)에서 전달돼요 |
| billing_data.bank_code | String | 은행코드 3자리 (자동계좌이체) |
| billing_data.bank_name | String | 은행명 (자동계좌이체) |
| billing_data.bank_account | String | 마스킹된 계좌번호 (자동계좌이체) |
| billing_data.username | String | 계좌주명 (자동계좌이체) |
| billing_expire_at | Date | 빌링키 만료일 (ISO 8601) |
| sandbox | Number | 샌드박스 여부 (billing_key 조회) |
| version | Number | 빌링키 데이터 버전 (billing_key 조회에만 포함) |
| revoked_at | Date | 빌링키 삭제 시각, 삭제 전이면 null (billing_key 조회에만 포함) |
| receipt_data | Object | 발급과 함께 결제까지 진행한 경우의 결제 정보 (receipt_id 조회, price > 0일 때만) |
billing_expire_at은 빌링키 토큰 자체의 만료일이고, 어떻게 발급했느냐에 따라 계산 방식이 달라요.
- 백엔드 REST 카드 발급 — 입력한 카드 유효기간(년·월)의 1일 + 1개월. 즉 카드 유효기간이 끝나는 시점과 사실상 같아요.
- 계좌 자동이체 빌링키 —
2099-12-31T23:59:59+09:00. 계좌에는 유효기간 개념이 없어서 사실상 만료가 없는 값이에요. - 결제창 발급 중 PG가 만료일을 주지 않는 경우 — 발급일 + 3년으로 채워요. 이 값은 카드의 실제 유효기간과 별개예요.
만료된 빌링키로 결제·삭제를 요청하면 SUBSCRIBE_BK_EXPIRED(2310)가 나와요. 다만 카드가 재발급되거나 분실 신고되면 billing_expire_at이 남아 있어도 결제는 실패하므로, 결제 실패 응답을 받았을 때 고객에게 결제수단 갱신을 안내하는 흐름을 함께 둬야 해요.
에러 코드
인증·권한 관련 에러는 에러 코드표를 참고해요.
| 코드 | 메시지 | 대처 방법 |
|---|---|---|
RC_NOT_FOUND (2000) |
영수증 정보를 찾지 못했다 | receipt_id로 조회할 때 존재하지 않거나 다른 프로젝트의 영수증이면 SUBSCRIBE_BK_NOT_FOUND보다 먼저 이 코드가 나와요. receipt_id와 사용 중인 Application 키를 확인해요 |
SUBSCRIBE_BK_NOT_FOUND (2309) |
빌링키 발급 내역을 찾지 못했다 | receipt_id 또는 billing_key가 올바른지 확인해요 |
SUBSCRIBE_NOT_SUCCESS (2308) |
빌링키 발급이 완료된 건이 아니다 | 빌링키 발급이 정상 완료되었는지 확인해요 |
RC_NOT_SUBSCRIBE (2057) |
정기결제 요청 정보가 아니다 | 정기결제 관련 영수증인지 확인해요 |
