Webサービスや業務システムを開発するとき、
「月額課金をStripeで実装したい」
「契約したユーザーだけ機能を利用できるようにしたい」
「解約やカード変更まで自分で実装する必要があるのか」
「Stripe側と自社データベースをどう連携すればよいのか」
と迷うことがあります。
Stripeを使えば、月額・年額などのサブスクリプション課金をWebシステムへ組み込めます。
例えば、
ユーザー登録
↓
料金プラン選択
↓
Stripe Checkoutで決済
↓
サブスクリプション開始
↓
Webhookで自社システムへ反映
↓
有料機能を利用可能
という構成です。
Stripe公式ドキュメントでも、固定料金のサブスクリプションについて、商品・価格を用意し、Checkout、Webhookによる状態監視、Customer Portalによる契約管理を組み合わせる構成が案内されています。
ただし、Stripeの決済画面を表示できればサブスク実装が完成するわけではありません。
実際のWebシステムでは、
- 誰が契約しているか
- どのプランなのか
- 支払いが成功しているか
- 解約予約されているか
- 契約終了後に機能を停止するか
- 決済失敗時にどうするか
まで自社システム側で管理する必要があります。
特に重要なのが、
Stripeを決済基盤、自社データベースをサービス利用状態の管理基盤として連携させること
です。
この記事では、Stripeでサブスク課金を実装する基本構成から、Checkout、Webhook、Customer Portal、自社DBとの連携、解約・決済失敗まで具体的に解説します。
Stripeのサブスク課金とは
Stripeでは、Stripe Billingなどの機能を利用して継続課金を管理できます。
例えば、
月額980円
月額2,980円
月額9,800円
といった料金プランを作り、ユーザーへ継続的に請求します。
一般的なSaaSなら、
Free
Starter
Business
Enterprise
のような料金体系にも利用できます。
Webシステム側では、
このユーザーは現在Businessプランを契約している
という情報を参照し、利用できる機能を切り替えます。
Stripeサブスク実装で理解したい主なデータ
Stripeを使う場合、最初に主要なデータの役割を整理すると理解しやすくなります。
Product
販売する商品・サービスです。
例えば、
「在庫管理システム」
というサービスそのものをProductとして登録します。
Price
商品の料金です。
例えば、
月額プラン:2,980円/月
年額プラン:29,800円/年
などです。
一つのProductに複数のPriceを紐づけることもできます。
Customer
Stripe上の顧客です。
自社システムのユーザーや企業と対応させます。
例えば自社DBに、
user_id:123
stripe_customer_id:cus_xxxxx
のような形でStripe側のCustomer IDを保存します。
Subscription
顧客の契約情報です。
例えば、
Customer A
↓
Businessプラン
↓
月額9,800円
↓
契約中
という情報を持ちます。
Invoice
サブスクリプションによって発生する請求情報です。
毎月の請求や支払い状況を確認するときに利用します。
Checkout Session
ユーザーが実際に申し込み・決済を行うためのセッションです。
Stripe Checkoutでは、継続課金を含む場合にCheckout Sessionのmodeへsubscriptionを指定できます。Stripeのホスト型Checkoutへユーザーを遷移させてサブスクリプションを開始する構成を取れます。
Stripeサブスク実装の基本構成
Webシステムへ組み込む場合、次のような構成が分かりやすいでしょう。
1.ユーザーがプランを選択
例えば、
Free
Starter
月額2,980円
Business
月額9,800円
という料金ページを表示します。
2.サーバー側でCheckout Sessionを作成
ユーザーが、
「Businessプランを契約」
を押したら、バックエンドからStripe APIを呼び出します。
ここで、
- Customer
- Price
- subscription mode
- 成功後URL
- キャンセル後URL
などを設定します。
3.Stripe Checkoutへ移動
ユーザーはStripeの決済画面で支払い方法を入力します。
4.StripeでSubscriptionが作成される
決済が正常に完了すると、Stripe側にサブスクリプション情報が作成されます。
5.Webhookを受信する
Stripeから自社システムへイベントが送信されます。
6.自社データベースを更新する
例えば、
plan:business
subscription_status:active
などを保存します。
7.有料機能を解放する
Businessプランで利用可能な機能を表示します。
このように、
Checkoutで申し込みを受け、Webhookで契約状態を同期する
という構成が基本になります。
Stripeサブスク実装ではWebhookが重要
Stripeのサブスクリプションでは、Webhookの設計が非常に重要です。
なぜならサブスク課金では、
- 初回決済
- 翌月の自動決済
- 決済失敗
- カード変更
- プラン変更
- 解約
- 契約終了
などがユーザーの画面操作とは別のタイミングで発生するためです。
Stripeも、サブスクリプションでは多くの処理が非同期に発生するため、Webhookイベントを利用して契約状態を管理する構成を案内しています。
なぜsuccess_urlだけでは不十分なのか
Checkoutでは決済後、
/payment/success
などへユーザーを戻せます。
ここで、
成功画面に来たから有料会員にする
という実装は避けた方がよいでしょう。
契約状態の正式な判断は、Stripe側の状態やWebhookを基準にします。
例えば、
Checkout完了
↓
Webhook受信
↓
自社DB更新
↓
有料機能開放
という流れです。
成功画面は、
「申し込みを受け付けました」
とユーザーへ表示するためのUIとして考えます。
サブスク実装で確認したい主なWebhook
すべてのStripeイベントを受信する必要はありません。
自社システムで必要なイベントだけを選びます。
代表的には次のようなイベントを検討します。
checkout.session.completed
Checkout Sessionが完了したときです。
初回申し込み後に、
- Stripe Customer ID
- Subscription ID
などを自社ユーザーへ紐づける処理に利用することがあります。
invoice.paid
請求書の支払いが成功した場合です。
継続課金で、
今回の支払いが完了した
ことを確認する際に重要になります。
Stripe公式ドキュメントでも、invoice.paidを受信して支払い済み顧客を確認し、サービス利用状態へ反映する例が示されています。
invoice.payment_failed
決済が失敗した場合です。
例えば、
- カード期限切れ
- 残高・利用枠
- 決済拒否
などで支払いに失敗する可能性があります。
Stripeはinvoice.payment_failedを、サブスクリプション請求の支払い失敗を検知する主要イベントとして案内しています。
customer.subscription.updated
サブスクリプション情報が変更された場合です。
例えば、
- プラン変更
- 解約予約
- ステータス変更
- 契約内容変更
などで利用します。
customer.subscription.deleted
サブスクリプションが終了した場合などに確認します。
有料機能を停止する処理と連携するケースがあります。
Stripeと自社データベースをどう分ける?
サブスク実装で迷いやすいのが、
契約情報をStripeだけで管理するのか
という点です。
基本的には、自社システム側にも必要な情報を保存します。
例えばUserテーブルに直接すべて入れる方法もありますが、契約を独立したテーブルで管理すると整理しやすくなります。
例えば次のような構成です。
users
id
name
email
subscriptions
id
user_id
stripe_customer_id
stripe_subscription_id
stripe_price_id
plan
status
cancel_at_period_end
created_at
updated_at
などです。
実際に何を保存するかはシステム要件によって決めます。
ポイントは、
Stripe内部の情報をすべて自社DBへコピーしないこと
です。
自社システムで頻繁に利用する情報だけ保持し、必要に応じてStripe APIから取得します。
自社ユーザーとStripe Customerを必ず紐づける
重要なのが、
自社ユーザー
↔
Stripe Customer
の対応関係です。
例えば、
user.id = 123
に対して、
stripe_customer_id = cus_ABC123
を保存します。
これにより、
StripeからWebhookが来たが、どのユーザーなのか分からない
という問題を防ぎやすくなります。
企業向けSaaSの場合は、
User
ではなく、
Organization
Company
Tenant
とStripe Customerを紐づける場合もあります。
例えば、
株式会社ABC
↓
Stripe Customer
↓
Businessプラン契約
↓
社員10人で利用
という構造です。
BtoB業務システムでは「ユーザー課金」か「会社課金」かを決める
業務システムへサブスクを組み込む場合、ここは特に重要です。
例えば、
1ユーザー月額1,000円
なのか、
1社月額10,000円
なのかでデータ構造が変わります。
ユーザー単位
User
↓
Subscription
会社単位
Organization
↓
Subscription
↓
複数User
となります。
BtoB SaaSでは、
Organization
├ Owner
├ Admin
├ Member
└ Subscription
のような構成も考えられます。
決済実装より先に、
誰と契約するサービスなのか
を決めることが重要です。
Stripeサブスクを実装する7ステップ
STEP1|料金体系を整理する
まず、
- 月額
- 年額
- 無料プラン
- 有料プラン
- ユーザー数課金
- 固定料金
- 従量課金
などを決めます。
例えば、
Free:0円
Starter:2,980円/月
Business:9,800円/月
という形です。
料金体系によってStripeの設計も変わります。
STEP2|ProductとPriceを作成する
Stripe側に商品と料金を登録します。
例えば、
Product:Business Plan
Price:9,800円/月
です。
アプリケーション側ではPrice IDを利用してCheckout Sessionを作成します。
STEP3|自社ユーザーとCustomerを紐づける
Stripe Customerを作成し、自社DBへCustomer IDを保存します。
例えば、
stripe_customer_id
という項目です。
STEP4|Checkoutを実装する
料金ページに、
「申し込む」
ボタンを用意します。
押下するとバックエンドでCheckout Sessionを作成し、Stripe Checkoutへ遷移します。
STEP5|Webhookを実装する
Stripeから、
- 契約
- 支払い
- 解約
などのイベントを受け取ります。
Webhookを受信したら、自社DBの契約情報を更新します。
STEP6|利用可能機能を制御する
例えば、
Free
→ 月10件まで
Starter
→ 月1,000件まで
Business
→ 無制限
という制御です。
ログインユーザーの契約プランを確認し、利用可能な機能を判断します。
STEP7|契約変更・解約を実装する
契約後には、
- 支払い方法変更
- プラン変更
- 請求履歴確認
- 解約
なども必要になります。
自作するかCustomer Portalを利用するかを決めます。
Customer Portalを活用する
StripeにはCustomer Portalがあります。
これを利用すると、ユーザー自身で、
- 支払い情報の変更
- 支払い方法変更
- サブスクリプション変更
- サブスクリプション解約
- 請求書確認・ダウンロード
などを行える構成を取れます。Stripe公式でも、Customer Portalは支払い情報・請求書・サブスクリプションを顧客自身が管理するためのStripeホスト型UIとして提供されています。
例えばアプリ内に、
「契約・支払い設定」
というボタンを用意します。
押下
↓
サーバー側でPortal Session作成
↓
Stripe Customer Portalへ移動
という流れです。
契約管理画面を全部自作する必要はない
サブスクサービスを作ると、
- カード変更画面
- 解約画面
- 請求履歴
- プラン変更
- 支払い方法管理
をすべて自作しようとしがちです。
しかし、標準的な契約管理ならCustomer Portalを利用できる場合があります。
自社システムでは、
料金ページ
契約状況表示
Customer Portalへの入口
だけ用意する構成も可能です。
独自UIが本当に必要かを考えてから実装すると、開発範囲を抑えられます。
Stripeサブスクの解約をどう実装する?
解約には大きく、
- 即時解約
- 契約期間終了時に解約
という考え方があります。
例えば月額契約で、
7月15日に解約申請
↓
7月31日までは利用可能
↓
8月1日から利用不可
とするサービスなら、期間終了時解約を利用します。
システム側では、
status:active
cancel_at_period_end:true
のように、現在利用できる状態と「解約予定」を分けて表示する設計が考えられます。
Customer Portalでも、設定に応じて即時解約や現在の請求期間終了時の解約をユーザーへ提供できます。
「解約ボタンを押した瞬間」に利用停止しないケースがある
よくある実装ミスが、
解約申請
↓
即座に無料プランへ変更
という処理です。
しかし、
月末まで料金を支払っているので、それまでは利用可能
という契約なら、すぐに利用停止してはいけません。
そのため、
解約申請日
と、
実際の契約終了日
を分けて考えます。
決済失敗時の処理も設計する
サブスクでは初回決済だけでなく、翌月以降の決済があります。
カードの状態によっては決済に失敗することがあります。
例えば、
Businessプラン利用中
↓
翌月決済失敗
↓
invoice.payment_failed
↓
ユーザーへ通知
↓
支払い方法更新
↓
再決済
という流れです。
ここで、
決済失敗した瞬間に全機能停止
とするのか、
数日間の猶予期間を設ける
のかはサービス側のルールです。
Stripe側の決済状態だけでなく、自社サービスの利用ポリシーとして決めておきます。
サブスクリプション状態と利用権限を分けて考える
例えばStripe上の契約状態をそのまま画面表示条件へ使う方法もあります。
しかし実際には、
契約状態
+
サービス側ルール
によって利用可否を決める場合があります。
例えば、
active
通常利用可能。
trialing
無料トライアルとして利用可能。
支払いに問題がある状態
一定期間だけ利用可能。
契約終了
利用不可またはFreeプランへ変更。
などです。
つまり、
Stripeのstatus = 自社サービスの権限
と単純に固定しない方が設計しやすい場合があります。
プランごとの権限をどう実装する?
例えば、
Free
Starter
Business
という3プランがあるとします。
機能を、
Free
顧客100件まで
CSV出力不可
Starter
顧客1,000件まで
CSV出力可能
Business
顧客数無制限
API利用可能
高度な権限管理
とします。
このとき画面側だけ、
BusinessユーザーだけAPIボタン表示
とするのでは不十分です。
バックエンドでも、
このOrganizationはBusinessプランか
を確認します。
権限管理と同じように、サーバー側で利用可否を判定することが重要です。
プラン名をコードへ直接書きすぎない
例えばコード中に、
if plan === "business"
を大量に書くと、料金プラン変更時に修正箇所が増えます。
そこで、
- FEATURE_EXPORT_CSV
- FEATURE_API_ACCESS
- MAX_CUSTOMERS
など、機能単位で管理する方法があります。
例えば、
Free
→ CSV_EXPORT = false
Starter
→ CSV_EXPORT = true
Business
→ CSV_EXPORT = true
という考え方です。
将来的に料金プランが増えても変更しやすくなります。
Webhookは署名検証する
Webhook URLはインターネットからアクセスできるため、
Stripeから届いたように見える偽リクエスト
をそのまま信用してはいけません。
StripeはStripe-SignatureヘッダーとWebhook endpoint secretを利用して、受信したWebhookがStripeから送信されたものか検証する方法を提供しています。公式ライブラリによる署名検証が推奨されています。
つまり、
Webhook受信
↓
署名検証
↓
正常ならイベント処理
という流れにします。
Webhookの重複処理にも注意する
Webhookでは、同じイベントを複数回受信する可能性があります。
そのため、
invoice.paid受信
↓
ポイント100付与
という処理を単純に書くと、重複イベントによってポイントを二重付与する可能性があります。
Stripeは、処理済みのEvent IDを記録し、同じイベントを再処理しない方法をベストプラクティスとして案内しています。
例えば、
stripe_event_id
を保存して、
すでに処理済み
→ スキップ
未処理
→ 処理してEvent ID保存
とします。
Webhookの到着順を前提にしない
さらに重要なのがイベント順序です。
例えば、
customer.subscription.created
↓
invoice.created
↓
invoice.paid
という順番を想定してコードを書きたくなります。
しかしStripeは、Webhookイベントが生成された順番どおりに配信されることを保証していません。必要な場合は受信イベントの情報を使ってStripe APIから最新オブジェクトを取得する設計が推奨されます。
そのため、
必ずイベントAの後にイベントBが来る
という前提で設計しないことが重要です。
Stripe API呼び出しでは冪等性も考える
例えばユーザーが、
「契約する」
ボタンを連打した場合、
Checkout SessionやCustomerを重複作成してしまう設計は避けたいところです。
Stripe APIでは、POSTリクエストでIdempotency Keyを利用し、通信エラーなどによる再試行時の重複処理を防ぐ仕組みがあります。
自社システム側でも、
- 二重クリック防止
- 重複契約チェック
- 処理中ステータス
などを組み合わせます。
Stripeの秘密鍵をフロントエンドへ置かない
Stripeでは、
公開可能なキー
と、
サーバー側で管理すべき秘密鍵
を分けます。
秘密鍵をJavaScriptへ直接記述し、ブラウザから確認できる状態にしてはいけません。
例えばNext.jsなら、
ブラウザ
↓
自社API
↓
Stripe API
という構成にします。
Customer作成、Checkout Session作成などの重要処理はサーバー側で行います。
Stripeサブスク実装のデータ構造例
例えばBtoB SaaSなら、次のような構成があります。
organizations
id
name
owner_user_id
users
id
organization_id
name
email
role
subscriptions
id
organization_id
stripe_customer_id
stripe_subscription_id
stripe_price_id
plan_code
status
cancel_at_period_end
created_at
updated_at
stripe_events
id
stripe_event_id
event_type
processed_at
とします。
これにより、
Organization
↓
Subscription
↓
Stripe
を紐づけられます。
Webhookの重複防止用にイベントIDを管理することもできます。
【コピペ用】Stripeサブスク実装設計シート
サービス基本情報
サービス名:
課金対象:
個人:
法人:
料金体系
Free:
Starter:
Business:
月額:
年額:
従量課金:
Stripe
Product:
Price:
Customer:
Subscription:
自社DB
stripe_customer_id:
stripe_subscription_id:
stripe_price_id:
plan:
status:
cancel_at_period_end:
Checkout
料金ページ:
Checkout Session:
成功ページ:
キャンセルページ:
Webhook
checkout.session.completed:
invoice.paid:
invoice.payment_failed:
customer.subscription.updated:
customer.subscription.deleted:
契約変更
プランアップ:
プランダウン:
即時解約:
期間終了時解約:
決済失敗
ユーザー通知:
猶予期間:
機能停止:
Customer Portal
カード変更:
プラン変更:
解約:
請求履歴:
権限
Free機能:
Starter機能:
Business機能:
セキュリティ
Webhook署名検証:
Event重複処理:
秘密鍵管理:
操作ログ:
Stripeサブスク実装の具体例|業務管理SaaS
例えば案件管理システムを提供するとします。
料金体系は、
Free
月額0円
案件10件まで
Standard
月額4,980円
案件1,000件まで
CSV出力可能
Business
月額9,800円
案件無制限
API利用可能
権限管理可能
とします。
ユーザー登録時はFreeです。
有料申し込み時に、
料金ページ
↓
Stripe Checkout
↓
Webhook
↓
OrganizationのSubscription更新
↓
機能解放
とします。
Businessプランへ変更すると、
API利用
権限管理
などが利用可能になります。
Stripeサブスク実装の具体例|会員制サービス
例えばオンライン会員サービスなら、
無料会員
↓
月額会員へ登録
↓
Stripe Checkout
↓
支払い成功
↓
有料コンテンツ開放
とできます。
解約した場合は、
解約予約
↓
契約終了日までは利用可能
↓
Subscription終了
↓
無料会員へ戻す
という設計が考えられます。
Stripeサブスク実装でよくある失敗
失敗1|成功ページだけで契約済みにする
ブラウザ遷移だけを契約状態の根拠にしません。
Stripeの状態・Webhookを利用して同期します。
失敗2|Stripe Customerと自社ユーザーが紐づいていない
Webhookを受信しても対象ユーザーを特定できなくなります。
Customer IDを適切に管理します。
失敗3|初回決済しか考えていない
サブスクでは、
- 翌月決済
- 決済失敗
- 解約
- プラン変更
まで設計する必要があります。
失敗4|解約した瞬間に利用停止する
契約期間終了時解約なら、終了日まで利用できる場合があります。
自社サービスの契約ルールと合わせます。
失敗5|Webhookを何度受信しても同じ処理を実行する
Webhookは重複する可能性があります。
イベントIDなどを利用して重複処理を防ぎます。
失敗6|Webhookの到着順に依存する
イベント順序は保証されません。
必要に応じてStripe APIから最新状態を取得します。
失敗7|Webhook署名を確認しない
Webhookを受信したらStripeから送信されたイベントか検証します。
失敗8|契約管理画面をすべて自作する
標準的な支払い方法変更や解約であれば、Customer Portalで対応できる場合があります。
失敗9|プラン変更時の機能制御を考えていない
Stripe上ではプラン変更できても、自社システム側の利用権限が変わらなければ意味がありません。
失敗10|テスト環境と本番環境を混同する
APIキーやWebhook Secretなどは環境ごとに適切に分離します。
本番前に、
- 新規契約
- 更新
- 決済失敗
- 解約
- プラン変更
などをテストします。
Stripeを使う場合でも利用規約・契約条件を整理する
技術的にサブスクを実装できても、サービス側の契約条件が曖昧だとシステム仕様を決められません。
例えば、
- いつ課金するか
- 自動更新するか
- 解約期限
- 解約後いつまで利用可能か
- 日割りするか
- プラン変更時の料金
- 返金ルール
- 無料期間
などです。
特に、
解約ボタンを押したら何が起こるか
は技術ではなくサービス側のルールです。
先に契約ルールを整理し、そのルールをStripeへ落とし込みます。
Stripe Checkoutと独自決済画面はどちらがよい?
Webサービスでは、決済UIを完全に独自で作りたい場合もあります。
しかし、初期開発ではStripe Checkoutを利用する方法があります。
Stripe Checkoutにはホスト型、埋め込みなどのUIモードが用意されており、サブスクリプションにも利用できます。
Checkoutが向いているケース
- 早く導入したい
- 標準的な決済画面で問題ない
- 決済UIの開発範囲を減らしたい
独自UIを検討するケース
- 特殊な購入フロー
- 高度なUI統合
- 独自の契約手続き
などです。
まずCheckoutで始め、必要になった段階で高度な構成へ移行する方法もあります。
Stripe導入前に整理したいのは「決済」より「契約状態」
Stripeサブスク実装というと、
クレジットカードで毎月決済する機能
に注目しがちです。
しかし業務システムで本当に重要なのは、
現在この顧客がサービスを利用してよい状態なのか
を判定することです。
例えば、
新規登録
↓
無料
契約
↓
有料
決済失敗
↓
支払い確認中
解約予約
↓
契約期間終了までは有料
契約終了
↓
無料
という状態遷移があります。
決済画面よりも、この状態管理を先に整理すると実装しやすくなります。
Stripeサブスク実装に関するよくある質問
Stripeで月額課金を実装できますか?
できます。
Stripe BillingやCheckoutなどを利用して、月額・年額などの継続課金を構成できます。Stripe公式でもCheckoutによる固定料金サブスクリプションの実装方法が案内されています。
Stripe Checkoutだけでサブスク実装できますか?
申し込み・決済には利用できますが、Webサービス側では契約状態を反映する処理が必要です。
Webhook、自社DB、利用権限制御などもあわせて設計します。
解約画面を自分で作る必要がありますか?
必ずしもありません。
Customer Portalを利用して、ユーザー自身に契約・支払い情報を管理してもらう方法があります。
決済失敗はどうやって検知しますか?
invoice.payment_failedなどのWebhookイベントを利用して検知する方法があります。
Webhookは必須ですか?
サブスクリプションでは支払い・契約変更などが非同期に発生するため、実運用ではWebhookを中心に状態を同期する構成が重要です。Stripeもサブスクリプション管理にWebhookを利用する方法を案内しています。
自社DBにも契約情報を保存するべきですか?
一般的には、自社サービスの表示・権限制御に必要な情報を保存すると扱いやすくなります。
ただし、Stripe上の全情報をコピーする必要はありません。
Next.jsでもStripeサブスクを実装できますか?
可能です。
例えば、
Next.js
↓
Route Handler・バックエンドAPI
↓
Stripe API
↓
Webhook
↓
PostgreSQL
といった構成が考えられます。
重要なのはフレームワークよりも、秘密鍵をサーバー側で扱い、Webhookと契約状態を適切に設計することです。
hiro-dev-labではStripeを含む課金機能の設計から相談できます
hiro-dev-labでは、Stripe APIを接続するだけでなく、サブスクリプションを業務システムへどう組み込むかという段階から相談できます。
例えば、
- 料金プラン整理
- 月額・年額課金設計
- ユーザー・企業単位の契約設計
- Stripe Checkout
- Stripe Customer管理
- Subscription管理
- Webhook設計
- Customer Portal
- 解約フロー
- 決済失敗時の処理
- プラン変更
- 有料機能の権限制御
- 自社データベースとの連携
- 要求整理
- 業務要件・機能要件整理
- Webシステム設計・開発
などです。
例えば、
SaaSへ月額課金を付けたい
契約ユーザーだけ機能を利用できるようにしたい
Stripe側と自社DBをどう同期すればよいか分からない
解約・決済失敗まで考えた設計にしたい
BtoBの会社単位課金を実装したい
という場合でも、
料金体系 → 契約単位 → Stripe構成 → 自社DB → Webhook → 利用権限
の順番で整理できます。
まとめ|Stripeのサブスク実装は「決済画面」より「契約状態の同期」が重要
Stripeでサブスク課金を実装するとき、
「Checkoutでカード決済できた」
だけでは完成ではありません。
まず、
- 誰に課金するのか
- どんな料金プランなのか
- Stripe Customerと誰を紐づけるのか
- どのSubscriptionを契約中と判断するのか
- Webhookをどう処理するのか
- 決済失敗時にどうするのか
- 解約後いつまで利用できるのか
- プランごとにどの機能を利用できるのか
を整理します。
基本構成としては、
ユーザー・企業
↓
料金プラン選択
↓
Stripe Checkout
↓
Subscription作成
↓
Webhook
↓
自社DB更新
↓
利用機能を制御
という流れになります。
また契約後の、
- 支払い方法変更
- 請求履歴
- プラン変更
- 解約
についてはCustomer Portalを活用することで、独自実装する範囲を減らせる場合があります。
特に重要なのは、
Stripeを唯一の画面表示用データベースとして扱うのではなく、自社システムの契約状態と正しく同期させること
です。
その中心になるのがWebhookです。
Webhookでは、
- 署名検証
- 重複イベントへの対応
- イベント順序へ依存しない設計
まで考えます。StripeもこれらをWebhook実装上の重要なベストプラクティスとして案内しています。
「Stripeで毎月決済できるようにする」
だけで考えるのではなく、
契約開始 → 継続課金 → 決済失敗 → プラン変更 → 解約 → 契約終了
までを一つの業務フローとして設計することが、安定したサブスクリプション実装につながります。