@
All checks were successful
Deploy to Production / deploy (push) Successful in 1m22s

feat(billing): in-app embedded Stripe checkout + webhook hardening

Checkout previously used hosted ui_mode → window.location to checkout.stripe.com,
which pops out of the installed PWA into the system browser. Switch to embedded:

- API: ui_mode embedded_page (stripe-node v22 / API 2025-10 renamed the enum),
  return_url instead of success/cancel_url, returns client_secret.
- web: @stripe/react-stripe-js EmbeddedCheckout mounted in an in-app modal;
  NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY baked at build (Dockerfile arg + compose arg).
- .env.production.example: full Stripe section (was missing) + admin-email
  placeholder (INF-001).

Also bundled (same files): BILL-002 invoice.paid resets quota only on
subscription_cycle; BILL-003 webhook dedup rolled back on handler failure;
BILL-001 change-plan writes plan locally; BILL-004 webhook cross-checks
sub.customer before trusting metadata.orgId; INF-003 API routed off the raw
docker.sock through a locked-down tecnativa/docker-socket-proxy (CONTAINERS+POST).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@
This commit is contained in:
Marco Sadjadi
2026-05-29 20:56:40 +02:00
parent 9d5386ccba
commit cf423de3d5
8 changed files with 256 additions and 20 deletions

View File

@@ -11,6 +11,8 @@
},
"dependencies": {
"@bmm/types": "workspace:*",
"@stripe/react-stripe-js": "^6.4.0",
"@stripe/stripe-js": "^9.7.0",
"clsx": "2.1.1",
"framer-motion": "11.18.2",
"geist": "1.3.1",