Stripeでサブスクリプションを追加する方法:プラン、トライアル、Webhook、支払い失敗への対応
Stripeでサブスクリプションを追加するには、Stripeダッシュボードで定期価格を持つ商品を作成し、サーバーからサブスクリプションモードのStripe Checkoutへ顧客を送り、Webhookで各支払いの成功、失敗、変更、終了をアプリに伝えます。アクセス権は、完了ページではなく、利用者に紐づけて保存したサブスクリプションのステータスに基づいて付与してください。「請求を管理」ボタンを追加して、Stripeがホストするカスタマーポータルを開くようにすると、利用者はカードの変更、プランの切り替え、解約を、こちらで画面を作らずに行えます。
このガイドは、アプリに決済を追加する方法の内容を前提としています。そちらでは、単発のCheckout、テストモード、本番公開を扱っています。ここでは、定期課金ならではの違いに焦点を当てます。Stripeの詳細は、2026年9月時点のStripeのドキュメントに基づいています。
サブスクリプションが単発の支払いより難しい理由
単発の支払いは、顧客がアプリにいる間に行われます。一方、サブスクリプションは、顧客がアプリを離れた後も続きます。毎月の更新、期限切れになるカード、期間の途中でのアップグレード、期間の終わりに効力を持つ解約などが発生します。アプリはこれらを、Webhookを通じてのみ知ります。サブスクリプションのバグの多くは、最初の支払いをすべての話だと考えてしまうことから生じます。
選択肢
| 方法 | 構築するもの | 向いている用途 |
|---|---|---|
| 定期価格付きのPayment Link | リンクだけ | 需要の検証。アクセスを手作業で管理する場合 |
| Checkout(サブスクリプションモード)+カスタマーポータル | サーバーのルート、Webhook、請求ボタン | ほとんどのSaaSアプリや会員制 |
| 独自の支払いフォームを使うSubscriptions API | 支払いのUI、認証、再試行など、はるかに多くのもの | 特殊な請求フローのあるアプリ |
| マーチャント・オブ・レコードのプロバイダー | Checkoutに似ている | 売上税の処理をプロバイダーに任せたい販売者 |
ほとんどのアプリにとっては、Checkoutとポータルの組み合わせが適切なトレードオフです。税務の扱いが気がかりなら、Stripe vs Paddle vs Lemon Squeezyでプロバイダーを比較してください。
まずStripeで料金体系を設計する
Stripeでは、商品は売るもの(「Proプラン」)であり、価格はそれをどう課金するか(「月額20ドル」「年額200ドル」)です。1つの商品に複数の価格を設定できます。次の点を決めてください。
- 提供するプランと、それぞれがアプリでどの機能を解除するか
- 月払い、年払い、またはその両方
- トライアルを提供するかどうか、そして最初にカードが必要かどうか
商品と価格はテストモードで作成し、その価格IDを控えておいてください。アプリはそのIDを参照します。料金がまだ決まっていなければ、SaaS製品の価格設定方法とフリーミアムと無料トライアルを読んでください。
対応すべきサブスクリプションのライフサイクル
Stripeのサブスクリプションの概要には、サブスクリプションが取り得るステータスが列挙されています。アクセス権に最も関係するものは次のとおりです。
| ステータス | 意味 | アクセスを付与するか |
|---|---|---|
trialing | トライアル期間中 | はい |
active | 正常な状態 | はい |
incomplete | 最初の支払いがまだ完了していない。Stripeは顧客に23時間を与える | いいえ |
incomplete_expired | 最初の支払いが一度も成功しなかった | いいえ |
past_due | 直近の支払いが失敗したか、試行されていない。再試行が続く場合がある | 任意。多くのアプリは短い猶予期間を設ける |
unpaid | 再試行が終わり、請求書は未払いのまま、それ以上の試行は行われない | いいえ。Stripeのドキュメントではアクセスを取り消すよう述べている |
canceled | 終了した。再開はできない | いいえ |
paused | 支払い方法がないままトライアルが終了し、一時停止に設定された | いいえ |
ステータスは利用者またはアカウントのレコードに保存し、アクセス権はそれに基づいて判断してください。関連するWebhookが届くたびに、ステータスを更新してください。
処理すべきWebhookイベント
| イベント | アプリの処理 |
|---|---|
checkout.session.completed | 新しいStripeの顧客IDとサブスクリプションIDを、利用者に紐づける |
invoice.paid | サブスクリプションを有効にし、新しい期間の終了日を記録する |
invoice.payment_failed | カードが失敗したことを利用者に伝え、ポータルへのリンクを示す |
invoice.payment_action_required | カードの認証を完了するよう利用者に求める |
customer.subscription.updated | プラン、ステータス、予定されている解約を更新する |
customer.subscription.deleted | 有料アクセスを削除する |
customer.subscription.trial_will_end | トライアル終了前に利用者にリマインドする。Stripeは3日前に送信する |
StripeのWebhookドキュメントのハンドラーの規則は、今も有効です。署名は生のボディを使って検証し、素早く2xxを返し、重複や順序の入れ替わったイベントを扱い、再送を想定してください。Webhookとはでは基本的な考え方を説明しており、決済のガイドでは規則を詳しく列挙しています。
ステップごとの進め方
- Stripeのテストモードで商品と価格を作成します。
- シークレットを追加します。シークレットキー、価格ID、そして後からWebhookの署名シークレットを追加します。フロントエンドのコードには決して入れないでください。
- 料金ページ:各プランのボタンがサーバーを呼び出し、サーバーがログイン中の利用者のためにサブスクリプションモードのCheckout Sessionを作成します。支払いをアカウントに結びつけられるように、ユーザーIDを渡してください。
- Webhookエンドポイント:署名を検証し、上記のイベントを処理して、利用者ごとに1つのサブスクリプションのレコードを更新します。
- 機能の解除をステータスとプランに基づいて行い、保護されたすべての操作でサーバー側で確認します。ボタンを隠すだけにはしないでください。
- カスタマーポータル:Stripeダッシュボードで設定します(利用者が切り替えられるプラン、解約できるかどうか)。そのうえで「請求を管理」ボタンを追加し、サーバーでポータルのセッションを作成してそこにリダイレクトします。
- 支払いの失敗:Stripeの請求設定で、再試行の動作と、最後の再試行の後の扱いを選びます。
past_dueの間は、アプリ内にバナーを表示してください。 - ライフサイクル全体をテストし、そのあとに公開して、本番のWebhookを登録します。
AIビルダーに与えるプロンプト
Stripeでサブスクリプション課金を追加してください。プランは、Starter(価格IDは STRIPE_PRICE_STARTER)と Pro(STRIPE_PRICE_PRO)です。料金ページは、サーバー上でサブスクリプションモードのCheckout Sessionを作成します。STRIPE_SECRET_KEY を使い、ログイン中の利用者のIDを添付してください。利用者には、Stripeの顧客ID、サブスクリプションID、プラン、ステータスを保存してください。シークレットキーをブラウザに決して公開しないでください。
POST /api/stripe/webhook を追加してください。生のリクエストボディを使い、STRIPE_WEBHOOK_SECRET で署名を検証してください。checkout.session.completed、invoice.paid、invoice.payment_failed、customer.subscription.updated、customer.subscription.deleted、customer.subscription.trial_will_end を処理してください。処理済みのイベントIDを記録し、重複を無視してください。利用者のステータスは、届いた順序ではなく、サブスクリプションのオブジェクトから更新してください。
Proの機能をサーバー側で制限してください。ステータスが active または trialing で、かつプランが Pro の場合のみ許可します。ステータスが past_due のときは、「支払いに失敗しました。カードを更新してください」というバナーを表示してください。この利用者向けに、Stripeのカスタマーポータルを開く「請求を管理」ボタンを追加してください。
アップグレード、ダウングレード、日割り計算
顧客がプランを切り替えると、Stripeのドキュメントによれば、変更により**日割り計算(プロレーション)**が発生することがよくあります。新しい価格が、現在の請求期間の残りに適用されます。日割り計算はプレビューするか、オフにできます。プランの請求間隔が同じなら、請求日は変わりません。月払いから年払いに変えると、請求日は切り替えた日に移ります。ポータルで利用者にプランの変更を許可すれば、このロジックを自分で書く必要がなくなります。ただし、どの切り替えを許可するかは、ポータルの設定で決めてください。
テストのチェックリスト
Stripeのテストモードとテスト用カードを使い、すべての状態を確認してください。
- 新しいサブスクリプションで、正しい利用者に正しいプランが付与される
- 支払い直後にタブを閉じても、アクセスが付与される(Webhookが機能していることの確認になります)
- サインアップ時にカードが拒否されると、何も付与されない
- 更新が失敗すると、アカウントが past_due になり、バナーが表示される
- ポータルでカードを更新すると、active の状態に戻る
- アップグレードとダウングレードで、機能が正しく変わる
- 期間の終わりに解約すると、終了日までアクセスが残り、その後削除される
- トライアルの利用者はアクセスでき、リマインダーを受け取り、正しく有料に移行するか、アクセスを失う
- 同じWebhookイベントを2回送っても、何も変わらない
Stripeのテストクロックを使うと、時間の経過をシミュレートできるため、1か月待たずに更新をテストできます。使い方は、Stripeの最新のテストのドキュメントを確認してください。
よくある間違い
- 完了ページでアクセスを付与する。 顧客は支払いを済ませても、そのページに到達しないことがあります。Webhookを使ってください。
- 最初の支払いしか処理しない。 更新、失敗、解約は後からイベントとして届きます。
- プランの状態をフロントエンドでだけ確認する。 誰でもAPIを直接呼び出せます。
- 誤って1人の利用者が複数のサブスクリプションを持つ。 新しいCheckout Sessionを作成する前に既存のサブスクリプションを確認するか、既存の顧客はポータルに案内してください。
- 最初の更新の失敗でアクセスを取り消す。 カードの失敗はつまらない理由で起こります。短い猶予期間と、わかりやすいバナーがあれば、顧客を失わずに済みます。
- 本番のWebhookを登録し忘れる。 テスト用と本番用のエンドポイントには、別々の署名シークレットがあります。
- 税金と返金を無視する。 公開前に返金ポリシーを決め、税務上の義務について会計士に確認してください。
Mythexでのサブスクリプション
Mythexで構築したアプリは、ご自身のStripeアカウントとキーを使います。アプリ向けにStripeをワンクリックで接続する機能はありません。テストキーと価格IDをプロジェクトのシークレットとして追加し、上記のようなプロンプトを使い、プレビューでStripeのテスト用カードを使ってテストしてください。Webhookにはアプリの公開URLが必要なので、Stripeにエンドポイントを登録する前に公開してください。本番キーに切り替えた後は、本番のアプリが新しいキーを読み込めるように、もう一度公開してください。詳しくは、Stripeで決済を受け付けるとバックエンドでWebhookを処理するを参照してください。課金の周辺で何を作るかについては、SaaS MVPの作り方で説明しています。
よくある質問
Stripeでサブスクリプションを追加する最も簡単な方法は何ですか?
Stripeダッシュボードで、定期価格を持つ商品を作成します。サーバーから、サブスクリプションモードのStripe Checkoutへ顧客を送り、サブスクリプションのイベントはWebhookで処理します。そして「請求を管理」ボタンを、Stripeがホストするカスタマーポータルにリンクします。これにより、カードのフォームやプラン変更の画面を自分で作る必要がなくなります。
サブスクリプションには、どのStripe Webhookイベントが必要ですか?
最低限、新しいサブスクリプションを利用者に紐づけるための checkout.session.completed、各支払いの成功を確認するための invoice.paid、更新の失敗を警告するための invoice.payment_failed、そしてプラン変更と解約を追跡するための customer.subscription.updated と customer.subscription.deleted が必要です。
サブスクリプションの支払いが失敗するとどうなりますか?
2026年9月時点のStripeのドキュメントによると、通常、サブスクリプションは past_due(支払い遅延)の状態になり、Stripeは設定に基づいて支払いを再試行できます。最後の再試行の後は、ダッシュボードの設定によって、キャンセルされるか、未払い(unpaid)になるか、past_due のままになるかが決まります。
カードの登録なしで無料トライアルを提供できますか?
はい。Stripeは無料トライアルに対応しており、そのドキュメントでは、支払い方法がないままトライアルが終わった場合に、設定によって一時停止(paused)の状態になることも説明されています。最初にカードを登録してもらうと、登録数は減りがちですが、有料顧客は増えやすくなります。ご自身の製品に合う方法をテストしてください。