如何使用 Stripe 添加订阅:套餐、试用、Webhook 与付款失败处理
要使用 Stripe 添加订阅,请在 Stripe 控制台中创建一个带定期价格的产品,从你的服务端将客户引导至订阅模式的 Stripe Checkout,并由 Webhook 告知你的应用每次付款何时成功、失败、变更或结束。订阅状态应与用户关联存储,并据此授予访问权限,而不是依据成功页面。另外添加一个管理账单按钮,打开 Stripe 托管的客户门户,让用户无需你开发相关页面,就能更换银行卡、切换套餐和取消订阅。
本指南建立在如何为应用添加支付的基础之上,后者涵盖了一次性 Checkout、测试模式和正式上线。这里我们重点讨论定期计费的不同之处。Stripe 的细节来自其截至 2026 年 9 月的文档。
为什么订阅比一次性付款更复杂
一次性付款发生在客户仍在你的应用中时。而订阅会在客户离开之后继续发生:每月续费、银行卡过期、周期中途升级、在当期结束时才生效的取消等。你的应用只能通过 Webhook 得知这些事件。大多数订阅相关的问题,都源于把第一次付款当作全部情况。
你的选择
| 方式 | 你需要开发的内容 | 最适合 |
|---|---|---|
| 带定期价格的付款链接 | 只需一个链接 | 测试需求;手动处理访问权限 |
| Checkout(订阅模式)+ 客户门户 | 一个服务端路由、一个 Webhook、一个账单按钮 | 大多数 SaaS 应用和会员制业务 |
| 订阅 API 加自建付款表单 | 工作量大得多:付款界面、身份验证、重试逻辑 | 有特殊计费流程的应用 |
| 销售记录方服务商 | 与 Checkout 类似 | 希望由服务商处理销售税的卖家 |
对大多数应用来说,Checkout 加客户门户是合适的权衡。如果税务处理让你担心,可以对比Stripe、Paddle 与 Lemon Squeezy。
先在 Stripe 中规划定价
在 Stripe 中,产品是你销售的东西(“Pro 套餐”),价格是你为它收费的方式(“每月 20 美元”“每年 200 美元”)。一个产品可以有多个价格。请先决定:
- 提供哪些层级,以及每个层级在你的应用中解锁哪些功能
- 按月、按年,还是两者都提供
- 是否提供试用,以及试用是否需要预先绑定银行卡
在测试模式下创建产品和价格,并记下它们的价格 ID;你的应用会引用这些 ID。如果你还没有确定定价,请阅读如何为 SaaS 产品定价和免费增值与免费试用。
你必须处理的订阅生命周期
Stripe 的订阅概述列出了订阅可能具有的各种状态。其中对访问权限最重要的是:
| 状态 | 含义 | 是否授予访问权限 |
|---|---|---|
trialing | 处于试用期 | 是 |
active | 状态良好 | 是 |
incomplete | 首次付款尚未完成;Stripe 会给客户 23 小时 | 否 |
incomplete_expired | 首次付款从未成功 | 否 |
past_due | 最近一次付款失败或尚未尝试;之后可能会重试 | 由你决定;许多应用会允许短暂的宽限期 |
unpaid | 重试已结束,发票保持未结清,不再尝试 | 否,Stripe 的文档建议撤销访问权限 |
canceled | 已结束;无法重新开始 | 否 |
paused | 试用期结束时未添加支付方式,并已设置为暂停 | 否 |
将状态存储在你的用户或账户记录中,并据此决定访问权限。每当收到相关的 Webhook 时都要更新该状态。
需要处理的 Webhook 事件
| 事件 | 你的应用应做什么 |
|---|---|
checkout.session.completed | 将新的 Stripe 客户和订阅 ID 关联到你的用户 |
invoice.paid | 将订阅标记为有效,并记录新的周期结束时间 |
invoice.payment_failed | 告知用户银行卡扣款失败,并附上门户链接 |
invoice.payment_action_required | 请用户完成银行卡身份验证 |
customer.subscription.updated | 更新套餐、状态以及任何已安排的取消 |
customer.subscription.deleted | 移除付费访问权限 |
customer.subscription.trial_will_end | 在试用期结束前提醒用户;Stripe 会在结束前三天发送该事件 |
Stripe Webhook 文档中的处理程序规则依然适用:使用原始请求体验证签名,快速返回 2xx 响应,处理重复和乱序的事件,并预期会有重试。什么是 Webhook介绍了相关概念,而付款指南则详细列出了这些规则。
分步操作
- 在 Stripe 测试模式下创建产品和价格。
- 添加机密信息:密钥、价格 ID,以及稍后的 Webhook 签名密钥。绝不要把它们放在前端代码中。
- 定价页面:每个套餐的按钮调用你的服务端,服务端为已登录用户创建一个订阅模式的 Checkout 会话。传入你的用户 ID,以便 Webhook 能将付款与账户匹配。
- Webhook 端点:验证签名,并处理上述事件,为每位用户更新一条订阅记录。
- 根据已存储的状态和套餐控制功能访问,并在服务端对每个受保护的操作进行检查,而不只是隐藏按钮。
- 客户门户:在 Stripe 控制台中进行配置(用户可以切换到哪些套餐,是否可以取消),然后添加管理账单按钮,在服务端创建门户会话并重定向过去。
- 付款失败:在 Stripe 的账单设置中,选择重试策略以及最后一次重试之后会发生什么。在状态为
past_due时在应用中显示横幅提示。 - 测试整个生命周期,然后发布并注册正式环境的 Webhook。
给 AI 构建工具的提示词
使用 Stripe 添加订阅计费。套餐:Starter(价格 ID 保存在 STRIPE_PRICE_STARTER 中)和 Pro(STRIPE_PRICE_PRO)。定价页面在服务端使用 STRIPE_SECRET_KEY 创建订阅模式的 Checkout 会话,并附上已登录用户的 ID。将 Stripe 客户 ID、订阅 ID、套餐和状态保存到用户记录中。绝不要把密钥暴露给浏览器。
添加 POST /api/stripe/webhook。使用原始请求体并通过 STRIPE_WEBHOOK_SECRET 验证签名。处理 checkout.session.completed、invoice.paid、invoice.payment_failed、customer.subscription.updated、customer.subscription.deleted 和 customer.subscription.trial_will_end。记录已处理的事件 ID,使重复事件被忽略。根据订阅对象更新用户状态,而不是根据事件到达的顺序。
在服务端对 Pro 功能进行访问控制:只有当状态为 active 或 trialing 且套餐为 Pro 时才允许使用。当状态为 past_due 时,显示“付款失败,请更新银行卡”横幅。添加一个管理账单按钮,为该用户打开 Stripe 客户门户。
升级、降级与按比例计费
当客户切换套餐时,Stripe 的文档说明,此变更通常会产生按比例计费(proration):新价格会应用于当前计费周期的剩余时间。你可以预览按比例计费的结果,也可以将其关闭。如果两个套餐的计费周期相同,计费日期保持不变;从按月改为按年,则计费日期会变为切换当天。让客户在门户中自行更改套餐可以省去你编写这部分逻辑的工作,但需要在门户设置中决定允许哪些切换。
测试清单
使用 Stripe 测试模式和测试卡,逐一验证每种状态:
- 新订阅会为正确的用户开通正确的套餐
- 付款后立即关闭标签页,访问权限仍然会授予(证明 Webhook 正常工作)
- 注册时银行卡被拒,不会授予任何权限
- 续费失败会使账户进入 past_due 状态,并显示横幅
- 在门户中更新银行卡后,状态恢复为 active
- 升级和降级后,功能会正确变化
- 在当期结束时取消,访问权限会保留到结束日期,然后移除
- 试用用户可以获得访问权限、收到提醒,并能正确转为付费或失去访问权限
- 同一个 Webhook 事件发送两次,结果不会发生变化
Stripe 的测试时钟可以模拟时间流逝,因此无需等待一个月就能测试续费。关于如何使用它,请查阅 Stripe 当前的测试文档。
常见错误
- **在成功页面上授予访问权限。**客户可能已经付款,却从未到达该页面。应使用 Webhook。
- **只处理第一次付款。**续费、失败和取消会以事件的形式在之后到达。
- **只在前端检查套餐状态。**任何人都可以直接调用你的 API。
- **无意中为同一用户创建了多个订阅。**在创建新的 Checkout 会话之前,先检查是否已存在订阅,或者让已有客户直接进入门户。
- **首次续费失败就撤销访问权限。**银行卡失败的原因往往很普通。配合清晰横幅的短暂宽限期可以留住客户。
- **忘记正式环境的 Webhook。**测试端点和正式端点的签名密钥不同。
- **忽视税务和退款。**上线前请确定退款政策,并咨询会计师以核实你的纳税义务。
Mythex 中的订阅
你在 Mythex 上构建的应用使用的是你自己的 Stripe 账户和密钥;应用中没有一键连接 Stripe 的功能。将测试密钥和价格 ID 添加为项目机密,使用类似上面的提示词,并在预览中用 Stripe 测试卡进行测试。Webhook 需要你应用的公开 URL,因此请先发布,再在 Stripe 中注册端点;切换到正式密钥之后,再次发布,以便正式应用获取这些密钥。参见使用 Stripe 接受付款和在后端处理 Webhook。关于更广泛的产品,如何搭建 SaaS MVP介绍了计费周边需要构建的内容。
常见问题
使用 Stripe 添加订阅最简单的方法是什么?
在 Stripe 控制台中创建一个带定期价格的产品,将客户引导至订阅模式的 Stripe Checkout,使用 Webhook 处理订阅事件,并将“管理账单”按钮链接到 Stripe 托管的客户门户。这样你就无需自己开发银行卡表单和套餐变更页面。
订阅需要哪些 Stripe Webhook 事件?
至少需要:checkout.session.completed,用于将新订阅关联到你的用户;invoice.paid,用于确认每一次成功付款;invoice.payment_failed,用于提醒续费失败;以及 customer.subscription.updated 和 customer.subscription.deleted,用于跟踪套餐变更和取消。
订阅付款失败时会发生什么?
根据 Stripe 截至 2026 年 9 月的文档,订阅通常会变为 past_due 状态,Stripe 可以根据你的设置重试付款。在最后一次重试之后,你在控制台中的设置将决定订阅是被取消、标记为未付款,还是保持 past_due 状态。
可以在不要求银行卡的情况下提供免费试用吗?
可以。Stripe 支持免费试用,其文档说明,如果进行相应配置,试用期结束时仍未添加支付方式的订阅可以进入 paused(暂停)状态。预先收集银行卡信息通常意味着注册人数较少,但付费客户较多;请测试哪种方式更适合你的产品。