← 返回博客
Tutorial发布于 2026-04-28· 10 分钟阅读

如何给 Next.js 添加 Stripe 订阅(完整指南)

By make1day · Updated 2026-11-07

这是「在 Next.js 中接入 Stripe 订阅」最短、且不会在生产翻车的路径。四个部件,没有灌水。

1. 创建产品与价格

在 Stripe 后台创建带周期性价格的 Product,把 Price ID 作为 STRIPE_PRICE_ID_PRO 写进环境变量,绝不硬编码进源码。

2. 结账路由

POST /api/checkout 读取套餐、解析价格 id、创建 mode 为 subscription 的 Checkout Session,带上 client_reference_id 与明确的 success_url / cancel_url,把托管页 URL 返回浏览器。创建会话前要求已登录——游客结账会找不到该给谁发授权。

3. Webhook 是真相来源

在解析 JSON 之前,先用签名头校验原始 body。处理 checkout.session.completed 与 customer.subscription.deleted,然后更新数据库。两条规则:

  • 验签失败(缺头、HMAC 不对、JSON 损坏)必须抛错并返回 HTTP 400。用 200 确认伪造请求是安全漏洞。
  • 记录已处理事件 id,任何写库之前先跳过重放。Stripe 会重试,没有这一步就会出现重复升级与幽灵退款。

4. 功能权限

每个受保护路由或服务端动作都从数据库读套餐,绝不读客户端状态。套餐未激活返回 402。AI 接口、源码 ZIP 下载、席位限制都挂在这一个检查上。

5. 跑通整个闭环

用测试卡 4242 4242 4242 4242 在测试模式完成结账,确认套餐翻转,再取消并确认翻回。然后用篡改签名的 Webhook 打一次,确认返回 400。若一份 env 就能跑通,计费就是真的。

好的模板会把第 2–4 步预先接好,并把它们放在与支付商无关的接口后面,这样以后加 Creem、PayPal、Waffo 或 Lemon Squeezy 时不必重写应用代码。

FAQ

验签之前可以先解析 body 吗?+

不行。先用签名头校验原始字节,再解析。先解析再重新序列化会改变字节,导致 HMAC 校验失败。

为什么游客结账会发不出授权?+

Webhook 按用户 id 或付款邮箱发放权限。若没人登录、付款邮箱又对不上账户,license 就没有可认领的人。创建会话前要求登录。

被忽略的 Webhook 响应是什么意思?+

返回 200 并标记 ignored,表示事件合法已验签但不属于我们处理的类型。它绝不能用于验签失败——那些必须是 400。

All frequently asked questions · Markdown version (for AI agents)

How to Add Stripe Subscriptions to Next.js (Complete Guide) · make1day