Prerequisites
Before you start, you need:- A Dodo Payments merchant account
- An API key from Developer → API Keys in the dashboard, stored in
DODO_PAYMENTS_API_KEY - A webhook secret from Developer → Webhooks, stored in
DODO_PAYMENTS_WEBHOOK_KEY - At least one subscription product created under Products
API Integration
Checkout Sessions
Create a subscription by building a checkout session with your subscription product. The customer authorizes a payment method and the subscription activates when they complete checkout.- Node.js SDK
- Python SDK
- REST API
API Response
Response bao gồm mộtcheckout_url:
Webhooks
Webhook thông báo cho server của bạn khi các subscription event xảy ra. Thiết lập endpoint trong Developer → Webhooks trên dashboard. Để thiết lập webhook endpoint, xem Webhooks.Subscription Event Types
Theo dõi các event này để quản lý subscription lifecycle:subscription.active— Subscription được kích hoạtsubscription.updated— Một field trên subscription đã thay đổisubscription.on_hold— Charge gia hạn hoặc charge thay đổi plan thất bạisubscription.failed— Tạo subscription thất bại (terminal; customer phải subscribe lại)subscription.renewed— Recurring charge thành côngsubscription.past_due— Gia hạn thất bại và grace period bắt đầu; customer vẫn giữ quyền truy cập cho đếnpast_due_ends_atsubscription.plan_changed— Plan được upgrade, downgrade hoặc thay đổisubscription.cancelled— Subscription đã bị cancelsubscription.expired— Subscription đã đến cuối term
paused, unpaused và update_payment_method, xem Subscription Webhooks.
Payment Scenarios
Successful Payment Flow Chuỗi webhook phụ thuộc vào việc subscription có trial hay không. Immediate billing (0 trial days):subscription.active: mandate được authorize và subscription được kích hoạt.payment.succeeded: xác nhận charge đầu tiên. Dự kiến event này xuất hiện trong 2–10 phút sau checkout.
- At trial start (checkout):
subscription.activeđược phát sau khi payment method được authorize. Chưa có recurring charge nào được thực hiện. Charge thực tế đầu tiên được trì hoãn đến khi trial kết thúc. - At trial end: recurring amount được charge và bạn nhận
payment.succeededcùng vớisubscription.renewed.
subscription.renewed: được phát ở mỗi billing cycle khi payment gia hạn được khấu trừ, luôn đi kèmpayment.succeeded. Event này cũng chứanext_billing_dateđã cập nhật.
Bất cứ khi nào tiền thực sự được khấu trừ cho subscription product, bạn sẽ nhận
subscription.renewed và payment.succeeded. Sử dụng subscription.renewed (thay vì chỉ dùng payment.succeeded) làm tín hiệu để gia hạn quyền truy cập cho cycle tiếp theo.- Subscription Failure
subscription.failed- Tạo subscription thất bại do không thể tạo mandate.payment.failed- Cho biết payment thất bại.
- Subscription On Hold
subscription.on_hold- Subscription bị đặt on hold do payment gia hạn thất bại hoặc charge thay đổi plan thất bại. Nếu business của bạn có grace period, lần gia hạn thất bại trước tiên sẽ chuyển subscription sangpast_due(subscription.past_due), và chỉ chuyển sangon_hold(hoặccancelled, tùy theo cài đặt grace period) khi grace period kết thúc. Xem Subscription States.- Khi subscription chuyển sang on hold, subscription sẽ không tự động renew cho đến khi payment method được cập nhật.
Best Practice: Để đơn giản hóa việc triển khai, chúng tôi khuyến nghị chủ yếu theo dõi subscription event để quản lý subscription lifecycle.
subscription.failed vs. subscription.on_hold
Hai event này rất dễ bị nhầm lẫn, nhưng cần được xử lý theo những cách rất khác nhau:
Handling Subscription On Hold
Khi subscription chuyển sang stateon_hold, bạn cần cập nhật payment method để reactivate subscription. Phần này giải thích thời điểm subscription chuyển sang on hold và cách xử lý.
When Subscriptions Go On Hold
Subscription được đặt on hold khi:- Renewal payment fails: Charge gia hạn tự động thất bại do không đủ tiền, thẻ hết hạn hoặc ngân hàng từ chối
- Plan change charge fails: Charge ngay lập tức trong quá trình upgrade/downgrade plan thất bại
- Payment method authorization fails: Không thể authorize payment method cho recurring charge
Reactivating Subscriptions from On Hold
Để reactivate subscription từ stateon_hold, hãy sử dụng Update Payment Method API. API này tự động:
- Tạo charge cho các khoản còn nợ
- Tạo invoice cho charge
- Xử lý payment bằng payment method mới
- Reactivate subscription về state
activekhi payment thành công
1
Handle subscription.on_hold webhook
Khi nhận webhook
subscription.on_hold, hãy cập nhật application state và thông báo cho customer:2
Update payment method
Khi customer sẵn sàng cập nhật payment method, hãy gọi Update Payment Method API:
Bạn cũng có thể sử dụng payment method ID hiện có nếu customer đã lưu payment method:
3
Monitor webhook events
Sau khi cập nhật payment method, hãy theo dõi các webhook event sau:
payment.succeeded- Charge cho các khoản còn nợ đã thành côngsubscription.active- Subscription đã được reactivate
Sample Subscription Event Payload
Changing Subscription Plans
Bạn có thể upgrade hoặc downgrade subscription plan bằng change plan API endpoint. API này cho phép bạn sửa product, quantity của subscription và xử lý proration.Change Plan API Reference
Proration Options
Khi thay đổi subscription plan, bạn có bốn tùy chọn để xử lý charge ngay lập tức:1. prorated_immediately
- Credit phần chưa sử dụng của billing cycle hiện tại, được tính theo thời gian còn lại. Credit bao gồm base plan, quantity và mọi add-on
- Sau đó charge đầy đủ một cycle theo plan, quantity và add-on mới. Bản thân charge không bao giờ được prorate
- Net immediate charge = (full new cycle) trừ (remaining fraction x full old cycle). Nếu credit lớn hơn, phần chênh lệch được giữ dưới dạng credit ở cấp subscription cho các lần renew trong tương lai
- Trong trial period, tùy chọn này ngay lập tức chuyển user sang plan mới và charge customer ngay
2. full_immediately
- Charge customer toàn bộ subscription amount của plan mới mà không credit cho cycle trước
- Dù upgrade hay downgrade, customer đều trả toàn bộ giá plan mới từ đầu
- Hữu ích khi bạn muốn charge toàn bộ amount bất kể còn bao nhiêu thời gian trong plan cũ
3. difference_immediately
- Customer chỉ trả phần chênh lệch giữa giá plan cũ và plan mới
- Amount không phụ thuộc vào thời điểm thay đổi trong cycle. Cùng một upgrade có chi phí như nhau vào ngày 1 và ngày 29
- Khi upgrade, customer được charge phần chênh lệch ngay lập tức. Ví dụ, $30/month → $80/month = charge ngay $50
- Khi downgrade, phần chênh lệch giá được lưu dưới dạng credit ở cấp subscription và tự động áp dụng cho các lần renew trong tương lai. Ví dụ, $50/month → $20/month = lưu credit $30
4. do_not_bill
- Áp dụng thay đổi plan ngay lập tức nhưng không charge tại thời điểm thay đổi. Plan, quantity và add-on mới có thể được sử dụng ngay
- Vì hiện tại không có charge, upgrade cho customer sử dụng plan cao hơn miễn phí trong phần còn lại của cycle hiện tại. Downgrade có hiệu lực ngay lập tức nhưng không có credit cho phần cycle chưa sử dụng mà customer đã thanh toán
- Add-on được cấp thông qua
do_not_billkhông được credit trong lần thay đổi plan sau đó vì chúng chưa từng được bill. Thay đổi tiếp theo sẽ bill toàn bộ quantity add-on mới - Plan cập nhật (cùng quantity/add-on) được bill vào lần renewal tiếp theo theo lịch, và ngày billing ban đầu được giữ nguyên
Behavior
- Khi gọi API này, Dodo Payments ngay lập tức khởi tạo charge dựa trên proration option bạn đã chọn
- Với
prorated_immediately, credit cho phần chưa sử dụng của cycle hiện tại được tính trong mỗi lần thay đổi, cả upgrade lẫn downgrade. Nếu credit lớn hơn charge của cycle mới, phần còn lại được cộng vào credit balance của subscription. Các credit này chỉ dành cho subscription đó và chỉ được dùng để bù trừ các recurring payment trong tương lai của cùng subscription - Với
difference_immediately, net luôn bằng chính xác phần chênh lệch giá. Đối với downgrade, phần dư được lưu thành credit ở cấp subscription, giống nhưprorated_immediately - Tùy chọn
full_immediatelybỏ qua việc tính credit và charge toàn bộ amount của plan mới - Tùy chọn
do_not_billáp dụng thay đổi ngay lập tức nhưng trì hoãn billing đến ngày renewal tiếp theo, ngày này được giữ nguyên
Charge Processing
- Immediate charge được khởi tạo khi thay đổi plan thường hoàn tất xử lý trong chưa đầy 2 phút
- Nếu immediate charge này thất bại vì bất kỳ lý do nào, subscription sẽ tự động được đặt on hold cho đến khi vấn đề được giải quyết
On-Demand Subscriptions
On-demand subscription cho phép bạn charge customer linh hoạt, không chỉ theo lịch cố định. Tính năng này khả dụng cho mọi account.
subscription_data.on_demand vào request body. Điều này cho phép bạn authorize payment method mà không charge ngay lập tức hoặc đặt initial price tùy chỉnh.
To charge an on-demand subscription:
Đối với các charge tiếp theo, sử dụng endpoint POST /subscriptions//charge và chỉ định amount cần charge customer cho transaction đó.
Để xem hướng dẫn đầy đủ từng bước (bao gồm request/response example, safe retry policy và webhook handling), xem On-Demand Subscriptions Guide.
Key Things to Know About Subscription Billing
Trial thực hiện authorization $0, không phải charge. Khi subscription có trial, trial start tạo mandate authorization $0 để lưu card; charge thực tế đầu tiên xảy ra khi trial kết thúc. Trong payment list, subscription đang free trial hiển thị chính xác một payment với
total_amount bằng 0. Paid trial thay vào đó sẽ charge trial_amount ngay từ đầu.Subscription lifecycle:
past_due = gia hạn thất bại và grace period đang diễn ra (customer vẫn giữ quyền truy cập). on_hold = gia hạn thất bại (có thể khôi phục: yêu cầu customer cập nhật payment method; dunning retry được áp dụng). expired = term kết thúc mà không renew và không thể reactivate. Customer phải subscribe lại. cancelled = kết thúc bởi customer hoặc merchant. Hầu hết lỗi gia hạn là issuer-side decline (không đủ tiền, thẻ bị từ chối), không phải lỗi của Dodo.