구독 운영

해지

구독 계약을 해지해요. 설정에 따라 즉시이거나 관리자 승인을 거쳐요.

v1 API 상세 명세

구독 계약을 해지해요.

고객이 해지 요청

구독 계약의 중도 해지를 요청해요. 구독 설정에 따라 즉시 해지되거나 관리자 승인 후 해지돼요.

해지 처리 방식

설정 동작 설명
use_termination_approval: false 즉시 해지 요청 즉시 구독 종료
use_termination_approval: true 승인 대기 관리자 승인 후 해지

플로우

  • 해지 요청 -> 승인 필요?
  • 승인 필요? -> 즉시 해지 / 환불 처리 (false)
  • 승인 필요? -> 승인 대기 (true)
  • 승인 대기 -> 관리자 승인 / 해지 + 환불 (승인)

API 엔드포인트

POSThttps://api.bootapi.com/v1/order_subscriptions/requests/ing/terminationBasic Auth

요청 파라미터

파라미터 타입 필수 설명
order_subscription_id String 선택 구독 계약 ID (요청 본문). 없으면 order_number가 필수예요
order_number String 선택 구독 주문번호. order_subscription_id가 없으면 필수예요
user_id String 선택 로그인한 회원 ID 또는 이 몰의 외부 회원 ID. 보내면 구독 소유자와 대조해요. Bootpay-User-JWT 헤더로 보내도 돼요
reason String 선택 중도 해지 사유. 템플릿의 use_termination_reason 이 켜져 있으면 필수
termination_fee Number 선택 중도 해지 수수료. 수수료 계산 값이 0 이 아니면 필수
last_bill_refund_price Number 선택 마지막 회차 환불 금액. 수수료 계산 값이 0 이 아니면 필수
final_fee Number 선택 최종 청구 금액. 수수료 계산 값이 0 이 아니면 필수
service_end_at String 선택 서비스 종료일
수수료 값은 계산 API에서 받아 그대로 넣어요

수수료 계산이 돌려준 termination_fee·last_bill_refund_price·final_fee 중 0 이 아닌 값을 빼고 보내면 거절돼요. 계산 → 고객 동의 → 해지 요청 순서로 붙여요.

코드 예제

const { BootpayCommerce } = require('@bootpay/backend-js')

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

const response = await commerce.orderSubscription.terminateRequest(
    '687a1b2c3d4e5f6789012345',
    {
        reason: '개인 사정으로 인한 해지 요청',
        termination_fee: 30000,        // 수수료 계산 API 값 그대로
        last_bill_refund_price: 15000,
        final_fee: 15000
    }
)
console.log(response)javascript

응답

성공 응답

요청이 반영된 구독 계약 상세 전체를 돌려줘요. 아래는 일부만 추린 예시예요.

{
  "order_subscription_id": "687a1b2c3d4e5f6789012345",
  "status": "manual_terminated",
  "service_end_at": "2025-07-31T23:59:59+09:00",
  "request_histories": [
    {
      "request_type": "request_termination",
      "request_status": "request_approved_auto",
      "termination_fee": 30000,
      "last_bill_refund_price": 15000,
      "final_fee": 15000
    }
  ]
}json

응답 필드 설명

필드 타입 설명
order_subscription_id String 구독 계약 고유 ID
status String 구독 상태. 자동 승인이면 manual_terminated(직접 해지), 관리자 승인이 필요하면 승인 전까지 그대로예요
service_end_at String 서비스 종료일
request_histories Array 이 구독의 요청 이력. 해지 요청은 request_type 이 request_termination (내부값 41)이고, 확정된 수수료·환불액이 함께 담겨요. 요청 유형 전체

에러 코드

공통 에러

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

코드 메시지 대처 방법
ORDER_SUBSCRIPTION_TERMINATE_UNABLE 이미 해지되었거나 해지할 수 없는 구독 상태예요 구독 상태를 확인해요
SUBSCRIPTION_TERMINATION_NOT_ALLOWED 이미 중도해지 되었거나, 정책상 중도해지 요청을 할 수 없는 상태예요. 구독 상태를 확인해요
SUBSCRIPTION_TERMINATION_REASON_REQUIRED 중도해지 사유를 입력해야 해요. reason 파라미터를 입력해요
SUBSCRIPTION_TERMINATION_FEE1_INVALID 중도해지 수수료가 유효하지 않아요. 수수료 계산 값의 termination_fee 를 넣어요
SUBSCRIPTION_TERMINATION_FEE2_INVALID 마지막 회차 환불금액이 유효하지 않아요. 수수료 계산 값의 last_bill_refund_price 를 넣어요
SUBSCRIPTION_TERMINATION_FEE3_INVALID 최종 수수료가 유효하지 않아요. 수수료 계산 값의 final_fee 를 넣어요
ORDER_SUBSCRIPTION_TERMINATION_REQUEST_DUPLICATE 이미 대기 중인 중도해지 요청이 있어요. 기존 요청 처리를 기다려요
ORDER_SUBSCRIPTION_TERMINATE_CANNOT_ABLE 구독해지를 승인할 수 없는 상태예요. 이미 해지·만료된 구독인지 확인해요
알려진 문제 — 고객 해지에는 해지 웹훅이 오지 않아요

지금은 고객 해지 요청이 즉시 해지되거나 관리자 승인으로 해지돼도 subscription.terminated 웹훅이 나가지 않아요. 이 API의 응답 status 나 계약 상세의 status 로 해지 여부를 확인해요.

use_termination 설정이 false인 구독 상품은 해지 요청이 불가능해요. 부트페이 관리자 상품 설정에서 구독 설정을 확인해요.

관리자가 해지 처리

관리자가 직접 구독 계약을 해지해요. 고객 요청 없이 관리자가 즉시 해지할 수 있으며, 수수료와 환불 금액을 직접 설정할 수 있어요.

이 API는 관리자(Supervisor) 권한이 필요해요. 해지된 구독을 되살리는 API는 없어요 — 복구는 부트페이 관리자에서만 할 수 있고, 복구되면 subscription.restored 웹훅이 와요.

고객 요청 vs 관리자 직접 해지

구분 고객 요청 관리자 직접 해지
API 고객 해지 요청 이 API
승인 과정 관리자 승인 필요 (설정에 따라) 즉시 해지
수수료 설정 자동 계산 관리자가 직접 설정 가능
환불 금액 자동 계산 관리자가 직접 설정 가능

API 엔드포인트

PUThttps://api.bootapi.com/v1/order_subscriptions/:order_subscription_id/terminateBasic Auth (supervisor 권한 필요)

요청 파라미터

파라미터 타입 필수 설명
order_subscription_id String 필수 구독 계약 ID (URL 파라미터)
reason String 선택 해지 사유
termination_fee Number 선택 해지 수수료 (관리자 직접 설정)
last_bill_refund_price Number 선택 마지막 회차 환불 금액
final_fee Number 선택 최종 정산 금액. 양수면 추가 결제, 음수면 그 금액만큼 환불해요. 실제 환불·추가 결제는 이 값으로 실행돼요
service_end_at String 선택 서비스 종료일 (ISO 8601, 미입력 시 즉시)
cancel_date String 선택 해지 기준일 (ISO 8601). service_end_at 을 비우면 이 날짜가 서비스 종료일이 돼요
알려진 문제 — final_fee 를 빼면 환불·추가 결제가 실행되지 않아요

지금은 termination_fee·last_bill_refund_price·final_fee 를 보내지 않으면 서버 계산값이 아니라 0 으로 확정돼요. 특히 final_fee 가 0 이면 last_bill_refund_price 를 넣었어도 환불이 실행되지 않아요. 수수료 계산에서 받은 값(또는 직접 정한 값)으로 세 값을 모두 함께 보내요.

코드 예제

curl -X PUT "https://api.bootapi.com/v1/order_subscriptions/{order_subscription_id}/terminate" \
  -H "Authorization: Basic {base64(client_key:secret_key)}" \
  -H "Content-Type: application/json" \
  -d '{
    "reason": "서비스 정책 변경에 따른 해지",
    "termination_fee": 0,
    "last_bill_refund_price": 15000,
    "final_fee": -15000
  }'bash

응답

{
  "order_subscription_id": "687a1b2c3d4e5f6789012345",
  "status": "admin_terminated",
  "service_end_at": "2025-07-11T15:00:00+09:00"
}json

응답 필드 설명

파라미터 타입 설명
order_subscription_id String 구독 계약 ID
status String 변경된 상태 (admin_terminated: 관리자 해지)
service_end_at String 서비스 종료 시각

해지 사유와 확정된 수수료·환불액은 신청 관리의 해지 요청 이력(request_type: request_termination)에 남아요. 관리자 해지 웹훅은 subscription.admin_terminated 로 와요.

에러 코드

공통 에러

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

코드 메시지 대처 방법
ORDER_SUBSCRIPTION_NOT_FOUND 구독결제 건을 찾을 수 없어요. order_subscription_id를 확인해요
ORDER_SUBSCRIPTION_TERMINATE_CANNOT_ABLE 구독해지를 승인할 수 없는 상태예요. 이미 해지·만료된 구독인지 확인해요
TIME_INVALID 시간 포맷이 잘못되었어요. ISO 8601 표준시 포맷으로 보내요. service_end_at·cancel_date 형식을 확인해요