このエントリーは with Advent Calendar 2025 の 19日目の記事です。
Stripeでサブスクリプション決済を実装する際、こんな疑問を持ったことはないでしょうか?🤔
- サブスクリプションの契約時に決済が失敗したら、どんな挙動になるのか?
- テスト環境で決済失敗のケースを検証するにはどうすればいいのか?
本記事では、Stripeのテスト環境で決済失敗時の挙動を検証した結果と、その方法について共有します。
テスト用の決済失敗カード
Stripeのテスト環境では、基本的に決済が成功するテストカード(4242424242424242など)を使用します。しかし、以下のカード番号を使うと、Customerへの紐付けは成功するが、決済時に失敗するという挙動を再現できます。
| カード番号 | 挙動 |
|---|---|
4000000000000341 |
カードの紐付けは成功するが、決済時に拒否される |
検証フロー
テストカードをCustomerに紐づける
検証に用いる顧客データの支払い方法に、テストカードを紐づけます。
セキュリティの制限により、Stripe APIに直接カード番号を送信することはできないので、Stripeのダッシュボードから紐付けを行うことを推奨します。
テストを行う顧客の詳細から、支払い方法 → カードを追加 でカード情報を追加します。
Customer Portalからの更新
なお、ダッシュボードからの紐付けではなく、Customer Portalを用いて決済手段の更新を行うことでも、紐付けが可能です。
決済失敗カードでサブスクリプション作成
Stripe APIのSubscription createを使って、サブスクリプションの作成を行ってみましょう。
以下のサンプルコードはRubyを用いています。
Stripe::Subscription.create(
customer: 'cus_xxx',
items: [{ price: 'price_xxx' }]
)
サブスクリプションが作成されています!
サブスクリプション契約時、決済が失敗した場合のデフォルトの挙動
1. サブスクリプションは作成される
意外かもしれませんが、決済に失敗してもサブスクリプション自体は作成されます。
ただし、ステータスは active(有効) ではなく incomplete(未完了) になります。
2. Webhookイベントの違い
通常の決済成功時は invoice.paid イベントが発生しますが、決済失敗時はinvoice.payment_failedが発生します。
3. 決済失敗から失効まで
Stripeは決済失敗後、以下の流れで処理を行います
| 時間 | 挙動 |
|---|---|
| 決済失敗直後 |
subscription.status が incomplete に |
| 23時間以内 | 支払いを猶予する |
| 23時間以内に決済が成功1 |
subscription.status が active に移行 |
| 23時間経過後も決済が完了しない |
subscription.status が incomplete_expired(期限切れ)に移行 |
補足:サブスクリプションの更新時に決済が失敗した場合
新規契約ではなく、サブスクリプションの更新時に決済が失敗した場合、subscription.statusはincompleteではなくpast_due(期限超過)となります。
この場合は、上述の処理と異なり、Stripeの設定に従って自動的に支払いのリトライが行われます。
決済失敗時にサブスクリプションを作成したくない場合
決済が失敗した際に、サブスクリプションを作成せずエラーとしてユーザーに通知し、再度契約フローを踏ませたいケースもあるかと思います。
その場合、Subscription createを行う際にpayment_behaviorオプションにerror_if_incompleteを指定することで実現できます。
Stripe::Subscription.create(
customer: 'cus_xxx',
items: [{ price: 'price_xxx' }],
payment_behavior: 'error_if_incomplete'
)
実行すると、以下のようにエラーが返却され、Stripeのダッシュボードを確認しても、サブスクリプションの作成が行われていないことがわかると思います。
Your card was declined. (Stripe::CardError)
Stripe::CardErrorで捕捉可能なので、エラーハンドリングが行えます。
まとめ
- Stripeのサブスクリプション作成時、決済にたとえ失敗しても、デフォルトでは
incomplete状態でサブスクリプションが作成される -
payment_behavior: 'error_if_incomplete'を指定すると、決済失敗時にエラーを返却できる - テスト時は
4000000000000341のカード番号で、決済失敗を検証可能
実装の際には、決済の失敗についても挙動を確認した上で、適切にハンドリングするようにしましょう!👍
参考リンク
- Stripe Testing - Declined payments
- Create a subscription | Stripe API Reference
- サブスクリプションの仕組み | Stripe Docs
- 支払いの再試行を自動化する | Stripe Docs
- エラー処理 | Stripe Docs
-
支払いの猶予期間中に、ユーザーが新たな支払い方法を登録するなどすると決済をリトライします。 ↩




