Skip to main content

概要

オンデマンドサブスクリプションでは、顧客の支払い方法を一度承認すると、固定スケジュールではなく、必要なときにいつでも変動する金額を請求できます。この機能はすべてのアカウントで利用でき、承認は必要ありません。 このガイドでは、次の方法を説明します。
  • オンデマンドサブスクリプションを作成する(任意の初回価格で mandate を承認)
  • カスタム金額で後続の請求をトリガーする
  • webhook を使用して結果を追跡する
一般的なサブスクリプションの設定については、サブスクリプション統合ガイドを参照してください。

前提条件

  • Dodo Payments merchant account と API key
  • webhook secret が設定され、イベントを受信する endpoint があること
  • カタログにサブスクリプション product があること
このガイドでは、checkout session(POST /checkouts)を介してオンデマンドサブスクリプションを作成します。この session は常にホスト型の checkout_url を返します。顧客をその URL にリダイレクトして mandate を承認してもらい、return_url には、その後に移動させる場所を設定します。

オンデマンドの仕組み

  1. on_demand object を使用して subscription を作成し、支払い方法を承認して、必要に応じて初回請求を回収します。
  2. 後から、専用の charge endpoint を使用し、カスタム金額でその subscription に対する charge を作成します。
  3. webhook(例:payment.succeededpayment.failed)をリッスンして、システムを更新します。

オンデマンドサブスクリプションを作成する

Endpoint: POST /checkouts 主要な request fields(body):
Create Checkout Sessionで確認してください

オンデマンドサブスクリプションを作成する

Success

オンデマンドサブスクリプションに請求する

mandate の承認後、必要に応じて charge を作成します。 Endpoint: POST /subscriptions/{subscription_id}/charge 主要な request fields(body):
integer
必須
請求する金額(最小通貨単位)。例:$25.00 を請求するには、2500 を渡します。
string
この請求に対する任意の currency override。
string
この請求に対する任意の description override。
boolean
true の場合、Adaptive Currency の手数料を product_price に含めます。false の場合、手数料は上乗せされます。
object
顧客のウォレット残高をこの請求の決済に使用する方法を指定します。
object
支払いに関する追加のメタデータ。省略した場合は、サブスクリプションのメタデータが使用されます。
Success
オンデマンドではないサブスクリプションへの請求は失敗する可能性があります。請求を行う前に、サブスクリプションの詳細に on_demand: true が含まれていることを確認してください。

請求失敗への対応

オンデマンドサブスクリプションへの請求が失敗した場合、次に何をするかはあなたが決定します。スケジュールされたサブスクリプションでは、更新に失敗すると以降の自動請求が停止しますが、オンデマンドサブスクリプションは失敗後も請求できます。独自の retry ロジックの一部として、請求エンドポイントを再度呼び出せます。

失敗時の動作

1

Charge attempt fails

POST /subscriptions/{subscription_id}/charge リクエストはエラーレスポンスを返すか、非同期で完了し、拒否理由を含む payment.failed webhook を発行します。
2

Subscription may transition to on_hold

サブスクリプションは on_hold 状態に移行し、subscription.on_hold webhook を発行することがあります(Subscription States → On Hold を参照)。これはシグナルであり、ロックではありません。オンデマンドサブスクリプションでは、on_hold になっても、再度請求することを妨げません。
3

Retry the charge (your call)

オンデマンドフローでは、Dodo は自動 retry を行いません。いつでも POST /subscriptions/{subscription_id}/charge を再度呼び出して retry できます。下記の 安全な retry ポリシー に従い、exponential backoff を使用し、hard decline をスキップして、burst パターンを避けてください。これにより、retry が当社の fraud および risk システムによってフラグ付けされるのを防げます。
4

Optionally, ask the customer for a new payment method

支払い方法自体に問題があるために retry が繰り返し失敗する場合(カードの有効期限切れ、アカウントの閉鎖など)は、POST /subscriptions/{subscription_id}/update-payment-method を使用して、顧客から新しい支払い方法を取得します。成功すると、サブスクリプションは active に戻り、続けて payment.succeeded および subscription.active webhook が発行されます。
オンデマンドとスケジュール型の違い:スケジュールされたサブスクリプションでは、Dodo が独自に更新 retry と督促を実行します。オンデマンドサブスクリプションでは、次の請求をいつ行うべきかを把握しているのはあなただけです(カレンダーではなく利用イベントによって決まるため)、retry ポリシーを管理します。

オンデマンド請求が失敗した場合の webhook シーケンス

Event 3 と 4 は、後続の請求が成功した後にのみ発行されます。

retry の責任

Dodo Payments は、失敗したオンデマンド請求を自動 retry しません。retry ポリシーはあなたが管理します。当社の fraud detection システムによって card testing としてフラグ付けされるのを避けるため、以下の安全な retry ガイドラインに従ってください。
Subscription Dunning — 組み込みのメールによる回収シーケンス — は、スケジュールされたサブスクリプションの 更新 支払いの失敗と、顧客が開始したキャンセルを対象としています。オンデマンド請求の失敗向けには設計されていません。支払い方法を更新する必要があると判断した場合は、顧客に直接(transactional email やアプリ内プロンプトなどで)連絡してください。

支払いの retry

当社の fraud detection システムは、積極的な retry パターンをブロックすることがあり(potential card testing としてフラグ付けする場合もあります)、安全な retry ポリシーに従ってください。
burst retry パターンは、当社の risk システムや processor によって fraud または card testing の疑いとしてフラグ付けされる可能性があります。retry が集中しないようにし、以下の backoff スケジュールと時刻合わせのガイダンスに従ってください。

安全な retry ポリシーの原則

  • Backoff mechanism:retry の間隔には exponential backoff を使用します。
  • Retry limits:retry の合計回数を制限します(最大 3~4 回)。
  • Intelligent filtering:retry 可能な失敗(network/issuer error、残高不足など)の場合にのみ retry し、hard decline は決して retry しません。
  • Card testing preventionDO_NOT_HONORSTOLEN_CARDLOST_CARDPICKUP_CARDFRAUDULENTAUTHENTICATION_FAILURE などの失敗は retry しないでください。
  • Vary metadata (optional):独自の retry システムを管理している場合は、メタデータ(例:retry_attempt)で retry を区別します。

推奨 retry スケジュール(サブスクリプション)

  • 1 回目:請求を作成した直後
  • 2 回目:3 日後
  • 3 回目:さらに 7 日後(合計 10 日後)
  • 4 回目(最終):さらに 7 日後(合計 17 日後)
最終ステップ:それでも未払いの場合は、ポリシーに基づいてサブスクリプションを未払いとしてマークするか、キャンセルします。支払い方法を更新できる期間中に顧客へ通知してください。

burst retry を避け、authorization 時刻に合わせる

  • portfolio 全体で「burst」動作が発生しないよう、retry の基準を元の authorization timestamp にします。
  • 例:顧客が本日午後 1:10 に trial または mandate を開始した場合、backoff(例:+3 日 → 午後 1:10、+7 日 → 午後 1:10)に従い、後続の retry を各日の午後 1:10 にスケジュールします。
  • または、最後に成功した支払い時刻 T を保存している場合は、時刻を合わせるため、次の試行を T + X days にスケジュールします。
Time-zone と DST:スケジュールには一貫した time standard を使用し、間隔を維持するため、表示時にのみ変換します。

retry すべきでない decline code

  • STOLEN_CARD
  • DO_NOT_HONOR
  • FRAUDULENT
  • PICKUP_CARD
  • AUTHENTICATION_FAILURE
  • LOST_CARD
decline reason の包括的な一覧と、ユーザーが修正可能かどうかについては、Transaction Failures ドキュメントを参照してください。
soft/temporary issue(例:insufficient_fundsissuer_unavailableprocessing_error、network timeout)の場合にのみ retry します。同じ decline が繰り返される場合は、それ以上の retry を一時停止してください。

実装ガイドライン(コードなし)

  • 正確な timestamp を永続化する scheduler/queue を使用し、正確な時刻の offset(例:同じ HH:MM の T + 3 days)で次の試行を計算します。
  • 最後に成功した支払いの timestamp T を保持・参照して次の試行を計算します。複数のサブスクリプションを同じ時刻に集中させないでください。
  • 常に最後の decline reason を評価し、上記の skip list にある hard decline の retry を停止します。
  • 意図しない surge を防ぐため、顧客ごと、アカウントごとに同時 retry 数を制限します。
  • 事前に連絡します:次回のスケジュールされた試行の前に、支払い方法を更新するよう顧客へ email/SMS で通知します。
  • メタデータは observability のみに使用し(例:retry_attempt)、意味のないフィールドをローテーションして fraud/risk システムを「回避」しようとしないでください。

キャンセル

オンデマンドサブスクリプションでは、即時の終了日を決める基準となる固定の billing cycle がないため、スケジュールされたサブスクリプションとは異なるキャンセルフローに従います。

Customer Portal の動作

顧客が Customer Portal からオンデマンドサブスクリプションをキャンセルすると、デフォルトではキャンセルが次回の billing date にスケジュールされます。オンデマンドサブスクリプションでは、Cancel Now オプションは意図的に表示されません。 理由は、オンデマンドサブスクリプションには予測可能な定期更新日がなく、次回の請求時刻が完全に利用イベントによって決まるためです。次回の billing date にキャンセルをスケジュールすることで、期間の境界まで mandate を有効なまま維持し、進行中の利用分を請求できるようにしてから、サブスクリプションを適切に終了できます。 顧客がキャンセルを確定した後:
  • サブスクリプションは active のままとなり、スケジュールされたキャンセル日まで POST /subscriptions/{id}/charge を介して引き続き請求できます。
  • サブスクリプションの cancel_at_next_billing_datetrue が設定されます。
  • キャンセルが有効になった時点で subscription.cancelled webhook が発行されます。
サブスクリプションを直ちに終了する必要がある場合(返金やサポートリクエストへの対応など)は、Customer Portal のフローに依存せず、API を介してプログラムでキャンセルしてください。

プログラムでキャンセルする

オンデマンドサブスクリプションは、いつでも API を介してキャンセルできます。キャンセルを即時に行うか、スケジュールするかを制御できます。 Endpoint: PATCH /subscriptions/{subscription_id}
サブスクリプションの statuscancelled に設定すると、直ちに終了します。mandate は revoke され、それ以降の請求は作成できません。
cURL

キャンセル時の webhook

handler でオンデマンドのキャンセルとスケジュールされたサブスクリプションのキャンセルを区別するには、webhook の処理時にサブスクリプションの on_demand flag を確認してください。

webhook で結果を追跡する

顧客の journey を追跡するため、webhook handling を実装します。Implementing Webhooks を参照してください。
  • subscription.active:Mandate が authorized になり、サブスクリプションが有効化された
  • subscription.failed:作成に失敗した(例:mandate failure)
  • subscription.on_hold:サブスクリプションが保留になった(例:unpaid state)
  • subscription.cancelled:サブスクリプションが完全にキャンセルされた(Cancellation を参照)
  • payment.succeeded:請求が成功した
  • payment.failed:請求が失敗した
オンデマンドフローでは、利用量ベースの請求を照合するため、payment.succeededpayment.failed に注目します。payment.failed に続いて subscription.on_hold が発生した場合は、サブスクリプションを回復するために Handling failed charges を参照してください。

テストと次のステップ

1

Create in test mode

test API key を使用してサブスクリプションを作成し、返された checkout_url を開いて mandate を完了します。
2

Trigger a charge

少額の product_price(例:100)を指定して請求エンドポイントを呼び出し、payment.succeeded を受信したことを確認します。
3

Go live

Event と内部 state の更新を検証したら、live API key に切り替えます。

トラブルシューティング

  • 422 Invalid Request:作成時に on_demand.mandate_only が、請求時に product_price が指定されていることを確認してください。
  • Currency errorsproduct_currency を上書きする場合は、アカウントと顧客でサポートされていることを確認してください。
  • No webhooks received:webhook URL と signature secret の設定を確認してください。
最終更新日 2026年8月6日