feat(story-5.2): add Stripe subscription checkout with session verification

Add POST /api/v1/stripe/create-subscription-checkout endpoint with
get_or_create_stripe_customer (SELECT FOR UPDATE), plan_id→price_id
mapping from env vars, active subscription guard (409), and
session_id in success URL. Add GET /verify-checkout-session endpoint
for server-side payment verification. Add /subscription-success
frontend page with loading/verified/failed states.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Vonic 2026-04-14 23:58:57 +07:00
parent 71edc183c4
commit 07a4bc3fc3
7 changed files with 382 additions and 18 deletions

View file

@ -8,3 +8,9 @@
## Deferred from: code review of story 5-1 (2026-04-14)
- `ref` cast `as any` on Switch component in `pricing.tsx:99` — pre-existing issue, not introduced by this change. Should use proper `React.ComponentRef<typeof Switch>` type.
## Deferred from: code review of story 5-2 (2026-04-14)
- Webhook handler needs to distinguish `mode='subscription'` from `mode='payment'` in `checkout.session.completed` and update User's `subscription_status`, `plan_id`, `stripe_subscription_id` — scope of Story 5.3.
- Subscription lifecycle events (`invoice.paid`, `customer.subscription.updated/deleted`, `invoice.payment_failed`) not handled — scope of Story 5.3.
- `_get_or_create_stripe_customer` can create orphaned Stripe customers if `db_session.commit()` fails after `customers.create`. Consider idempotency key in future.