자동결제

빌링키 결제 요청

저장된 빌링키로 지금 결제를 요청해요.

이 문서는 발급받은 빌링키로 서버에서 결제를 요청하는 방법을 설명해요. 정기결제, 사용량 과금처럼 고객이 다시 결제창을 열지 않아도 되는 흐름을 구현할 때 사용해요.

여기서 다루는 API는 서버가 호출한 시점에 결제를 요청하는 POST /v2/subscribe/payment이에요. 미래 특정 시점에 한 번 실행할 결제는 같은 빌링키를 쓰더라도 예약결제에서 별도 예약 API로 등록해야 해요.

영상으로 보기

구독결제의 모든 것 — 배치·회차·무료체험·해지 · 16분 33초

핵심 요약

  • billing_key로 현재 시점의 결제를 요청해요.
  • 매월·매주 청구 대상 선정과 호출 시점 결정은 가맹점 스케줄러가 담당해요.
  • 이 API는 호출 즉시 1회 결제만 시도하고 자동 재시도를 하지 않아요. 잔액 부족·한도 초과 등으로 실패하면 재청구 큐와 고객 안내는 가맹점이 직접 설계해야 해요.
  • 성공 응답의 receipt_id는 결제 조회·취소·웹훅 멱등 처리의 기준이므로 반드시 저장해야 해요.
  • 미래 특정 시점에 한 번 실행하려면 이 API에 execute_at을 넣는 방식이 아니라 예약결제reserve_execute_at으로 등록해야 해요.

결제 요청 흐름

API 엔드포인트

POSThttps://api.bootpay.co.kr/v2/subscribe/paymentBasic Auth

결제 요청과 예약결제 구분

목적 API 실행 시각 파라미터
지금 결제 요청 POST /v2/subscribe/payment 없음
미래 1회 결제 예약 POST /v2/subscribe/payment/reserve reserve_execute_at

execute_at은 이 문서의 결제 요청 API에 넣는 공식 요청 파라미터가 아니에요. 예약 실행 시각은 예약 API의 reserve_execute_at으로 전달해야 해요. 일부 SDK 내부 모델이나 응답 필드에서 execute_at이라는 이름이 보이더라도, 연동할 때는 어느 엔드포인트를 호출하는지​​를 기준으로 구분해요.

요청 파라미터

파라미터 타입 필수 설명
billing_key String 필수 부트페이에서 발급한 빌링키
wallet_key String 선택 우선순위 빌링키 결제에 사용하는 지갑 키. 지정하면 billing_key 대신 이 값으로 빌링키를 찾아요
price Number 필수 결제 금액. KRW는 100원 이상, USD는 0.01 이상이어야 해요
order_name String 필수 상품명, 주문명 (미입력 시 RC_NAME_BLANK 2003)
order_id String 필수 가맹점 고유 주문번호 (미입력 시 RC_O_ID_BLANK 2005)
tax_free Number 선택 비과세 금액 (price 이하)
metadata Object 선택 커스텀 데이터 (결제 완료/취소 시 반환)
user Object 선택 구매자 정보 (페이앱: 전화번호 필수)
items Array 선택 상품 정보 (페이코: 필수)
extra Object 선택 추가 옵션. 할부 관련 값은 대부분 이 객체 안에서 읽어요
card_quota String 선택 카드 할부 개월 수 (00, 02, 03 등). 아래 주의사항을 참고해요
card_interest String 선택 무이자 할부 여부 (일부 PG만 지원). 아래 주의사항을 참고해요
feedback_url String 선택 웹훅 수신 URL (미입력 시 관리자 설정값)
content_type String 선택 웹훅 데이터 타입 (application/json 또는 application/x-www-form-urlencoded)
할부 값은 extra 안에 함께 넣어요

card_quota·card_interest는 최상위 파라미터로도 받지만, 실제로 PG에 전달할 때 대부분의 PG(나이스페이먼츠·키움페이·페이앱·웰컴페이먼츠·라이트페이)는 extra 안의 값을 읽어요. 최상위 값만 넣으면 할부가 적용되지 않을 수 있으니 아래처럼 extra에도 함께 넣어야 해요. KCP는 최상위 값을 읽고, 이니시스는 최상위 값이 없으면 extra 값으로 대체해요.

{
  "extra": {
    "card_quota": "00",
    "card_interest": "0"
  }
}json

코드 예제

import { Bootpay } from '@bootpay/backend-js'

Bootpay.setConfiguration({
    client_key: '[ Client Key ]',
    secret_key: '[ Secret Key ]'
})

try {
    const response = await Bootpay.requestSubscribePayment({
        billing_key: '[ billing_key ]',
        order_name: '월 정기결제 - 2025년 1월',
        order_id: 'monthly_' + Date.now(),
        price: 9900,
        tax_free: 0
    })
    console.log(response)
} catch (e) {
    console.log(e)
}javascript

응답

빌링키 결제 요청 응답도 결제 상태에 따라 나눠서 처리해요. 성공 응답의 receipt_id는 이후 결제 조회·취소·웹훅 멱등 처리의 기준이에요.

{
  "receipt_id": "6261104e1fc19202e6f9420e",
  "order_id": "monthly_1705289520000",
  "price": 9900,
  "tax_free": 0,
  "cancelled_price": 0,
  "cancelled_tax_free": 0,
  "order_name": "월 정기결제 - 2025년 1월",
  "company_name": "부트페이 주식회사",
  "metadata": {
    "user_id": "1234"
  },
  "pg": "나이스페이먼츠",
  "method": "카드",
  "method_symbol": "card",
  "method_origin": "카드자동",
  "method_origin_symbol": "card_rebill",
  "currency": "KRW",
  "requested_at": "2025-01-15T14:31:58+09:00",
  "purchased_at": "2025-01-15T14:32:00+09:00",
  "receipt_url": "https://npg.nicepay.co.kr/issue/...",
  "status_locale": "결제완료",
  "status": 1
}json
응답 필드는 값이 있을 때만 내려와요

성공 응답은 값이 null인 필드를 지워서 내려줘요(compact). 예를 들어 receipt_url은 결제가 완전히 끝난 건에만, cancelled_at은 취소된 건에만 들어와요. 응답을 파싱할 때 특정 키가 항상 존재한다고 가정하면 안 돼요.

실패 응답의 payload는 PG 원본 응답이에요

승인 거절 응답의 payloadPG사가 내려준 원본 응답을 그대로 담은 값​​이에요. 필드 이름과 구조가 PG마다 다르고, receipt_id·order_id가 들어있지 않을 수도 있어요. 실패한 건을 식별할 때는 payload 안의 값을 읽지 말고, 요청할 때 쓴 order_id를 가맹점 쪽에서 들고 있다가 매칭​​해야 해요. 분기 판단은 error_codepg_error_code로 해요.

receipt_id를 반드시 저장해요

빌링 결제 응답의 receipt_id는 이후 결제 조회·결제 취소 시 필수예요. 결제 성공 시 receipt_id를 DB에 저장해야 해요.

에러 코드

공통 에러

인증·권한 관련 에러는 에러 코드표를 참고해요.

코드 메시지 대처 방법
SUBSCRIBE_BK_NOT_FOUND (2309) 빌링키 발급 내역을 찾지 못했다 billing_key가 올바른지 확인해요
SUBSCRIBE_BK_EXPIRED (2310) 빌링키 유효기간 만료 빌링키를 새로 발급받아요
RC_NAME_BLANK (2003) 상품명을 입력한다 order_name 값을 입력해요
RC_O_ID_BLANK (2005) order_id 값을 입력한다 order_id를 유니크한 값으로 입력해요
RC_PRICE_LEAST_LT (2004) 100원보다 큰 금액을 결제할 수 있다 KRW는 price를 100원 이상, USD는 0.01 이상으로 설정해요
RC_PROVIDER_NOT_ALLOW (2104) 가맹점이 탈퇴/차단 상태 부트페이 관리자에서 가맹점 상태를 확인해요
RC_PROVIDER_PAYMENT_NOT_ALLOW (2102) 서비스 이용료 미납으로 결제 불가 부트페이 서비스 이용료를 납부해요
RC_NOT_CONFIRM_READY (2023) 결제 승인 대기 상태가 아니다 결제 상태를 확인 후 재시도해요
RC_CONFIRM_METHOD_NOT_FOUND (2025) 결제 승인 함수가 구현되지 않은 PG이다 PG사에 문의해요
RC_CONFIRM_FAILED (2026) PG사가 결제 승인을 거절했다 한도초과·잔액부족·카드 정지 등 실제 승인 거절이 이 코드로 내려와요. pg_error_codemessage로 사유를 확인하고 고객에게 안내해요
RC_CONFIRM_CRITICAL_FAILED (2085) 서버에서 치명적인 오류 발생 부트페이 관리자에 문의해요
RC_REQUEST_FAILED (2013) 결제 요청 처리 중 예상치 못한 예외가 발생했다 승인 거절이 아니라 요청 단계의 예외 fallback이에요. 요청 파라미터를 확인 후 재시도해요
2085의 message는 코드 의미와 맞지 않아요

RC_CONFIRM_CRITICAL_FAILED(2085)는 메시지 매핑 테이블에 취소금액 복구 관련 문구가 잘못 들어가 있어서, 내려오는 message가 실제 오류 상황과 맞지 않아요. message 문자열로 분기하지 말고 error_code 값으로 분기​​해야 해요.

다음 단계