체크아웃

주문서 요청

장바구니를 주문서로 바꿔 결제 직전 정보까지 고정해요.

상품 판매 페이지에 결제 기능을 추가해요.

이럴 때 필요해요​: 상품 판매 페이지에 결제를 붙일 때, 구독 요금제 주문서를 만들 때
내가 할 일​: 관리자(상품 등록) + 프론트엔드(주문서 SDK) + 백엔드(주문 검증·웹훅)

Commerce SDK를 사용하여 구독/요금제 결제를 구현해요. 주문서를 통해 상품 선택부터 결제까지 한 번에 처리할 수 있어요.

빠르게 시작하려면?

체크아웃 빠른 매뉴얼 — JavaScript 최소 코드로 5분 안에 연동해요. 이 페이지는 전체 파라미터와 할인/프로모션을 다루는 Full Reference예요.

내가 하는 것

  • 관리자 상품 관리에서 상품 등록 (또는 API로 등록)
  • 서버에서 주문 완료 후 검증
  • 웹훅으로 주문 상태 동기화

Bootpay가 알아서 하는 것

  • 주문서 UI 호스팅, 결제 처리
  • 주문 생성·저장, 고객 데이터 관리
  • 웹훅 알림, 취소/환불 처리

연동 흐름

상품 등록 (관리자)

Bootpay 관리자 상품 대시보드에서 상품을 등록해요. 상품명, 가격, 구독 설정 등을 입력하면 product_id가 발급돼요.

::: tip API로 상품을 등록할 수도 있어요. 상품 등록 가이드를 참고해요.

주문서 요청 (개발자 · 프론트엔드)

import { BootpayCommerce } from '@bootpay/commerce-js'

const CLIENT_KEY = 'your-client-key'

async function selectPlan(planKey) {
    // 서버에 주문 생성 요청 (위변조 방지)
    const orderRes = await fetch('/api/orders/plan', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ plan_key: planKey })
    })
    const orderData = await orderRes.json()

    // Commerce 주문서 요청
    const response = await BootpayCommerce.requestCheckout({
        client_key: CLIENT_KEY,
        name: orderData.order_name,
        price: orderData.price,
        redirect_url: window.location.origin + '/result',
        user: {
            membership_type: 'guest',
            user_id: 'user_1234',
            name: '홍길동',
            phone: '01012345678',
            email: 'user@example.com'
        },
        products: [
            {
                product_id: 'product_id_here',
                duration: -1,
                quantity: 1
            }
        ],
        metadata: {
            order_id: orderData.order_id,
            plan_key: planKey
        },
        extra: {
            separately_confirmed: false,
            create_order_immediately: true
        }
    })
}javascript
모바일 앱 (Android · iOS · Flutter · React Native)

Commerce 주문서는 웹 리디렉트 방식이에요. 모바일 앱에서는 WebView로 주문서 페이지를 열거나, 결제 요청에서 일반 결제 SDK를 사용해요.

요청 파라미터

파라미터 타입 필수 설명
client_key String 필수 Commerce 클라이언트 키
name String 필수 주문명 (예: "Professional 플랜")
price Integer 필수 서버에서 계산한 결제 금액
redirect_url String 필수 결제 완료 후 이동 URL
products Array 필수 구독 상품 배열
products[].product_id String 필수 상품 ID
products[].duration Integer 필수 구독 기간 (-1: 무기한)
products[].quantity Integer 필수 수량
user Object 필수 구매자 정보
user.membership_type String 필수 회원 유형 (guest/member)
user.name String 필수 구매자 이름
user.phone String 선택 구매자 전화번호
user.email String 선택 구매자 이메일
request_id String 선택 청구서 ID (할인 적용 시)
metadata Object 선택 가맹점 커스텀 데이터
extra Object 선택 추가 옵션
extra.separately_confirmed Boolean 선택 분리 승인 모드
extra.create_order_immediately Boolean 선택 즉시 주문 생성 여부

결제 완료 처리 (개발자 · 프론트엔드)

결제 완료 후 redirect_url로 이동하며, URL 파라미터로 결과를 전달해요.

파라미터 설명
order_number Commerce 주문 고유 번호
event 결과 이벤트 (done/cancel/error)

프론트엔드 결과만으로 주문을 완료하면 안 돼요. 반드시 서버에서 주문 검증을 수행해요.

서버 검증 (개발자 · 서버)

GEThttps://api.bootapi.com/v1/orders/{order_number}Basic Auth
const express = require('express')
const { Bootpay } = require('@bootpay/backend-js')
const { BootpayCommerce } = require('@bootpay/backend-js')

const commerce = new BootpayCommerce({
    client_key: 'your-commerce-client-key',
    secret_key: 'your-commerce-secret-key',
    mode: 'production'
})

// 결제 검증 API
app.post('/api/orders/verify', async (req, res) => {
    const { receipt_id, order_id } = req.body

    // 주문 정보 조회
    const order = await getOrder(order_id) // DB에서 조회

    // Bootpay 결제 정보 조회
    Bootpay.setConfiguration({
        client_key: 'REST_APPLICATION_ID',
        secret_key: 'PRIVATE_KEY'
    })
    const receipt = await Bootpay.getReceipt(receipt_id)

    // 금액 검증 (위변조 방지)
    if (receipt.status === 1 && receipt.price === order.price) {
        // 주문 완료 처리
        res.json({ success: true })
    } else {
        // 금액 불일치 — 결제 취소
        await Bootpay.cancelPayment({
            receipt_id,
            cancel_price: receipt.price,
            cancel_reason: '금액 위변조 의심'
        })
        res.json({ success: false, message: '금액 불일치' })
    }
})javascript

:::

응답

주문 조회 응답

{
  "order_id": "68707c59b0eacea5cd974efd",
  "order_name": "구독상품 - 1회차",
  "price": 2800,
  "status": 2,
  "receipt_status": 1,
  "order_number": "25071182085082524116",
  "purchased_at": "2025-07-11T02:52:09Z",
  "created_at": "2025-07-11T02:52:09Z",
  "result_data": {
    "receipt_id": "68707c598bbe23d076af189c",
    "pg": "라이트페이",
    "method": "카드",
    "status": 1,
    "card_data": {
      "card_company": "KB국민",
      "card_no": "557042******1074"
    }
  },
  "order_subscriptions": {
    "subscriptions": [
      {
        "order_subscription_id": "68707c58b0eacea5cd974ef7",
        "status": 1,
        "current_duration": 3,
        "total_subscription_duration": 4
      }
    ]
  }
}json

:::

필드 타입 필수 설명
order_id String 필수 Commerce 주문 ID
order_name String 필수 주문명
price Integer 필수 결제 금액
status Integer 필수 주문 상태 (0: 대기, 1: 결제완료, 2: 확인)
receipt_status Integer 필수 결제 영수증 상태 (1: 완료)
order_number String 필수 주문 고유번호
purchased_at String 필수 결제 일시 (ISO 8601)
created_at String 필수 주문 생성 일시
result_data Object 선택 결제 결과 상세
receipt_id String 필수 Bootpay 영수증 ID
pg String 필수 PG사 이름
method String 필수 결제 수단
status Integer 필수 결제 상태 (1: 완료)
card_data Object 선택 카드 결제 시 카드 정보
card_company String 필수 카드사
card_no String 필수 마스킹된 카드번호
order_subscriptions Object 선택 구독 정보
subscriptions Array 필수 구독 목록
order_subscription_id String 필수 구독 ID
status Integer 필수 구독 상태 (1: 활성)
current_duration Integer 필수 현재 구독 회차
total_subscription_duration Integer 필수 총 구독 회차

주문 상태 관리

주문서 결제 후 가맹점 DB에서 주문 상태를 관리해요.

시점 가맹점 DB 상태 비고
주문서 요청 전 pending 주문 예비 생성 (서버에서 가격 계산)
서버 검증 성공 paid bootpay_order_id, bootpay_order_number 저장
배송 시작 shipping 가맹점이 직접 변경
배송 완료 completed 가맹점이 직접 변경
환불 웹훅 수신 refunded order.cancelled 웹훅으로 확인
상세 가이드

주문 전체 흐름(시퀀스 다이어그램), DB 설계, 흔한 실수는 다음 문서를 참고해요:

에러 코드

공통 에러

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

코드 메시지 대처 방법
ORDER_PRODUCT_BLANK 주문한 상품 정보가 없어요. products 파라미터를 확인해요
ORDER_PRODUCT_NOT_FOUND 상품 정보가 없어요 product_id를 확인해요
ORDER_PRICE_NOT_MATCH 요청된 금액과 상품의 결제 금액이 일치하지 않는다 price 계산을 확인해요
ORDER_ADDRESS_BLANK 배송상품의 경우 배송지 정보가 필수예요. 배송지 정보를 입력해요. address 정보를 입력해요

할인/프로모션 적용

서버에서 청구서를 미리 생성하여 할인을 적용할 수 있어요.

// 서버에서 청구서 생성 (할인 적용)
const invoice = await commerce.invoice.create({
    products: [{ product_id: 'product_123', quantity: 1 }],
    price: finalPrice,           // 할인 적용된 최종 금액
    original_price: originalPrice,
    user: { user_id: 'user_1234', name: '홍길동' },
    metadata: { promotion_code: 'SUMMER2024' }
})

// 프론트엔드에서 invoice_id를 request_id로 전달
BootpayCommerce.requestCheckout({
    request_id: invoice.data.invoice_id,
    // ...
})javascript