가맹점 서비스에서 손님이 무통장 입금을 골랐을 때 써요. 가맹점 서버가 입금대기를 등록하면, 뱅크알람이 입금 문자를 받아 붙이고 웹훅으로 알려요.
1. GET /v1/sdk/deposits/accounts 입금 계좌 목록 → 손님이 은행 선택
2. POST /v1/sdk/deposits 입금대기 등록 → 응답의 계좌로 입금 안내
3. 손님 송금 → 은행 입금 문자 → 부트페이가 금액 · 입금자명으로 매칭
4. deposit.matched 웹훅 → GET /v1/sdk/deposits/{id} 로 다시 확인 → 결제 완료- 판매자가 뱅크알람 설정에서 입금 계좌를 등록해야 해요
- 모든 호출은 서버에서 Commerce
client_key·secret_key로 해요 (Basic Auth)
1입금 계좌 목록
{
"accounts": [
{ "id": "6ad715d43648be5a4eac7d40", "bank_name": "NH농협은행", "account_no": "3120224889861", "holder": "윤태섭", "primary": true },
{ "id": "6ad715d43648be5a4eac7d41", "bank_name": "KB국민은행", "account_no": "675601-01-092472", "holder": "윤태섭", "primary": false }
]
}jsonid 를 등록 때 account_id 로 보내요. 안 보내면 primary 계좌예요. 주문 전 화면에는 은행 이름만 보여 주고, 계좌번호는 등록 응답으로 안내해요.
2입금대기 등록
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
merchant_order_id |
String | 필수 | 가맹점 주문번호 (100자까지) |
price |
Number | 필수 | 입금받을 금액. 입금액과 똑같아야 붙어요 |
depositor |
String | 필수 | 입금자명. 입금 알림의 이름과 같아야 붙어요 |
account_id |
String | 선택 | 손님이 고른 계좌. 없으면 대표 계좌 |
webhook_url |
String | 선택 | 이 건의 웹훅 주소 (https://). 먼저 서명 비밀값이 있어야 해요 |
order_name |
String | 선택 | 관리자에 보일 주문 이름. 기본 「무통장 입금」 |
buyer_name |
String | 선택 | 구매자 이름. 없으면 입금자명 |
buyer_phone |
String | 선택 | 구매자 휴대폰. 알림톡을 켜면 필수 |
buyer_email |
String | 선택 | 구매자 이메일. 주면 안내 메일을 보내요 |
notify |
Object | 선택 | 구매자 알림톡 (건당 과금) |
memo |
String | 선택 | 관리자 메모 |
curl -X POST "https://api.bootapi.com/v1/sdk/deposits" \
-H "Authorization: Basic {base64(client_key:secret_key)}" \
-H "Content-Type: application/json" \
-d '{
"merchant_order_id": "SHOP-20261020-0042",
"price": 35000,
"depositor": "김보람",
"account_id": "6ad715d43648be5a4eac7d40"
}'bash응답
등록 · 조회 응답과 웹훅의 data 는 같은 모양이에요.
{
"merchant_order_id": "SHOP-20261020-0042",
"order_number": "26102065578025458162",
"order_name": "무통장 입금",
"amount": 35000,
"status": "awaiting",
"buyer_name": "김보람",
"account": { "id": "6ad715d43648be5a4eac7d40", "bank_name": "NH농협은행", "account_no": "3120224889861", "holder": "윤태섭" },
"deadline": "2026-10-21T14:32:11+09:00",
"deadline_label": "30분",
"notify": { "deposit_guide": true, "deposit_paid": true },
"paid_at": null,
"deposit": null
}json| 필드 | 설명 |
|---|---|
| status | awaiting 입금 대기 · paid 입금 확인 · expired 기한 만료 · cancelled 취소 |
| deadline | 입금 기한. 판매자 설정(30분 ~ 30일, 기본 30분)으로 정해져요 |
| deadline_label | 안내용 문구 — 「30분」 · 「2시간」 · 「3일」 |
| account | 손님에게 안내할 계좌 (등록 시점 값) |
| deposit | 붙은 입금. 입금 전엔 null |
같은 merchant_order_id 로 같은 값을 다시 보내면 기존 입금대기를 돌려줘요. 재시도해도 안전해요. 값이 다르면 BANK_DEPOSIT_MERCHANT_ID_CONFLICT 예요.
입금 기한
기한이 지나면 expired 로 닫혀요. 그 뒤 들어온 입금은 deposit.unmatched 로 와요.
deposit.expired 웹훅은 기한 시각에 바로 오지 않고, 그 뒤 첫 등록 · 조회 · 입금 때 와요. 정확한 시각은 deadline 으로 판단해요.
손님이 주문을 취소하거나 다시 주문했다면 취소로 바로 닫아 주세요. 같은 금액 · 이름의 입금대기가 둘 열려 있으면 자동으로 안 붙어요.
구매자 메일 (무료)
buyer_email 을 주면 메일을 보내요.
| 언제 | 내용 |
|---|---|
| 등록 직후 | 금액 · 계좌 · 입금자명 · 기한 |
| 입금 확인 | 금액 · 입금 시각 |
같은 주문번호로 재시도하면 다시 보내지 않아요.
구매자 알림톡 (유료)
notify 를 켜면 알림톡을 보내요. 건당 6.5원(부가세 별도)이 판매자의 알림톡 충전금에서 빠져요. 잔액이 없으면 안 보내고, 문자로 대신 보내지 않아요.
"notify": { "deposit_guide": true, "deposit_paid": true, "link": "https://shop.example.com/orders/SHOP-20261020-0042" }json| 필드 | 설명 |
|---|---|
| deposit_guide | 등록 직후 「납부 안내」 |
| deposit_paid | 입금 확인 때 「입금 확인」 |
| link | 알림톡 버튼 주소 (https://) |
판매자 쪽에서 세 가지가 준비돼야 해요. 안 됐으면 BANK_DEPOSIT_NOTIFY_NOT_READY 로 무엇이 빠졌는지 알려 줘요.
- 카카오 채널 연결 — 알림 설정 › 카카오
- 공용 템플릿 「납부 안내」 · 「입금 확인」 채택 — 메시지 › 템플릿
- 알림톡 충전 — 결제 관리 › 알림톡
notify 를 안 보내면 판매자의 알림 설정을 따라요.
3조회
부트페이 주문번호로 조회해도 돼요.
판매자가 잘못 붙은 입금을 되돌리면 awaiting 이 되고 deposit.reverted 가 와요. 가맹점 주문도 입금 대기로 되돌려요.
입금대기 취소
| 지금 상태 | 결과 |
|---|---|
| 입금 대기 | cancelled + deposit.cancelled 웹훅 |
| 기한 지남 | expired + deposit.expired 웹훅 |
| 이미 닫힘 | 그대로 돌려줘요 (웹훅 없음) |
| 입금 확인됨 | BANK_DEPOSIT_NOT_CANCELABLE |
4자동으로 붙는 조건
금액 · 입금자명이 같은 입금대기가 딱 하나이고, 아래가 모두 맞아야 해요. 아니면 판매자가 직접 골라요.
- 은행이 보낸 알림 (은행 앱, 은행 대표번호 문자)
- 입금된 계좌 끝자리가 등록 계좌 중 하나와 같음
- 입금자명이
depositor와 같음 - 판매자의 뱅크알람 이용이 정지되지 않음
손님이 다른 등록 계좌로 보내도 붙어요.
입금 웹훅
받는 주소는 관리자 쇼핑몰 설정 › 뱅크알람 › 입금 웹훅에서 정하거나, 등록 때 webhook_url 로 보내요. 둘 다 있으면 webhook_url 이 우선이에요.
| 이벤트 | 언제 |
|---|---|
deposit.matched |
입금대기에 붙어 입금 확인 |
deposit.ambiguous |
후보가 여럿이라 판매자가 골라야 함 |
deposit.unmatched |
붙일 입금대기가 없음 |
deposit.confirmed_manually |
판매자가 직접 입금 확인 |
deposit.expired |
기한이 지나 닫힘 |
deposit.cancelled |
취소됨 |
deposit.reverted |
입금 확인을 되돌림 |
deposit.received |
입금 알림 도착 (기본으로는 안 보내요) |
POST {webhook_url}
X-Bootpay-Webhook-Event: deposit.matched
X-Bootpay-Delivery-Id: 6710b2c4e1a9f3c2d8a1b7e0
X-Bootpay-Timestamp: 1760931731
X-Bootpay-Signature: sha256=9c1e…{
"event": "deposit.matched",
"event_code": 401,
"idempotency_key": "26102065578025458162:deposit.matched:k_35000_김보람_9861_1401_nh",
"occurred_at": "2026-10-20T14:02:11+09:00",
"data": {
"merchant_order_id": "SHOP-20261020-0042",
"order_number": "26102065578025458162",
"amount": 35000,
"status": "paid",
"account": { "id": "6ad715d43648be5a4eac7d40", "bank_name": "NH농협은행", "account_no": "3120224889861", "holder": "윤태섭" },
"paid_at": "2026-10-20T14:01:58+09:00",
"deposit": { "bank_name": "농협", "account_tail": "9861", "depositor": "김보람", "amount": 35000, "received_at": "2026-10-20T14:01:58+09:00" }
}
}jsondeposit.ambiguous · deposit.unmatched 의 data 는 { deposit, candidates } 예요.
- 2xx 로 답하면 받은 것으로 봐요. 아니면 10번까지 다시 보내요
- 같은 이벤트가 같은
idempotency_key로 다시 올 수 있어요 - 설정 주소로 10건 연속 실패하면 웹훅이 꺼져요
- 본문을 그대로 믿지 말고 조회 API 결과로 주문을 바꿔요
5웹훅 서명 비밀값
{ "secret": "whsec_3f9c…" }json이 응답에서만 원문을 보여 줘요. 다시 부르면 새 값으로 바뀌어요. 관리자 뱅크알람 › 입금 웹훅에서도 만들 수 있어요.
서명은 HMAC-SHA256(비밀값, "{X-Bootpay-Timestamp}.{본문}") 이에요.
import crypto from 'node:crypto'
app.post('/bootpay/deposit', express.raw({ type: 'application/json' }), async (req, res) => {
const timestamp = req.get('X-Bootpay-Timestamp')
const signature = req.get('X-Bootpay-Signature') || ''
const body = req.body.toString('utf8')
// 5분 넘은 요청은 거부
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return res.sendStatus(400)
const expected = 'sha256=' + crypto
.createHmac('sha256', process.env.BOOTPAY_DEPOSIT_WEBHOOK_SECRET)
.update(`${timestamp}.${body}`)
.digest('hex')
if (expected.length !== signature.length || !crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature))) {
return res.sendStatus(401)
}
const { data } = JSON.parse(body)
const deposit = await bootpayGet(`/v1/sdk/deposits/${encodeURIComponent(data.merchant_order_id)}`)
// paid → 결제 완료 · awaiting → 입금 대기 · expired / cancelled → 주문 취소
res.sendStatus(200)
})javascript에러 코드
| 코드 | 메시지 | 대처 방법 |
|---|---|---|
BANK_DEPOSIT_MERCHANT_ID_BLANK |
가맹점 주문번호를 보내주세요. | merchant_order_id 를 넣어요 |
BANK_DEPOSIT_MERCHANT_ID_TOO_LONG |
가맹점 주문번호는 100자까지예요. | 100자 이하로 줄여요 |
BANK_DEPOSIT_MERCHANT_ID_CONFLICT |
같은 주문번호가 다른 금액 · 입금자명 · 계좌로 이미 등록되어 있어요. | 새 주문번호로 등록해요 |
BANK_DEPOSIT_ACCOUNT_MISSING |
등록된 입금 계좌가 없어요. | 판매자가 계좌를 등록해야 해요 |
BANK_DEPOSIT_ACCOUNT_INVALID |
고른 입금 계좌를 찾을 수 없어요. | 계좌 목록을 다시 불러와요 |
BANK_DEPOSIT_WEBHOOK_SECRET_REQUIRED |
웹훅 서명 비밀값이 없어요. | 비밀값을 먼저 발급받아요 |
ORDER_BANK_TRANSFER_DEPOSITOR_BLANK |
입금자명을 입력해주세요. | depositor 를 넣어요 |
WEBHOOK_URL_INVALID |
웹훅 수신 URL 형식이 올바르지 않습니다. https 주소를 입력해 주세요. | https:// 주소를 보내요 |
BANK_DEPOSIT_BUYER_EMAIL_INVALID |
구매자 이메일(buyer_email) 형식을 확인해 주세요. | 주소를 고치거나 빼요 |
BANK_DEPOSIT_NOTIFY_NOT_READY |
구매자 알림톡을 보낼 준비가 안 됐어요 — (원인과 설정 위치) | 안내대로 설정하거나 notify 를 빼요 |
BANK_DEPOSIT_NOTIFY_PHONE_BLANK |
구매자 알림톡을 보내려면 구매자 휴대폰 번호(buyer_phone)를 보내주세요. | buyer_phone 을 넣어요 |
BANK_DEPOSIT_NOTIFY_LINK_INVALID |
알림톡 버튼 링크(notify.link)는 https 로 시작하는 주소여야 해요. | https:// 주소를 넣어요 |
BANK_DEPOSIT_NOT_CANCELABLE |
입금을 기다리는 수기 주문만 취소할 수 있어요. | 이미 입금된 건이에요. 결제 완료로 처리해요 |
ORDER_NOT_FOUND |
주문을 찾을 수 없어요. | 주문번호를 확인해요 |
PROCESS_DUPLICATED |
같은 요청이 처리 중이에요. | 잠시 뒤 같은 값으로 다시 보내요 |
함께 보기
- 뱅크알람으로 입금 확인 — 설정 · 매칭 규칙
- 주문 웹훅 설정 — 쇼핑몰 주문 웹훅(
order.*) - 예제:
commerce-example의functions/_shared/bank-deposit.js