前置条件
- 一个 Stripe 账号(stripe.com)—— 免费,测试模式不需要 实体公司。
- Stripe CLI 用来本地转发 webhook —— 见 docs.stripe.com/stripe-cli。
- 一个跑起来的 Postgres(
pnpm db:push已经执行过)。
1. 选定当前 Provider
打开src/config/site.ts:
'stripe'。如果之前改过,改回来。
2. 在 Stripe Dashboard 建商品和价格
进 Stripe Dashboard,Products → Add product。每个要卖的 scene 建一个商品。 卖 vibestrap 脚手架本体时同一个商品下挂两个价格(或者拆成两个商品):| Scene | 说明 |
|---|---|
| Vibestrap promo | 限时价(例如 $49 一次性) |
| Vibestrap standard | 原价(例如 $99 一次性) |
pro_monthly 订阅、一个 pro_yearly 订阅、
一个 lifetime 一次性,再加 1–4 个 credits_* 一次性。
记下每个 price_… ID,下一步要塞到环境变量里。
3. 配环境变量
.env.local(变量名严格对齐 src/env.ts):
4. 本地用 Stripe CLI 联调
whsec_… 的 webhook 签名密钥。把它贴到 .env.local 的
STRIPE_WEBHOOK_SECRET,重启 pnpm dev。之后所有测试支付都会带正确签名打到
你本地的路由。
不走 UI 直接造一个事件:
5. 生产环境 webhook
Stripe Dashboard:Developers → Webhooks → Add endpoint。- URL:
https://your-domain.com/api/webhooks/stripe - Events(至少订阅):
checkout.session.completed、invoice.paid、customer.subscription.updated、customer.subscription.deleted。 - 创建完点进去复制 Signing secret(
whsec_…),作为生产环境的STRIPE_WEBHOOK_SECRET。
验证
stripe listen开着,启动 dev。- 打开
/pricing,点 “Get vibestrap”,会跳到 Stripe Checkout。 - 用测试卡
4242 4242 4242 4242,过期日填未来任意月份,CVC 和邮编随便。 - 应该回跳到你设置的
successUrl。 - 查数据库:
能看到
provider='stripe'、status='paid'、对应金额。 - 再
stripe trigger checkout.session.completed一次 —— 不会有重复行, 因为payment.invoiceId/sessionId做了幂等。
常见坑
- Webhook 密钥对不上 ——
stripe listen打印的密钥每次会话都会变,不要拿 到生产环境。生产用 Dashboard 上 endpoint 的那一个。 - 测试 vs 正式模式混用 —— 测试模式
sk_test_*和正式模式sk_live_*下的 价格 ID 不通用,一个 price ID 只在一个模式里存在。 - 没开 Stripe Tax —— 卖到欧盟没开 Stripe Tax 的话 VAT 会从你利润里扣。 要么打开 Stripe Tax,要么换成 MoR(Paddle / Lemon Squeezy)。
successUrl/cancelUrl缺失 —— 任一个为空createCheckout都会抛 错。必须是绝对 URL(https://…)。- 订阅丢
subscription_data.metadata—— 续订发的invoice.paid事件本身metadata是空的。Stripe Provider 会把 checkout 的metadata复制到subscription_data.metadata,让续订也带着userId/scene,别去掉这条 路径。
官方文档
- Stripe 文档:stripe.com/docs
- Stripe CLI:docs.stripe.com/cli
- Webhooks 参考:docs.stripe.com/webhooks
- 测试卡号:docs.stripe.com/testing
- Stripe Tax:stripe.com/tax