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.succeeded、payment.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
オンデマンドではないサブスクリプションに請求すると、400(SUBSCRIPTION_NOT_ON_DEMAND)が返されて失敗します。請求する前に、サブスクリプションに on_demand: true があることを確認してください。オンデマンドサブスクリプションではプランを変更することもできません。POST /subscriptions/{subscription_id}/change-plan は、これらに対して 422 を返します。

失敗した請求への対応

オンデマンドサブスクリプションへの請求が失敗した場合、次に何をするかはあなたが決定します。スケジュールされたサブスクリプションでは、更新に失敗すると以降の自動請求が停止しますが、オンデマンドサブスクリプションは失敗後も請求できます。独自の 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 が送信される場合があります(サブスクリプションの状態 → On Holdを参照)。これはシグナルであり、ロックではありません。オンデマンドサブスクリプションでは、on_hold によって再度請求できなくなることはありません。前回の支払いがまだ保留中の場合、新しい請求は 409 で拒否されます。また、直近の成功した支払い以降に4回を超える支払いが失敗している場合は、429 で拒否されます。
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 は、後続の請求が成功した後にのみ発行されます。

再試行の責任

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

Paymentの再試行

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

安全な再試行ポリシーの原則

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

推奨される再試行スケジュール(サブスクリプション)

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

バースト再試行を避け、承認時間に合わせる

  • 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 を使用し、間隔を維持するため、表示時にのみ変換します。

再試行すべきでないDecline Code

  • STOLEN_CARD
  • DO_NOT_HONOR
  • FRAUDULENT
  • PICKUP_CARD
  • AUTHENTICATION_FAILURE
  • LOST_CARD
decline reason の包括的な一覧と、ユーザーが修正可能かどうかについては、Transaction Failures ドキュメントを参照してください。
soft/temporary issue(例:insufficient_funds、issuer_unavailable、processing_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_date に true が設定されます。
  • キャンセルが有効になった時点で subscription.cancelled webhook が発行されます。
サブスクリプションを直ちに終了する必要がある場合(返金やサポートリクエストへの対応など)は、Customer Portal のフローに依存せず、API を介してプログラムでキャンセルしてください。

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

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

キャンセル時のWebhook

cancel_at_next_billing_date を設定またはクリアしても、専用のWebhookは送信されません。スケジュールされたキャンセルを追跡するには、APIレスポンスまたは次の subscription.updated payload から cancel_at_next_billing_date を読み取ってください。
ハンドラーでオンデマンドのキャンセルとスケジュールされたサブスクリプションのキャンセルを区別するには、Webhookの処理時にサブスクリプションの on_demand flag を確認してください。

Webhookで結果を追跡する

顧客の利用フローを追跡するために、Webhook処理を実装してください。Webhooksを参照してください。
  • subscription.active: Mandate が承認され、サブスクリプションが有効化された
  • subscription.failed: 作成に失敗した(例:mandate の失敗)
  • subscription.on_hold: サブスクリプションが保留になった(例:未払い状態)
  • subscription.cancelled: サブスクリプションが完全にキャンセルされた(キャンセルを参照)
  • payment.succeeded: 請求に成功した
  • payment.failed: 請求に失敗した
オンデマンドフローでは、使用量ベースの請求を照合するために payment.succeeded と payment.failed に注目してください。payment.failed の後に subscription.on_hold が続く場合は、サブスクリプションを復旧するために失敗した請求への対応を参照してください。

テストと次のステップ

1

Create in test mode

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

Trigger a charge

少額の product_price(例:100)を指定してcharge endpointを呼び出し、payment.succeeded を受信することを確認します。
3

Go live

イベントと内部状態の更新を検証したら、live API key に切り替えます。

トラブルシューティング

  • 422 Invalid Request: 作成時に on_demand.mandate_only が指定され、請求時に product_price が指定されていることを確認してください。
  • 通貨エラー: product_currency を上書きする場合は、アカウントと顧客でサポートされていることを確認してください。
  • Webhookを受信できない: Webhook URL と署名 secret の設定を確認してください。
最終更新日 2026年9月26日