概要
Firebase Functions で Stripe Webhook 受信 → Firestore users ドキュメントの planType を同期。
APIエンドポイント
POST /v1/stripe/webhook — Stripe イベント受信(認証なし、Stripe webhook signature で検証)
対象イベント
| イベント |
処理 |
checkout.session.completed |
planType: 'subscriber'、stripeCustomerId、stripeSubscriptionId を保存。subscription から trial_end を取得し trialEndsAt に保存 |
invoice.paid |
planType: 'subscriber' を確認・維持(トライアル→本課金移行の確認) |
customer.subscription.deleted |
planType: 'free' に戻す(解約) |
invoice.payment_failed |
planType: 'free' に戻す(支払い失敗) |
仕様
- 解約時: 即座に
planType: 'free' に戻す(期間末まで維持しない)
- 支払い失敗時: 即座に
planType: 'free' に戻す(リトライ期間なし)
- 署名検証: Stripe webhook signing secret で全リクエストを検証
- trialEndsAt: subscription オブジェクトの
trial_end から取得
冪等性対応
- Stripe は同一イベントを複数回送信する可能性がある
processedStripeEvents コレクション(eventId → processedAt)で処理済みイベントを管理
- 処理済みイベントはスキップ
- TTL: 30日
データモデル変更(users コレクション)
planType: 'free' | 'subscriber' | 'premium' // premium は将来用・未実装
stripeCustomerId: string | null
stripeSubscriptionId: string | null
trialEndsAt: Timestamp | null
- 既存の
adFree: boolean を planType に移行(マイグレーション必要)
受け入れ条件
概要
Firebase Functions で Stripe Webhook 受信 → Firestore users ドキュメントの planType を同期。
APIエンドポイント
POST /v1/stripe/webhook— Stripe イベント受信(認証なし、Stripe webhook signature で検証)対象イベント
checkout.session.completedplanType: 'subscriber'、stripeCustomerId、stripeSubscriptionIdを保存。subscription からtrial_endを取得しtrialEndsAtに保存invoice.paidplanType: 'subscriber'を確認・維持(トライアル→本課金移行の確認)customer.subscription.deletedplanType: 'free'に戻す(解約)invoice.payment_failedplanType: 'free'に戻す(支払い失敗)仕様
planType: 'free'に戻す(期間末まで維持しない)planType: 'free'に戻す(リトライ期間なし)trial_endから取得冪等性対応
processedStripeEventsコレクション(eventId→processedAt)で処理済みイベントを管理データモデル変更(users コレクション)
adFree: booleanをplanTypeに移行(マイグレーション必要)受け入れ条件