정기결제위젯은 구독 가입 화면에서 빌링키 등록 UI를 띄우고, 사용자가 결제수단 등록을 마친 뒤 가맹점 코드가 requestSubscription()을 호출해 정기결제를 시작하는 흐름이에요. 단건 결제위젯처럼 “위젯 렌더링 = 결제 완료”가 아니에요.
이 문서의 목표는 독자가 아래 여정을 따라 신규 구독자의 결제수단 등록부터 서버 조회, 다음 회차 결제 준비까지 연결하도록 돕는 거예요.
| 독자 상황 | 먼저 볼 내용 | 완성 기준 |
|---|---|---|
| 단건 결제위젯과 차이가 헷갈리는 개발자 | 전체 흐름 이해 | render()와 requestSubscription()의 책임을 구분 |
| 신규 구독 가입 화면을 만드는 개발자 | 빌링키 등록 UI 렌더링 → 정기결제 요청 | 등록 UI와 가입 확정 버튼을 연결 |
| 서버 저장 흐름을 설계하는 개발자 | 응답 조회와 구독 저장 | receipt_id 조회 후 subscription_id와 빌링키를 매핑 |
| 이미 등록된 사용자를 처리하는 개발자 | 다음 회차 결제 처리 | 위젯 재노출 없이 서버 빌링 API로 결제 |
주문서에서 한 번 결제를 받는 흐름은 결제위젯을 봐요. 이 문서는 멤버십·정기 구독처럼 빌링키를 등록하고 반복 결제를 준비하는 흐름만 다뤄요.
이 가이드는 위젯 생성에서 구독 결제 유형으로 위젯을 만들고 widget_key를 받았다고 가정해요. 결제수단·디자인·브랜드페이 노출 같은 초기 설정은 관리자에서 먼저 끝내요.
0먼저 구분할 것
정기결제위젯에서 가장 중요한 구분은 “사용자가 결제수단을 등록하는 화면”과 “가맹점 서버가 구독을 확정하는 처리”를 나누는 거예요.
| 단계 | 클라이언트/위젯 역할 | 서버 역할 |
|---|---|---|
| 빌링키 등록 UI | BootpayWidget.render()로 등록 화면 표시 |
아직 주문 확정하지 않음 |
| 구독 시작 요청 | 가입 확정 버튼에서 requestSubscription() 호출 |
receipt_id를 받을 준비 |
| 결과 조회 | 응답의 receipt_id를 서버로 전달 |
결제 조회 API 응답으로 빌링키·구독 식별자 저장 |
| 다음 회차 결제 | 위젯을 다시 띄우지 않음 | 자동결제 API로 결제 스케줄 실행 |
1전체 흐름 이해
단건 결제위젯과 정기결제위젯은 같은 BootpayWidget 네임스페이스를 쓰지만, 완성해야 하는 사용자 여정이 달라요. 관리자 설정은 위젯 생성에서 끝내고, 이 문서에서는 구독 가입 화면 연동만 다뤄요.
| 위젯 | 호출 흐름 |
|---|---|
| 단건결제위젯 | BootpayWidget.render() → 사용자가 결제수단 선택 → 결제 완료 (한 번에) |
| 정기결제위젯 | BootpayWidget.render() → 사용자가 빌링키 등록 → 가맹점 코드에서 BootpayWidget.requestSubscription() 호출 → 정기결제 시작 |
구독 위젯의 render()가 띄우는 UI는 결제수단을 선택하는 화면이 아니라 빌링키(브랜드페이)를 등록하는 화면이에요. 등록 화면을 띄웠다는 이유만으로 결제가 일어나지 않아요. 가맹점이 requestSubscription()을 호출하고, 서버가 응답을 조회·확인해야 정기결제 라이프사이클을 시작할 수 있어요.
2신규 구독자의 빌링키 등록 UI 렌더링
구독 가입 페이지나 결제수단 등록 페이지에 위젯을 렌더링해요. 이 단계에서는 결제가 아니라 결제수단 등록 경험을 만들어요.
import { BootpayWidget } from '@bootpay/client-js'
BootpayWidget.setEnvironmentMode('production', undefined)
document.addEventListener('bootpay-widget-ready', (e) => {
// 빌링키 등록 UI가 준비된 시점이다.
console.log('widget ready', e.detail)
})
BootpayWidget.render('#widget', {
client_key: 'YOUR_CLIENT_KEY',
widget_key: 'YOUR_SUBSCRIPTION_WIDGET_KEY',
price: 0,
subscribe_brandpay_type: 'sequential',
use_only_brandpay: true,
use_terms: false
})javascript렌더 옵션 확인
아래 옵션은 구독 가입 화면에서 SDK에 넘기는 연동 값이에요. 위젯 이름, 결제수단, 디자인 같은 초기 설정은 관리자에서 조정해요.
| 옵션 | 타입 | 설명 |
|---|---|---|
client_key |
string |
Client Key |
widget_key |
string |
관리자에서 생성한 구독 위젯 키 |
price |
number |
빌링키 등록만 할 거면 0. 등록과 동시에 첫 결제를 받을 거면 실 금액 |
subscribe_brandpay_type |
'sequential' | 'select' |
등록 UX 모드. 아래 표 참고 |
use_only_brandpay |
boolean |
true면 브랜드페이(빌링키 발급)만 노출. 구독 위젯에서는 보통 true |
use_terms |
boolean |
위젯 하단 약관 동의 영역 표시 여부 |
extra.subscribe_test_payment |
boolean |
true면 등록 시 0원 테스트 결제로 카드 검증만 해요 |
등록 UX 선택: subscribe_brandpay_type
| 값 | UX |
|---|---|
sequential |
결제수단을 순차로 안내해요. 한 번에 하나씩 등록 — 일반 구독 가입 흐름에 적합 (권장) |
select |
등록 가능한 결제수단을 목록형으로 한 번에 보여준다. 사용자가 직접 고른다 |
3가입 확정 시 정기결제 요청
사용자가 빌링키 등록을 마치고 구독 가입을 확정하면 requestSubscription()을 호출해야 해요. 이 호출의 결과로 받은 receipt_id가 서버 결제 조회의 출발점이에요.
const requestSubscription = async () => {
try {
const response = await BootpayWidget.requestSubscription({
subscription_id: 'YOUR_SUBSCRIPTION_ID',
price: 0,
order_name: '월간 멤버십',
user: {
id: 'user-1234',
email: 'user@example.com',
phone: '01012345678'
},
extra: {
open_type: 'iframe'
}
})
const { receipt_id } = response
// receipt_id를 서버로 전달해 빌링키 매핑 + 첫 결제/스케줄 등록
await fetch('/api/subscriptions', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ receipt_id })
})
} catch (e) {
console.error('subscription failed', e.error_code, e.message)
}
}javascript응답 데이터 예시
requestSubscription() 응답도 우선 receipt_id를 중심으로 받아요. 구독·빌링키 저장에 필요한 상세값은 이 receipt_id로 서버에서 결제 조회를 호출해 확인해요.
{
"event": "done",
"receipt_id": "6244f60c1fc19202e42e8c4e",
"subscription_id": "sub_20260428_001",
"order_name": "월간 멤버십",
"price": 0,
"status": 1
}json{
"event": "error",
"error_code": "BK_REQUEST_FAILED",
"message": "빌링키 발급 요청이 실패했습니다.",
"subscription_id": "sub_20260428_001"
}json{
"event": "cancel",
"message": "사용자가 결제수단 등록을 취소했습니다.",
"subscription_id": "sub_20260428_001"
}json클라이언트 응답만 보고 빌링키를 활성화하지 말고, 서버 조회 응답의 receipt_id, order_id/subscription_id, status, 금액 값을 내부 구독 정보와 비교한 뒤 저장해요.
요청 옵션 확인
| 옵션 | 타입 | 설명 |
|---|---|---|
subscription_id |
string (필수) |
가맹점 구독 식별자. 가맹점 DB의 구독/멤버십 PK와 매핑하는 값 |
price |
number |
등록만 할 거면 0, 첫 결제 동시 처리할 거면 실 금액 |
order_name |
string |
영수증/관리자에 표시되는 주문명 |
user |
UserModel |
구매자 정보 (id, email, phone) |
extra.open_type |
'iframe' | 'popup' |
빌링키 인증 창 표시 방식 |
subscription_id는 부트페이가 만들어 주는 값이 아니라 가맹점 측 구독 PK를 그대로 넣는 값이에요. 같은 사용자의 갱신 결제도 동일한 subscription_id를 써요. UUID, 자체 시퀀스 등 가맹점 내에서 유일하게 식별 가능한 값으로 정해요.
4서버에서 응답 조회하고 구독 저장
requestSubscription()의 응답에서 받은 receipt_id를 서버로 전달해 결제 내역을 조회해요. 클라이언트에서 받은 응답만 믿고 빌링키를 활성화하면 안 돼요. 응답 위변조나 네트워크 중단에 대비해 서버 조회 결과를 기준으로 구독 상태를 저장해야 해요.
서버 처리 순서:
- 클라이언트로부터
receipt_id수신 - 서버에서 결제 조회 API로 정기결제 정보 확인
- 응답의
billing_key(또는 그에 상응하는 식별자)를 가맹점 DB에subscription_id와 매핑 - 첫 결제 또는 다음 결제 스케줄 등록 → 자동결제(빌링) 결제 요청
요청-응답 흐름 외에 부트페이 Webhook으로도 빌링키 발급 결과를 받을 수 있어요. 결제 라이프사이클 이벤트를 비동기로 처리하면 Webhook 우선이 안전해요.
5이미 등록된 사용자의 다음 회차 결제
사용자가 빌링키를 이미 등록한 적이 있다면 등록 UI를 다시 띄우지 않아요. 이때는 requestSubscription() 대신 자동결제 결제 요청 API를 서버에서 호출해야 해요. 위젯은 신규 등록이 필요한 사용자에게만 노출하고, 재결제·갱신·실패 재시도는 서버의 구독 스케줄에서 처리해야 해요.
6다음 단계
- 위젯 생성 — 관리자에서 구독 위젯을 만들고 결제수단 설정하는 절차
- 자동결제 결제 요청 — 빌링키로 다음 결제를 일으키는 서버 API
- 빌링키 조회/삭제 — 등록된 빌링키 라이프사이클 관리
