Skip to main content

사전 요구 사항

시작하기 전에 다음이 필요합니다:
  • Dodo Payments merchant account
  • 대시보드의 Developer → API Keys에서 발급한 API key를 DODO_PAYMENTS_API_KEY에 저장
  • Developer → Webhooks에서 발급한 webhook secret을 DODO_PAYMENTS_WEBHOOK_KEY에 저장
  • Products에서 생성된 subscription product 하나 이상
자세한 내용은 Integration Guide Prerequisites를 참조하세요.

API 통합

Checkout Session

subscription product를 사용해 Checkout Session을 생성하여 subscription을 만듭니다. 고객이 payment method를 승인하면 Checkout을 완료하는 즉시 subscription이 활성화됩니다.
동일한 Checkout Session에서 subscription product와 one-time product를 함께 사용할 수 있습니다. 이를 통해 설정 수수료, SaaS와 함께 제공하는 하드웨어 번들 및 유사한 사용 사례를 지원할 수 있습니다. 예시는 Checkout Sessions를 참조하세요.

API 응답

응답에는 checkout_url가 포함됩니다:
고객을 이 URL로 리디렉션하세요. 고객이 payment method를 승인하면 subscription이 활성화됩니다.

Webhooks

Webhooks는 subscription 이벤트가 발생할 때 서버에 알립니다. 대시보드의 Developer → Webhooks에서 endpoint를 설정하세요. webhook endpoint를 설정하는 방법은 Webhooks를 참조하세요.

Subscription 이벤트 유형

subscription lifecycle을 관리하려면 다음 이벤트를 추적하세요:
  1. subscription.active — Subscription이 활성화됨
  2. subscription.updated — Subscription의 필드가 변경됨
  3. subscription.on_hold — 갱신 또는 플랜 변경 청구가 실패함
  4. subscription.failed — Subscription 생성에 실패함(종료 상태이며 고객이 다시 구독해야 함)
  5. subscription.renewed — 반복 청구가 성공함
  6. subscription.past_due — 갱신에 실패하고 유예 기간이 시작됨. 고객은 past_due_ends_at까지 계속 액세스할 수 있음
  7. subscription.plan_changed — 플랜이 업그레이드, 다운그레이드 또는 변경됨
  8. subscription.cancelled — Subscription이 취소됨
  9. subscription.expired — Subscription이 기간 종료에 도달함
이는 핵심 이벤트입니다. paused, unpaused, update_payment_method를 포함한 전체 목록은 Subscription Webhooks를 참조하세요.
subscription.updated를 사용하면 모든 subscription 변경에 대한 실시간 알림을 받을 수 있으므로 API를 polling하지 않고도 애플리케이션 상태를 동기화할 수 있습니다.

결제 시나리오

성공적인 결제 흐름 webhook 순서는 subscription에 trial이 있는지에 따라 달라집니다. 즉시 청구(0 trial days):
  1. subscription.active: mandate가 승인되고 subscription이 활성화됩니다.
  2. payment.succeeded: 첫 번째 청구를 확인합니다. Checkout 후 2~10분 이내에 수신될 것으로 예상하세요.
trial 기간이 있는 경우:
  1. trial 시작 시(Checkout): payment method가 승인되면 subscription.active가 한 번 발생합니다. 아직 반복 청구는 이루어지지 않습니다. 첫 실제 청구는 trial이 종료될 때까지 연기됩니다.
  2. trial 종료 시: 반복 금액이 청구되고 payment.succeeded를 subscription.renewed와 함께 수신합니다.
이후 모든 갱신:
  • subscription.renewed: 각 billing cycle에서 갱신 결제가 차감될 때 발생하며, 항상 payment.succeeded와 함께 전송됩니다. 업데이트된 next_billing_date도 포함합니다.
subscription product에 대해 실제로 금액이 차감될 때마다 subscription.renewed 및 payment.succeeded를 수신합니다. 다음 주기에 대한 액세스를 연장할 신호로 payment.succeeded만 사용하지 말고 subscription.renewed를 사용하세요.
결제 실패 시나리오
  1. Subscription 실패
  • subscription.failed - mandate 생성 실패로 subscription 생성에 실패했습니다.
  • payment.failed - 결제 실패를 나타냅니다.
  1. Subscription 보류
  • subscription.on_hold - 갱신 결제 또는 플랜 변경 청구 실패로 subscription이 보류됩니다. 비즈니스에 유예 기간이 있는 경우 실패한 갱신은 먼저 past_due(subscription.past_due)로 이동하고, 유예 기간이 종료될 때만 on_hold(또는 유예 기간 설정에 따라 cancelled)로 이동합니다. Subscription States를 참조하세요.
  • Subscription이 보류되면 payment method가 업데이트될 때까지 자동으로 갱신되지 않습니다.
권장 사항: 구현을 간소화하려면 subscription lifecycle을 관리할 때 주로 subscription 이벤트를 추적하는 것이 좋습니다.
error_code/error_message를 읽고, 재시도 시점을 결정하며, 고객에게 실패를 표시하는 전체 과정은 Handle Payment Failures를 참조하세요.

subscription.failed와 subscription.on_hold 비교

이 두 이벤트는 혼동하기 쉽지만 처리 방법은 매우 다릅니다:
subscription.failed는 종료 상태입니다. Subscription을 다시 활성화할 수 없습니다. 고객이 새 subscription을 생성해야 합니다. 이 이벤트가 발생하면 entitlement를 절대 부여하지 마세요.

보류된 Subscription 처리

Subscription이 on_hold 상태가 되면 다시 활성화하기 위해 payment method를 업데이트해야 합니다. 이 섹션에서는 subscription이 보류되는 시점과 처리 방법을 설명합니다.

Subscription이 보류되는 경우

다음과 같은 경우 subscription이 보류됩니다:
  • 갱신 결제 실패: 잔액 부족, 만료된 카드 또는 은행 거절로 자동 갱신 청구에 실패
  • 플랜 변경 청구 실패: 플랜 업그레이드/다운그레이드 중 즉시 청구에 실패
  • Payment method 승인 실패: 반복 청구에 대해 payment method를 승인할 수 없음
on_hold 상태의 subscription은 자동으로 갱신되지 않습니다. Subscription을 다시 활성화하려면 payment method를 업데이트해야 합니다.

보류된 Subscription 다시 활성화

on_hold 상태의 subscription을 다시 활성화하려면 Update Payment Method API를 사용하세요. 이 API는 다음 작업을 자동으로 수행합니다:
  1. 미납 잔액에 대한 청구 생성
  2. 청구서 생성
  3. 새 payment method를 사용하여 결제 처리
  4. 결제가 성공하면 subscription을 active 상태로 다시 활성화
1

Handle subscription.on_hold webhook

subscription.on_hold webhook을 수신하면 애플리케이션 상태를 업데이트하고 고객에게 알리세요:
2

Update payment method

고객이 payment method를 업데이트할 준비가 되면 Update Payment Method API를 호출하세요:
고객이 저장된 payment method를 보유한 경우 기존 payment method ID를 사용할 수도 있습니다:
3

Monitor webhook events

payment method를 업데이트한 후 다음 webhook 이벤트를 모니터링하세요:
  1. payment.succeeded - 미납 잔액에 대한 청구가 성공함
  2. subscription.active - Subscription이 다시 활성화됨

Subscription 이벤트 payload 예시


Subscription 플랜 변경

change plan API endpoint를 사용하여 subscription 플랜을 업그레이드하거나 다운그레이드할 수 있습니다. 이를 통해 subscription의 product와 수량을 변경하고 proration을 처리할 수 있습니다.

Change Plan API Reference

subscription 플랜 변경에 대한 자세한 내용은 Change Plan API 문서를 참조하세요.

Proration 옵션

Subscription 플랜을 변경할 때 즉시 청구를 처리하는 네 가지 옵션이 있습니다:

1. prorated_immediately

  • 남은 시간을 기준으로 비례 계산하여 현재 billing cycle의 사용하지 않은 부분을 크레딧으로 제공합니다. 크레딧에는 기본 플랜, 수량 및 add-on이 포함됩니다.
  • 그런 다음 새 플랜, 수량 및 add-on으로 전체 주기를 청구합니다. 청구 자체에는 proration이 적용되지 않습니다.
  • 순 즉시 청구액 = (새 주기 전체 금액) - (남은 비율 x 기존 주기 전체 금액). 크레딧이 더 큰 경우 차액은 향후 갱신에 사용할 subscription 범위의 크레딧으로 보관됩니다.
  • trial 기간에는 사용자가 즉시 새 플랜으로 전환되며 고객에게 바로 청구됩니다.

2. full_immediately

  • 이전 주기에 대한 크레딧 없이 새 플랜의 전체 subscription 금액을 고객에게 청구합니다.
  • 업그레이드와 다운그레이드 모두 고객은 새 플랜 가격 전액을 처음부터 지불합니다.
  • 기존 플랜에 남은 기간과 관계없이 전체 금액을 청구하려는 경우 유용합니다.

3. difference_immediately

  • 고객은 기존 플랜 가격과 새 플랜 가격의 차액만 지불합니다.
  • 금액은 주기의 어느 시점에 변경했는지에 따라 달라지지 않습니다. 1일에 변경하든 29일에 변경하든 동일한 업그레이드 비용이 적용됩니다.
  • 업그레이드 시 고객에게 차액이 즉시 청구됩니다. 예: $30/month → $80/month = 즉시 $50 청구
  • 다운그레이드 시 가격 차액은 subscription 범위의 크레딧으로 저장되어 향후 갱신에 자동 적용됩니다. 예: $50/month → $20/month = $30 크레딧 저장

4. do_not_bill

  • 플랜 변경을 즉시 적용하지만 변경 시점에는 아무것도 청구하지 않습니다. 새 플랜, 수량 및 add-on을 즉시 사용할 수 있습니다.
  • 지금 청구하지 않으므로 업그레이드 시 고객은 현재 주기의 남은 기간 동안 더 높은 플랜을 무료로 사용합니다. 다운그레이드는 이미 결제한 주기의 미사용 부분에 대한 크레딧 없이 즉시 적용됩니다.
  • do_not_bill를 통해 제공된 add-on은 청구된 적이 없으므로 이후 플랜 변경 시 크레딧으로 처리되지 않습니다. 이후 변경에서는 새 add-on 수량 전체가 청구됩니다.
  • 업데이트된 플랜(및 수량/add-on)은 다음 예정된 갱신 시 청구되며, 기존 billing date는 유지됩니다.
세 가지 “지금 청구” 모드는 모두 billing cycle을 재설정합니다. prorated_immediately, difference_immediately 및 full_immediately는 subscription의 next_billing_date를 변경일로 이동합니다. do_not_bill만 기존 갱신일을 유지하지만 즉시 청구는 적용하지 않습니다.

동작

  • 이 API를 호출하면 Dodo Payments가 선택한 proration 옵션에 따라 즉시 청구를 시작합니다.
  • prorated_immediately를 사용하면 업그레이드와 다운그레이드 모두 변경할 때마다 현재 주기의 미사용 부분에 대한 크레딧이 계산됩니다. 해당 크레딧이 새 주기 청구액을 초과하면 나머지가 subscription의 크레딧 잔액에 추가됩니다. 이 크레딧은 해당 subscription에만 적용되며 동일한 subscription의 향후 반복 결제를 상쇄하는 데만 사용됩니다.
  • difference_immediately를 사용하면 순액은 항상 정확한 가격 차액입니다. 다운그레이드의 초과 금액은 prorated_immediately와 동일하게 subscription 범위의 크레딧으로 저장됩니다.
  • full_immediately 옵션은 크레딧 계산을 건너뛰고 새 플랜의 전체 금액을 청구합니다.
  • do_not_bill 옵션은 변경을 즉시 적용하지만 청구를 다음 갱신일로 연기하며, 기존 갱신일은 유지됩니다.
Proration 모드 선택:
  • difference_immediately — 고객이 가격 차액을 지불합니다. 가장 예측 가능한 옵션으로, 주기의 어느 시점에 변경하든 청구액이 동일합니다.
  • prorated_immediately — 고객은 현재 주기의 미사용 시간에 대해서만 크레딧을 받습니다. 청구액은 주기의 어느 시점에 변경했는지에 따라 달라집니다.
  • full_immediately — 고객이 새 플랜의 전체 금액을 지불합니다. 이전 주기에 대한 크레딧은 없습니다.
  • do_not_bill — 지금은 청구하지 않습니다. 새 플랜은 다음 갱신 시 청구됩니다. 기존 billing date를 유지하는 유일한 모드입니다.

청구 처리

  • 플랜 변경 시 시작되는 즉시 청구는 일반적으로 2분 이내에 처리가 완료됩니다.
  • 어떤 이유로든 즉시 청구에 실패하면 문제가 해결될 때까지 subscription이 자동으로 보류됩니다.

On-Demand Subscriptions

On-Demand Subscriptions를 사용하면 고정된 일정뿐 아니라 유연한 방식으로 고객에게 요금을 청구할 수 있습니다. 이 기능은 모든 account에서 사용할 수 있습니다.
On-Demand Subscription을 생성하려면: On-Demand Subscription을 생성하려면 POST /checkouts API endpoint를 사용하고 요청 본문에 subscription_data.on_demand field를 포함하세요. 이를 통해 즉시 청구 없이 payment method를 승인하거나 사용자 지정 초기 가격을 설정할 수 있습니다.
POST /subscriptions는 deprecated되었습니다. 기존 통합에서는 계속 작동하지만 새 통합에서는 subscription_data.on_demand가 포함된 Checkout Session(POST /checkouts)을 통해 On-Demand Subscription을 생성해야 합니다. 현재 흐름은 On-Demand Subscriptions Guide를 참조하세요.
On-Demand Subscription에 요금을 청구하려면: 이후 청구에는 POST /subscriptions//charge endpoint를 사용하고 해당 거래에서 고객에게 청구할 금액을 지정하세요.
요청/응답 예시, 안전한 재시도 정책 및 webhook 처리를 포함한 전체 단계별 가이드는 On-Demand Subscriptions Guide를 참조하세요.

Subscription Billing에 대해 알아야 할 주요 사항

subscription period를 payment frequency보다 길게 설정하세요. subscription period가 payment frequency와 같으면(예: period = 1 month, frequency = 1 month) subscription은 단일 주기 동안만 유효한 뒤 갱신되지 않고 expired로 이동합니다. 지속적인 월간 플랜의 경우 긴 subscription period(예: 20 years)와 월간 payment frequency를 설정하세요.
첫 번째 성공적인 청구 시 통화가 고정됩니다. Checkout을 생성할 때 항상 billing_currency 및 billing_address.country를 명시적으로 전달하세요. 생략하면 고객의 IP(Adaptive Currency)를 기준으로 감지되며 subscription이 첫 번째 청구를 수행하면 해당 통화가 전체 기간 동안 고정됩니다. 이후 고객이 여행하더라도 변경할 수 없습니다.
trial은 청구가 아닌 $0 authorization을 수행합니다. Subscription에 trial이 있으면 trial 시작 시 카드를 저장하기 위해 $0 mandate authorization이 생성되며, 첫 실제 청구는 trial 종료 시 발생합니다. 결제 목록에서 free trial 중인 subscription은 total_amount가 0인 결제 하나만 표시됩니다. paid trial은 대신 trial_amount를 선불로 청구합니다.
Subscription lifecycle: past_due = 갱신에 실패했으며 유예 기간이 진행 중입니다(고객은 계속 액세스할 수 있음). on_hold = 갱신에 실패했습니다(복구 가능: 고객에게 payment method 업데이트를 요청하며 dunning 재시도가 적용됨). expired = 갱신 없이 기간이 종료되었으며 다시 활성화할 수 없습니다. 고객이 다시 구독해야 합니다. cancelled = 고객 또는 merchant가 종료했습니다. 대부분의 갱신 실패는 Dodo 오류가 아니라 issuer 측 거절(잔액 부족, 카드 거절)입니다.
인도 카드는 RBI e-mandate를 사용합니다. Off-session 청구(갱신 및 플랜 변경 청구)는 정산까지 최대 약 48시간이 걸릴 수 있으며, ₹15,000 초과 반복 자동 인출에는 새로운 고객 인증이 필요합니다(따라서 해당 한도를 초과하는 업그레이드는 기존 mandate를 사용할 수 없습니다). 한 청구가 아직 processing인 동안 동일한 subscription에 대한 두 번째 청구는 “Cannot create new charge as previous payment is not successful yet.” 오류와 함께 실패합니다. 인도 외 카드는 거의 즉시 확인됩니다.
Subscription 청구에는 $1 최소 금액(또는 이에 상응하는 통화 금액)이 있습니다. $0.01–$0.99 금액은 product_price: value out of range와 함께 거부됩니다. 정확히 $0로 가격이 책정된 subscription product는 허용됩니다. Card-Optional at Zero Price를 참조하세요. 카드에 청구하지 않고 승인하려면 On-Demand mandate_only 설정을 사용하세요.

관련 API Reference

Create Subscription (Deprecated)

Subscription을 직접 생성하기 위한 Legacy API입니다. 새 통합에는 Checkout Sessions를 사용하세요.

Change Subscription Plan

proration 옵션을 사용하여 subscription 플랜을 업그레이드, 다운그레이드 또는 변경하는 API reference

Update Payment Method

payment method를 업데이트하고 보류된 subscription을 다시 활성화하는 API reference

Patch Subscription

subscription 세부 정보 및 구성을 업데이트하는 API reference
마지막 수정일 2026년 9월 26일