체크아웃

장바구니·찜·견적

v1 장바구니, 찜, 비회원 미리보기의 URL·본문·응답과 현재 제약

v1 장바구니 API는 회원의 장바구니 관리와 주문 전 가격 견적을 제공해요. 엔드포인트별 필드와 오류는 장바구니 API 원문을 확인해요.

모든 URL은 https://api.bootapi.com 기준이며 서버 Basic 인증을 사용해요. 회원 장바구니에는 Bootpay-User-JWT 또는 쇼핑몰 서버가 secretKey로 인증하고 지정한 user_id가 필요해요. 두 값을 함께 보내면 같은 회원이어야 해요. client_key만으로 인증한 호출에서는 user_id를 사용할 수 없어요.

장바구니 HTTP 계약

메서드·URL 본문 성공 본문
GET /v1/cart 없음 장바구니 객체
POST /v1/cart product_id, product_option_id?, quantity null — 추가 후 다시 조회
PUT /v1/cart/:id 또는 PATCH quantity 변경된 항목
DELETE /v1/cart/:id 없음 null
DELETE /v1/cart/destroy_items item_ids: string[] success와 제거/남은 개수
DELETE /v1/cart/clear 선택 group_key success와 제거/남은 개수
POST /v1/cart/merge cart_items: object[] 비회원 장바구니 병합 결과
POST /v1/cart/batch items: object[] 일괄 추가 결과
POST /v1/cart/checkout item_ids: string[], 선택 group_key { "order_pre_id": "...", "url": "..." }
PATCH /v1/cart/:id/update_period subscription_period_id 기간 변경 결과

:id는 상품 ID가 아니라 장바구니 항목 ID​​예요. 추가는 단건 본문이고 일괄 추가는 items 배열이에요. 수량 변경 액션은 옵션 변경을 처리하지 않아요. 옵션을 바꾸려면 항목 삭제/추가 흐름을 사용해요.

추가 API는 is_subscription, period, corporate_type, user_group_id도 읽어요. 회원/기업 권한과 상품 소속을 서버에서 검증한 값만 전달해요.

await commerce.post('cart', {
  product_id: productId,
  product_option_id: optionId,
  quantity: 2
}, { headers: { 'Bootpay-User-JWT': customerJwt } })

const cart = await commerce.get('cart', {
  headers: { 'Bootpay-User-JWT': customerJwt }
})javascript

조회 객체에는 cart_id, user_id, cart_items, delivery_groups, summary, checkout_groups, item_count, total_summary, created_at, updated_at가 있어요. checkout_groups[].group_key는 일반/구독 및 구매 유형별 결제 그룹을 구분해요. POST /v1/cart/checkout에서는 item_ids를 배열로 보내고, 한 주문에는 한 그룹만 담아요. item_ids와 group_key를 모두 생략하면 REQUIRED_PARAMETER_IS_MISSING이에요. group_key를 함께 보내면 해당 그룹의 항목만 주문해요. 성공 응답의 url로 결제 화면을 열고, 결제가 끝난 뒤 장바구니 항목이 빠져요.

컨트롤러에 preview/benefits 메서드가 남아 있어도 /v1/cart/preview, /v1/cart/benefits 라우트는 없어요. 아래 order-preview를 사용해요.

비회원 상품 검증·배송비·미리보기

메서드·URL 요청 응답
POST /v1/cart/validate cart_items { cart_items: [...] }
POST /v1/cart/delivery-fee cart_items { delivery_groups: [...] }
POST /v1/cart/order-preview cart_items, 선택 shipping_address.zipcode checkout_ready, amounts, quote_token, expires_at 등
const preview = await commerce.cart.orderPreview({
  cart_items: [{ product_id: productId, product_option_id: optionId, quantity: 2 }]
})javascript

validate는 구매 불가 항목도 빼지 않고 is_available: false와 reason을 돌려줘요. 견적은 상품 금액·배송비를 주문 준비와 같은 규칙으로 계산해요. shipping_address.zipcode를 넣으면 제주·도서산간 추가 배송비까지 확정해요. 쿠폰·적립금은 반영하지 않고 구독 상품은 이 견적으로 결제할 수 없어요.

{
  "checkout_ready": true,
  "amounts": {
    "product_price": 20000,
    "delivery_price": 3000,
    "total_price": 23000
  },
  "quote_token": "q1.eyJ2Ijo...",
  "expires_at": "2026-09-29T03:00:00Z"
}json

cart_items는 최대 50개이며 수량은 각 항목과 같은 상품·옵션의 합계 모두 1~999여야 해요. 구매 불가 항목이 하나라도 있으면 checkout_ready: false, amounts: null이며 토큰이 없어요. 견적 토큰은 10분 동안 유효해요. 회원 장바구니에서 결제한다면 항목마다 cart_item_id를 보내세요. 결제 완료 후 해당 줄에서 결제한 수량만 차감해요.

회원 견적은 JWT 또는 secretKey 인증의 user_id를 사용해요. 비회원 견적에 Bootpay-Device-UUID를 보냈다면 준비 요청에도 같은 값을 보내야 해요. 견적과 준비의 구매자가 달라지면 ORDER_QUOTE_SESSION_MISMATCH로 거절돼요. 미리보기가 성공해도 주문서나 재고 예약은 생성되지 않아요.

찜

메서드·URL 본문 성공 본문
GET /v1/wishlist 없음 { "wishlist_items": [], "total_items": 0 }
POST /v1/wishlist product_id, 선택 product_option_id null
DELETE /v1/wishlist/:id 없음 null
POST /v1/wishlist/:id/to_cart 없음 null; 장바구니에 수량 1 추가 후 찜 삭제

:id는 wishlist_items[].wishlist_id예요. 항목에는 product_id, product_option_id, product_name, product_option_name, image, price, available, unavailable_label이 있어요. to_cart가 성공하면 찜과 장바구니를 다시 조회해요.

찜 API도 회원 전용이에요. Bootpay-User-JWT 또는 secretKey 인증의 user_id로 회원을 지정해요. POST /v1/wishlist는 다른 상점의 상품 ID를 PRODUCT_NOT_FOUND로 거절해요. 다른 회원의 wishlist_id로 삭제·이동하면 404예요. 필드와 오류는 찜 API 원문을 확인해요.

to_cart 재시도

POST /v1/wishlist/:id/to_cart에 Idempotency-Key 헤더를 보내면, 같은 회원이 같은 항목으로 재전송해도 장바구니 수량이 다시 오르지 않고 최초 결과를 돌려줘요. 같은 키로 다른 항목​​을 보내면 409 IDEMPOTENCY_REQUEST_MISMATCH예요. 헤더가 없으면 이전 동작 그대로예요.

담기까지 성공한 뒤 찜 삭제가 실패해 요청 자체가 실패로 끝난 경우에는, 같은 키의 재시도가 다시 실행돼요(주문 준비의 멱등 계약과 같아요). 응답을 받은 뒤의 재전송·다중 클릭은 막혀요.

API 원문

세부 요청·응답 필드와 오류 코드는 장바구니 API, 주문서 생성 방식은 주문 API를 참고해요.