Skip to content

[Billing] Webhook ハンドラ & Firestore 同期 #51

Description

@yuuka-dev

概要

Firebase Functions で Stripe Webhook 受信 → Firestore users ドキュメントの planType を同期。

APIエンドポイント

  • POST /v1/stripe/webhook — Stripe イベント受信(認証なし、Stripe webhook signature で検証)

対象イベント

イベント 処理
checkout.session.completed planType: 'subscriber'stripeCustomerIdstripeSubscriptionId を保存。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 コレクション(eventIdprocessedAt)で処理済みイベントを管理
  • 処理済みイベントはスキップ
  • TTL: 30日

データモデル変更(users コレクション)

planType: 'free' | 'subscriber' | 'premium'  // premium は将来用・未実装
stripeCustomerId: string | null
stripeSubscriptionId: string | null
trialEndsAt: Timestamp | null
  • 既存の adFree: booleanplanType に移行(マイグレーション必要)

受け入れ条件

  • Stripe CLI テストイベント正常処理
  • checkout.session.completed で planType が subscriber に更新される
  • invoice.paid でトライアル→本課金移行が確認できる
  • 解約で即座に planType が free に戻る
  • 支払い失敗で即座に planType が free に戻る
  • 同一イベントの重複処理がスキップされる
  • 不正な署名のリクエストを拒否

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions