5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Stripe】サブスクリプション作成時に決済が失敗した場合の挙動と検証方法

Last updated at Posted at 2025-12-18

このエントリーは with Advent Calendar 2025 の 19日目の記事です。


Stripeでサブスクリプション決済を実装する際、こんな疑問を持ったことはないでしょうか?🤔

  • サブスクリプションの契約時に決済が失敗したら、どんな挙動になるのか?
  • テスト環境で決済失敗のケースを検証するにはどうすればいいのか?

本記事では、Stripeのテスト環境で決済失敗時の挙動を検証した結果と、その方法について共有します。

テスト用の決済失敗カード

Stripeのテスト環境では、基本的に決済が成功するテストカード(4242424242424242など)を使用します。しかし、以下のカード番号を使うと、Customerへの紐付けは成功するが、決済時に失敗するという挙動を再現できます。

カード番号 挙動
4000000000000341 カードの紐付けは成功するが、決済時に拒否される

検証フロー

テストカードをCustomerに紐づける

検証に用いる顧客データの支払い方法に、テストカードを紐づけます。
セキュリティの制限により、Stripe APIに直接カード番号を送信することはできないので、Stripeのダッシュボードから紐付けを行うことを推奨します。

image.png

テストを行う顧客の詳細から、支払い方法カードを追加 でカード情報を追加します。

image.png
決済に失敗するテストカード番号を入力して、追加!

image.png
無事、紐付けに成功しました🎉

Customer Portalからの更新

なお、ダッシュボードからの紐付けではなく、Customer Portalを用いて決済手段の更新を行うことでも、紐付けが可能です。

image.png

決済失敗カードでサブスクリプション作成

Stripe APIのSubscription createを使って、サブスクリプションの作成を行ってみましょう。
以下のサンプルコードはRubyを用いています。

Stripe::Subscription.create(
  customer: 'cus_xxx',
  items: [{ price: 'price_xxx' }]
)

実行し、stripeのダッシュボードを確認すると...
image.png

サブスクリプションが作成されています!

サブスクリプション契約時、決済が失敗した場合のデフォルトの挙動

1. サブスクリプションは作成される

意外かもしれませんが、決済に失敗してもサブスクリプション自体は作成されます
ただし、ステータスは active(有効) ではなく incomplete(未完了) になります。

2. Webhookイベントの違い

通常の決済成功時は invoice.paid イベントが発生しますが、決済失敗時はinvoice.payment_failedが発生します。

3. 決済失敗から失効まで

Stripeは決済失敗後、以下の流れで処理を行います

時間 挙動
決済失敗直後 subscription.statusincomplete
23時間以内 支払いを猶予する
23時間以内に決済が成功1 subscription.statusactive に移行
23時間経過後も決済が完了しない subscription.statusincomplete_expired(期限切れ)に移行

補足:サブスクリプションの更新時に決済が失敗した場合

新規契約ではなく、サブスクリプションの更新時に決済が失敗した場合、subscription.statusincompleteではなく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 のカード番号で、決済失敗を検証可能

実装の際には、決済の失敗についても挙動を確認した上で、適切にハンドリングするようにしましょう!👍

参考リンク

  1. 支払いの猶予期間中に、ユーザーが新たな支払い方法を登録するなどすると決済をリトライします。

5
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?