diff --git a/.env.example b/.env.example index f890679..4d4d8f2 100644 --- a/.env.example +++ b/.env.example @@ -9,3 +9,11 @@ INTERNAL_SERVICE_TOKEN= SMTP_USERNAME= SMTP_PASSWORD= +# Stripe billing (required for checkout + portal + webhook) +STRIPE_SECRET_KEY= +STRIPE_WEBHOOK_SECRET= + +# Comma-separated whitelist of Stripe price ids accepted by the checkout endpoint. +# Example: +# STRIPE_ALLOWED_PRICE_IDS=price_xstream_paygo,price_xstream_subscription +STRIPE_ALLOWED_PRICE_IDS= diff --git a/README.md b/README.md index 58ef713..1a045f2 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,24 @@ cp .env.example .env make dev ``` +## Stripe 配置 (Stripe Billing Setup) + +Stripe 相关服务端能力现在由 `accounts.svc.plus` 承担,包括: + +- Checkout Session 创建 +- Customer Portal 跳转 +- Webhook 验签与订阅状态回写 + +需要的环境变量: + +| 变量 | 用途 | +| --- | --- | +| `STRIPE_SECRET_KEY` | Stripe API secret key | +| `STRIPE_WEBHOOK_SECRET` | Stripe webhook endpoint secret | +| `STRIPE_ALLOWED_PRICE_IDS` | 允许下单的 `price_...` 白名单,逗号分隔 | + +联调说明见 `docs/usage/stripe-billing.md`。 + ## 核心特性 & 技术栈 (Features & Tech Stack) 核心特性: @@ -66,6 +84,7 @@ make dev - 文档入口:`docs/README.md` - 快速开始:`docs/getting-started/quickstart.md` - 配置说明:`docs/usage/config.md` +- Stripe 联调:`docs/usage/stripe-billing.md` - 部署方式:`docs/usage/deployment.md` - API 参考:`docs/api/overview.md` - 运维:`docs/operations/monitoring.md`, `docs/operations/troubleshooting.md` diff --git a/docs/usage/stripe-billing.md b/docs/usage/stripe-billing.md new file mode 100644 index 0000000..f44f7a4 --- /dev/null +++ b/docs/usage/stripe-billing.md @@ -0,0 +1,60 @@ +# Stripe Billing + +`accounts.svc.plus` is the server-side owner of Stripe billing. + +It now provides: + +- `POST /api/auth/stripe/checkout` +- `POST /api/auth/stripe/portal` +- `POST /api/billing/stripe/webhook` + +## Required Environment Variables + +Set these before starting the service: + +```bash +STRIPE_SECRET_KEY=sk_test_xxx +STRIPE_WEBHOOK_SECRET=whsec_xxx +STRIPE_ALLOWED_PRICE_IDS=price_xstream_paygo,price_xstream_subscription +``` + +`STRIPE_ALLOWED_PRICE_IDS` is optional but recommended. When set, the checkout endpoint rejects any `price_id` that is not explicitly allowed. + +## Local Test Mode Runbook + +1. Start the account service with Stripe test-mode credentials. +2. Expose the service so Stripe webhooks can reach it, or use the Stripe CLI: + +```bash +stripe listen --forward-to http://127.0.0.1:8080/api/billing/stripe/webhook +``` + +3. Copy the webhook secret printed by Stripe CLI into `STRIPE_WEBHOOK_SECRET`. +4. Restart `accounts.svc.plus`. +5. Start `console.svc.plus` with matching public `NEXT_PUBLIC_STRIPE_PRICE_*` values. +6. Sign in through the console and start a checkout flow. +7. Complete the payment with Stripe test card data. +8. Verify: + - checkout redirects back to the console + - webhook delivery succeeds + - `GET /api/auth/subscriptions` contains a `provider = stripe` record + - Stripe portal opens for the same user + +## Webhook Notes + +The webhook currently handles these events: + +- `checkout.session.completed` +- `customer.subscription.created` +- `customer.subscription.updated` +- `customer.subscription.deleted` +- `invoice.paid` +- `invoice.payment_failed` + +The webhook is the authoritative source for Stripe subscription status in the local `subscriptions` store. + +## Operational Notes + +- Keep Stripe secret values server-side only. +- Use test mode until the complete flow is verified end to end. +- If checkout succeeds but no subscription record appears, inspect webhook delivery first.