For AI agents: fetch the complete documentation index at /llms.txt, the full documentation corpus at /llms-full.txt, the agent skill at /skill.md, or this page as Markdown at /zh/docs/web/stripe-payments.md (or send Accept: text/markdown).
添加 Stripe 支付
创建免费的 Stripe 账户、带周期价格的产品、密钥,以及结账后发放权益的签名 webhook。
初学者演练
前提条件:应用在本地运行(5 分钟启动)以及已迁移、能存真实账户的数据库(设置数据库)。你需要一个邮箱来注册 Stripe 账户——不需要卡,也不会扣款。本指南的一切都在测试模式下进行:假钱、测试卡号、上线前无限重试。
快速术语:测试模式是 Stripe 的沙盒——仪表板上的 Test mode 开关在你关掉之前让每个密钥、产品和付款都保持假的。密钥(sk_test_…)是服务器对 Stripe 的密码。带价格的产品是客户购买的东西;price id(price_…)在代码中指名它。Webhook 是付款成功或订阅变更时 Stripe 对服务器的回调;签名密钥(whsec_…)证明调用确实来自 Stripe。
你要创建的:一个 Stripe 账户、一个带周期价格的产品、一个 API 密钥和一个 webhook 端点——大约二十分钟。Stripe 自己托管结账页;套件在服务端创建会话并跳转,所以不需要可公开的浏览器密钥。
记住边界:本指南只销售 Web 订阅。iOS/Android 应用内购买必须走 Apple 和 Google 的计费——绝不能走 Stripe Checkout——这就是移动端用 RevenueCat 的原因。
创建 Stripe 账户
1. 打开 stripe.com → Start now,用你的邮箱注册。
2. 引导流程会问你的业务情况——测试模式下每个问题都可以跳过,照样使用完整沙盒;只在准备收真实付款前完成激活。
预期结果:进入仪表板,顶栏可见 Test mode 开关。下面的一切都保持它开启——正式密钥稍后放进生产密钥存储,绝不放进笔记本上的 env 文件。
复制 API 密钥
1. 在仪表板打开 Developers → API keys。
2. 你会看到两个测试密钥:Publishable key pk_test_… 和被打码的 Secret key。点击密钥旁的 Reveal test key,复制 sk_test_… 值。
套件只需要密钥:结账会话在服务端创建,用户被跳转到 Stripe 托管的页面,所以可公开密钥不会进 env 变量。你以后做的产品若引入 Stripe.js,才会在客户端用到可公开密钥;套件的计费流程不用它。
sk_test_… 是沙盒账户的完整凭据:它放在 apps/web/.env.local 或密钥存储中,绝不进 NEXT_PUBLIC_/EXPO_PUBLIC_ 变量,也绝不进 Git。
创建产品和价格
1. 打开 Product catalog → Add product。
2. 用你的方案命名——Pro 与套件自带的方案一致——给出价格并选择 Recurring(如每月):套件的结账创建订阅模式会话,需要周期价格而不是一次性价格。
3. 保存,打开产品,复制 price id——以 price_… 开头(不是 prod_…,那是产品 ID)。
自带的 pro 方案已经显示 Monthly/Yearly 切换:月付用 STRIPE_PRICE_ID 结账,年付选项需要 STRIPE_PRICE_ID_PRO_YEARLY 中的第二个周期价格——没有它年付结账会以 price-unconfigured 失败。方案名、金额以及购买授予什么,都在 apps/web/src/product-plans.ts 中修改——Stripe 管钱的一侧,方案文件管权益的一侧。
添加 webhook 端点
webhook 才是真正授予访问权的东西:套件只在签名的 Stripe 事件到达后才翻转权益,所以仅靠结账跳转什么也证明不了。
1. 打开 Developers → Webhooks → Add endpoint。
2. Endpoint URL:你的公开 URL 加 /api/billing/webhook——如 https://yourdomain.com/api/billing/webhook。其他计费提供商在该目录下各有自己的路径;Stripe 的接收器在根部。
3. 在 Select events 中选择套件处理的事件:checkout.session.completed、checkout.session.async_payment_succeeded、checkout.session.async_payment_failed、invoice.paid、invoice.payment_failed、customer.subscription.created、customer.subscription.updated 和 customer.subscription.deleted。
4. 创建端点,打开它的页面,在 Signing secret 下点击 Reveal,复制 whsec_… 值——每个端点有自己的密钥。
本地开发收不到 Stripe 的服务器,所以改用 Stripe CLI:先 stripe login 一次,然后在第二个终端运行 stripe listen --forward-to localhost:3000/api/billing/webhook。它会打印一个临时 whsec_…——stripe listen 运行期间,.env.local 里放的是这个值,而不是仪表板上的值。
把值加入应用
在 apps/web/.env.local 中设置下面几行。BILLING_PROVIDER=stripe 选择适配器;其余三个分别是密钥、价格和签名密钥。缺少任何一个就启用提供商会让启动失败并指出变量名。
三个 STRIPE_* 值都仅限服务端——绝不 NEXT_PUBLIC_/EXPO_PUBLIC_,绝不提交;生产环境通过托管方的密钥管理器提供(部署指南介绍 Secret Manager)。编辑后重启开发服务器。
# apps/web/.env.local
BILLING_PROVIDER=stripe
STRIPE_SECRET_KEY=sk_test_…
STRIPE_PRICE_ID=price_…
STRIPE_WEBHOOK_SECRET=whsec_… # `stripe listen` value locally; endpoint signing secret in production
# STRIPE_PRICE_ID_PRO_YEARLY=price_… # required for the shipped Yearly toggle验证与排错
启动 stripe listen --forward-to localhost:3000/api/billing/webhook 并保持运行,重启开发服务器,然后打开 /billing,选择 Pro 方案,用测试卡 4242 4242 4242 4242、未来的有效期和任意 CVC 完成 Stripe 托管的结账。
预期结果:应用回到 /billing?checkout=success,工作区权益翻转为激活——listen 终端记录了送达的事件,仪表板的 Developers → Webhooks → 你的端点显示绿色送达。
想不点结账就测试接收器,stripe trigger checkout.session.completed 会通过 listen 转发器发一个合成事件。
常见失败:每次送达都 400 表示签名密钥与该端点不匹配——为正确的端点重新复制 whsec_… 并更新 env;毫无动静表示 BILLING_PROVIDER 仍是 local;测试配置里混进 sk_live_ 密钥表示复制了错误模式的密钥——测试与正式严格分开。
套件也为 Lemon Squeezy、Creem、Polar、Whop、Paddle、Dodo 和 PayPal 提供同样的单合同适配器——流程相同,只是控制台和 env 名不同——而移动端购买始终走 RevenueCat,不走 Stripe。