참고

FAQ

반복 질문을 한 페이지에서 빠르게 확인해요.

이 문서는 Bootpay 결제 연동 중 자주 묻는 질문과 문제 해결 방법을 정리해요. 에러가 발생했거나 동작 방식이 헷갈릴 때 먼저 확인해요.

일반

Sandbox와 Production의 차이는 무엇인가요?

Sandbox​​는 테스트 환경으로, 실제 결제가 발생하지 않아요. 개발·테스트 단계에서 사용해요. Production​​은 실제 결제가 처리되는 운영 환경이에요.

  • Sandbox와 Production은 별도 키를 사용하며 데이터가 분리돼요
  • 테스트 완료 후 연동키를 Production용으로 교체하면 돼요

API 호출 제한이 있나요?

과도한 반복 호출은 제한될 수 있어요. 같은 결제 조회를 짧은 간격으로 무한 반복하지 말고, 재시도 간격과 최대 횟수를 정해요. 실제 제한 조건은 운영 정책에 따라 달라질 수 있으니 관리자 공지나 Bootpay 문의로 확인해요.

서버 인증은 토큰을 직접 관리해야 하나요?

결제 서버 SDK를 쓰면 Basic Auth 인증을 SDK가 처리해요. SDK 없이 직접 호출한다면 Authorization: Basic base64(client_key:secret_key) 헤더를 요청마다 포함해요. 자세한 내용은 API 인증을 봐요.

결제

테스트 결제는 어떻게 하나요?

  1. 관리자 > 개발자 설정 > API 연동키 (결제)에서 Sandbox 모드의 연동키를 복사해요
  2. SDK 초기화 시 Sandbox 키를 사용해요
  3. 결제위젯에서 테스트 결제를 진행해요
  4. Sandbox 결제는 실제 카드/계좌에서 금액이 차감되지 않아요

지원하는 결제수단은 무엇인가요?

Bootpay는 여러 결제수단을 지원해요. 실제 노출 여부는 계약한 PG사와 관리자에서 활성화한 결제수단에 따라 달라져요:

결제수단 설명
신용/체크카드 국내 주요 카드사
계좌이체 실시간 계좌이체
가상계좌 무통장 입금
휴대폰 결제 통신사 소액결제
간편결제 카카오페이, 네이버페이, 토스페이 등

separately_confirmed는 언제 사용하나요?

결제 승인 전에 서버에서 금액 검증​​이 필요한 경우 사용해요. extra.separately_confirmed: true로 설정하면:

  1. 결제 정보 입력 완료 시 confirm 이벤트 발생
  2. 서버에서 주문 금액과 결제 금액 비교
  3. 서버에서 승인 API를 호출하여 최종 승인

이 방식에서는 클라이언트의 onDone이 호출되지 않아요. onConfirm에서 받은 receipt_id를 백엔드로 전달하고, 프론트엔드는 백엔드 주문 상태를 조회해 결과 화면을 보여줘야 해요.

재고·쿠폰·포인트처럼 승인 직전 서버 판단이 필요하면 extra.separately_confirmed: true를 우선 검토해요. 다만 일부 PG·결제수단은 서버 승인을 지원하지 않을 수 있어요.

커머스 FAQ 는 별도

주문·상품·구독·링크페이 관련 FAQ 는 FAQ 에서 봐요.


트러블슈팅

인증 문제

Basic Auth 인증 실패

증상​: API 호출 시 인증 관련 에러가 발생

원인 및 해결​:

  1. Client Key / Secret Key 확인관리자 > 개발자 설정 > API 연동키 (결제)에서 서버용 키를 복사해요
  2. Sandbox / Production 모드 확인 — 테스트 시 sandbox 키, 운영 시 production 키를 사용해요
  3. 키 앞뒤 공백 제거 — 복사 시 포함된 공백을 확인해요
  4. Authorization 헤더 확인 — 직접 호출한다면 Authorization: Basic base64(client_key:secret_key) 형식인지 확인해요
// SDK 사용 시 — SDK가 Basic Auth를 처리
Bootpay.setConfiguration({
    client_key: 'YOUR_CLIENT_KEY',
    secret_key: 'YOUR_SECRET_KEY'
})

const receipt = await Bootpay.receiptPayment(receiptId)javascript

결제위젯 문제

위젯이 표시되지 않음

체크리스트​:

  1. client_key가 올바른지 확인
  2. 위젯 렌더링 대상 <div> 요소가 DOM에 존재하는지 확인
  3. 브라우저 콘솔에서 에러 메시지 확인
  4. CSP(Content-Security-Policy) 설정이 부트페이 도메인을 허용하는지 확인

결제 완료 후 콜백이 호출되지 않음

원인​: extra.separately_confirmed: true 설정 시 done이 아니라 confirm 이벤트를 구현해야 해요.

Bootpay.requestPayment({
    // ...
    extra: { separately_confirmed: true }
})
.on('confirm', function(data) {
    // 서버로 receipt_id 전달
    // 서버에서 금액·주문 상태 검증 후 승인 API 호출
    sendConfirmToServer(data.receipt_id)
})javascript

웹훅 문제

웹훅을 수신하지 못함

체크리스트​:

  1. HTTPS 필수 — HTTP URL은 지원하지 않아요
  2. 방화벽 확인 — 외부에서 웹훅 URL로 접근 가능한지 확인해요
  3. 200 응답 — 정상 수신한 요청은 빠르게 HTTP 200을 반환해요
  4. 처리 시간 — 무거운 비즈니스 로직은 비동기로 처리해 타임아웃을 피해야 해요

웹훅 중복 수신

원인​: 200 응답을 제때 반환하지 않으면 재시도가 발생해요.

해결​: 결제 웹훅은 receipt_idstatus 조합을 기준으로 중복 처리를 방지해요. 같은 결제 상태 변경을 이미 처리했다면 비즈니스 로직을 다시 실행하지 말고 바로 200으로 응답해요.

app.post('/webhook', async (req, res) => {
    const { receipt_id, status } = req.body
    const dedupeKey = `${receipt_id}:${status}`

    // 이미 처리된 결제 상태 변경인지 확인
    const exists = await db.webhookLogs.findOne({ where: { dedupe_key: dedupeKey } })
    if (exists) {
        return res.status(200).json({ success: true })
    }

    await db.webhookLogs.create({ dedupe_key: dedupeKey })

    // 200 먼저 반환
    res.status(200).json({ success: true })

    // 비동기로 비즈니스 로직 처리
    await processWebhook(req.body)
})javascript

취소 문제

부분 취소 실패

원인​: 일부 카드사/PG사는 부분 취소를 지원하지 않아요.

해결​: 전체 취소 후 차액을 재결제하거나, PG사에 부분 취소 지원 여부를 확인해요.