사전 요구 사항
시작하기 전에 다음이 필요합니다:- Dodo Payments merchant account
- 대시보드의 Developer → API Keys에서 발급한 API key를
DODO_PAYMENTS_API_KEY에 저장 - Developer → Webhooks에서 발급한 webhook secret을
DODO_PAYMENTS_WEBHOOK_KEY에 저장 - Products에서 생성된 subscription product 하나 이상
API 통합
Checkout Session
subscription product를 사용해 Checkout Session을 생성하여 subscription을 만듭니다. 고객이 payment method를 승인하면 Checkout을 완료하는 즉시 subscription이 활성화됩니다.- Node.js SDK
- Python SDK
- REST API
API 응답
응답에는checkout_url가 포함됩니다:
Webhooks
Webhooks는 subscription 이벤트가 발생할 때 서버에 알립니다. 대시보드의 Developer → Webhooks에서 endpoint를 설정하세요. webhook endpoint를 설정하는 방법은 Webhooks를 참조하세요.Subscription 이벤트 유형
subscription lifecycle을 관리하려면 다음 이벤트를 추적하세요:subscription.active— Subscription이 활성화됨subscription.updated— Subscription의 필드가 변경됨subscription.on_hold— 갱신 또는 플랜 변경 청구가 실패함subscription.failed— Subscription 생성에 실패함(종료 상태이며 고객이 다시 구독해야 함)subscription.renewed— 반복 청구가 성공함subscription.past_due— 갱신에 실패하고 유예 기간이 시작됨. 고객은past_due_ends_at까지 계속 액세스할 수 있음subscription.plan_changed— 플랜이 업그레이드, 다운그레이드 또는 변경됨subscription.cancelled— Subscription이 취소됨subscription.expired— Subscription이 기간 종료에 도달함
paused, unpaused, update_payment_method를 포함한 전체 목록은 Subscription Webhooks를 참조하세요.
결제 시나리오
성공적인 결제 흐름 webhook 순서는 subscription에 trial이 있는지에 따라 달라집니다. 즉시 청구(0 trial days):subscription.active: mandate가 승인되고 subscription이 활성화됩니다.payment.succeeded: 첫 번째 청구를 확인합니다. Checkout 후 2~10분 이내에 수신될 것으로 예상하세요.
- trial 시작 시(Checkout): payment method가 승인되면
subscription.active가 한 번 발생합니다. 아직 반복 청구는 이루어지지 않습니다. 첫 실제 청구는 trial이 종료될 때까지 연기됩니다. - trial 종료 시: 반복 금액이 청구되고
payment.succeeded를subscription.renewed와 함께 수신합니다.
subscription.renewed: 각 billing cycle에서 갱신 결제가 차감될 때 발생하며, 항상payment.succeeded와 함께 전송됩니다. 업데이트된next_billing_date도 포함합니다.
subscription product에 대해 실제로 금액이 차감될 때마다
subscription.renewed 및 payment.succeeded를 수신합니다. 다음 주기에 대한 액세스를 연장할 신호로 payment.succeeded만 사용하지 말고 subscription.renewed를 사용하세요.- Subscription 실패
subscription.failed- mandate 생성 실패로 subscription 생성에 실패했습니다.payment.failed- 결제 실패를 나타냅니다.
- Subscription 보류
subscription.on_hold- 갱신 결제 또는 플랜 변경 청구 실패로 subscription이 보류됩니다. 비즈니스에 유예 기간이 있는 경우 실패한 갱신은 먼저past_due(subscription.past_due)로 이동하고, 유예 기간이 종료될 때만on_hold(또는 유예 기간 설정에 따라cancelled)로 이동합니다. Subscription States를 참조하세요.- Subscription이 보류되면 payment method가 업데이트될 때까지 자동으로 갱신되지 않습니다.
권장 사항: 구현을 간소화하려면 subscription lifecycle을 관리할 때 주로 subscription 이벤트를 추적하는 것이 좋습니다.
subscription.failed와 subscription.on_hold 비교
이 두 이벤트는 혼동하기 쉽지만 처리 방법은 매우 다릅니다:
보류된 Subscription 처리
Subscription이on_hold 상태가 되면 다시 활성화하기 위해 payment method를 업데이트해야 합니다. 이 섹션에서는 subscription이 보류되는 시점과 처리 방법을 설명합니다.
Subscription이 보류되는 경우
다음과 같은 경우 subscription이 보류됩니다:- 갱신 결제 실패: 잔액 부족, 만료된 카드 또는 은행 거절로 자동 갱신 청구에 실패
- 플랜 변경 청구 실패: 플랜 업그레이드/다운그레이드 중 즉시 청구에 실패
- Payment method 승인 실패: 반복 청구에 대해 payment method를 승인할 수 없음
보류된 Subscription 다시 활성화
on_hold 상태의 subscription을 다시 활성화하려면 Update Payment Method API를 사용하세요. 이 API는 다음 작업을 자동으로 수행합니다:
- 미납 잔액에 대한 청구 생성
- 청구서 생성
- 새 payment method를 사용하여 결제 처리
- 결제가 성공하면 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 이벤트를 모니터링하세요:
payment.succeeded- 미납 잔액에 대한 청구가 성공함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는 유지됩니다.
동작
- 이 API를 호출하면 Dodo Payments가 선택한 proration 옵션에 따라 즉시 청구를 시작합니다.
prorated_immediately를 사용하면 업그레이드와 다운그레이드 모두 변경할 때마다 현재 주기의 미사용 부분에 대한 크레딧이 계산됩니다. 해당 크레딧이 새 주기 청구액을 초과하면 나머지가 subscription의 크레딧 잔액에 추가됩니다. 이 크레딧은 해당 subscription에만 적용되며 동일한 subscription의 향후 반복 결제를 상쇄하는 데만 사용됩니다.difference_immediately를 사용하면 순액은 항상 정확한 가격 차액입니다. 다운그레이드의 초과 금액은prorated_immediately와 동일하게 subscription 범위의 크레딧으로 저장됩니다.full_immediately옵션은 크레딧 계산을 건너뛰고 새 플랜의 전체 금액을 청구합니다.do_not_bill옵션은 변경을 즉시 적용하지만 청구를 다음 갱신일로 연기하며, 기존 갱신일은 유지됩니다.
청구 처리
- 플랜 변경 시 시작되는 즉시 청구는 일반적으로 2분 이내에 처리가 완료됩니다.
- 어떤 이유로든 즉시 청구에 실패하면 문제가 해결될 때까지 subscription이 자동으로 보류됩니다.
On-Demand Subscriptions
On-Demand Subscriptions를 사용하면 고정된 일정뿐 아니라 유연한 방식으로 고객에게 요금을 청구할 수 있습니다. 이 기능은 모든 account에서 사용할 수 있습니다.
subscription_data.on_demand field를 포함하세요. 이를 통해 즉시 청구 없이 payment method를 승인하거나 사용자 지정 초기 가격을 설정할 수 있습니다.
On-Demand Subscription에 요금을 청구하려면:
이후 청구에는 POST /subscriptions//charge endpoint를 사용하고 해당 거래에서 고객에게 청구할 금액을 지정하세요.
요청/응답 예시, 안전한 재시도 정책 및 webhook 처리를 포함한 전체 단계별 가이드는 On-Demand Subscriptions Guide를 참조하세요.
Subscription Billing에 대해 알아야 할 주요 사항
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 측 거절(잔액 부족, 카드 거절)입니다.관련 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