カスタムプラン(Custom Contract)

概要

本ドキュメントは、Stripe Checkout の price_data を用いた カスタムプラン(契約ベース価格)のフローを説明します。カスタムプランはベースプランの価格マッピングと分離し、既存の価格カタログや標準のプラン変更フローに影響を与えない設計です。

主要データモデル

subscriptions

  • pricing_type: custom
  • custom_contract_id: 契約への参照
  • payment_provider_subscription_id: Stripe sub_...

custom_contracts

  • 契約条件: amount, currency, billing_interval, starts_at, ends_at, 各種制限
  • Stripe 連携項目:
    • provider_checkout_session_id (Stripe cs_...)
    • provider_price_id (Stripe price_...)
    • provider_subscription_item_id (Stripe si_...)

subscription_histories

請求ごとのスナップショット:

  • custom_contract_id
  • provider_price_id
  • provider_subscription_item_id
  • invoice_id / payment_intent_id

フロー全体

1) カスタム契約の作成(Admin)

API:

  • POST /api/v1/admin/custom-contracts

ロジック:

  • draft 状態で契約を作成
  • 既存 subscription に紐付けるか、pricing_type = custom の subscription を新規作成

2) 支払いリンク送信(Admin)

API:

  • POST /api/v1/admin/custom-contracts/{id}/send-payment-link

ロジック:

  • price_data で Stripe Checkout Session を作成
  • metadata 設定:
    • custom_contract_id
    • subscription_slug
  • custom_contracts.provider_checkout_session_id を更新
  • ステータス draftoffered

3) Stripe Webhook(Checkout + Subscription)

customer.subscription.created

  • subscription と契約の紐付け:
    • subscriptions.pricing_type = custom
    • subscriptions.custom_contract_id = <id>
  • custom_contracts を更新:
    • provider_price_id
    • provider_subscription_item_id
    • subscription_id

invoice.paid

  • 請求サイクルの subscription_histories を作成/更新
  • custom_contracts.provider_price_id / provider_subscription_item_id を更新(invoice line から補完)
  • 成功時: custom_contracts.status = active

customer.subscription.updated

  • subscription ステータスを同期
  • 必要に応じて更新/更新履歴を作成

customer.subscription.deleted

  • subscription をキャンセルし契約を更新:
    • 早期終了は cancelled
    • ends_at 終了済みなら expired

ガードレール

  • カスタムプランは package_plan_to_providers を使用しない
  • 価格/範囲の変更は契約 + webhook 経由で実施
  • Stripe metadata が正しい紐付けの鍵

注意点

  • Webhook は順不同で到着するため、処理は idempotent 前提。
  • amount = 0 の場合でも invoice.paid による有効化を前提とする。