如何为应用添加支付:结账、订阅与 Webhook
在应用中添加支付最简单的方式是 Stripe:如果你只需要一个“购买”按钮,并且可以手动处理订单,就使用付款链接;如果你的应用需要知道是谁付了款并自动作出反应,就使用 Stripe Checkout;如果是定期计费,则使用订阅模式的 Checkout,再加上 Stripe 的客户门户。除了最简单的情况外,你还需要一个 Webhook——即 Stripe 在付款成功时调用的服务端端点。在切换到正式密钥之前,你应使用 Stripe 的测试密钥和测试卡号测试所有功能。
本指南会介绍每种方案、大多数教程都会略过的 Webhook 部分,以及在收取真实款项前需要检查的事项。Stripe 的细节来自其截至 2026 年 9 月的官方文档。
为什么要使用支付服务商
绝不要在你自己的表单中收集卡号。直接处理原始卡数据会使你承担 PCI DSS(信用卡行业安全标准)的合规范围,并带来严重的法律责任。像 Stripe 这样的支付服务商会托管付款表单、保存卡信息、处理银行验证,并告诉你的应用支付结果。你的应用只会看到“客户 X 为 Y 付了款”这样的信息。
本指南使用 Stripe,是因为它应用广泛、文档完善,并且大多数 AI 应用构建工具都支持。其他服务商也存在,其中一些作为“销售记录方”(merchant of record)会为你处理销售税;如果税务合规让你担心,可以对比一下这类模式。
使用 Stripe 收款的三种方式
| 方案 | 需要编写的代码 | 应用是否知道谁付了款 | 最适合 |
|---|---|---|---|
| 付款链接 | 无 | 只有添加了 Webhook 才知道 | 销售少量固定产品、捐款、测试需求 |
| Checkout(一次性) | 服务端代码,用于创建会话 | 是,通过 Webhook | 商店、付费下载、一次性购买 |
| Checkout(订阅) | 服务端代码加 Webhook 处理 | 是,通过 Webhook | SaaS、会员、任何定期收费的业务 |
付款链接
付款链接是你在 Stripe 控制台中创建的、由 Stripe 托管的付款页面,无需编写代码。你会得到一个 URL,可以放在应用的按钮后面、通过邮件分享,或者显示为二维码。Stripe 的文档称,付款链接可以销售产品、订阅,也可以接受捐款;你还可以让客户自行选择付款金额,或限制购买次数。
需要注意的是:你的应用不会自动知道某个已登录的用户是否付了款。对于捐款页面,或者你根据 Stripe 的邮件通知手动处理订单的小店铺来说,这样没有问题。但如果是“付费解锁专业版功能”,就不适用了。
Stripe Checkout
Checkout 是你的服务端针对某次特定购买按需创建的付款页面。你的服务端告诉 Stripe 正在购买什么(以及可选的购买客户是谁),Stripe 返回一个 URL,然后你把客户引导到该 URL。Stripe 的文档称,它同时支持一次性付款和订阅付款,形式可以是完全由 Stripe 托管的页面、嵌入你网站的页面,或嵌入式表单。
流程如下:
- 客户在你的应用中点击购买。
- 你的服务端使用密钥创建一个 Checkout 会话,并包含一个将其与你的用户或订单关联起来的 ID。
- 客户被重定向到 Stripe 并完成付款。
- Stripe 将他们重定向回你的成功页面。
- Stripe 向你的 Webhook 发送
checkout.session.completed事件,你的服务端随即将订单标记为已付款或解锁访问权限。
第 2 步必须在服务端完成,因为它需要使用你的密钥。这也是 Checkout 需要后端的主要原因。
订阅
订阅使用订阅模式的 Checkout,并配合你在 Stripe 中设置的定期价格。第一次付款的流程与上述相同。之后,续费、银行卡失败、升级和取消都会随时间发生——通常客户根本不在你的应用中——因此你的应用只能通过 Webhook 得知这些变化。
如果要让客户自行管理订阅,Stripe 提供了托管的客户门户。根据 Stripe 的文档,客户可以在那里更新支付方式和账单信息,更改或取消订阅,并查看和下载发票。你在 Stripe 控制台中进行配置,并添加一个“管理账单”按钮,将客户引导至该门户。这样你就不必自己开发这些页面。
Webhook:不能跳过的部分
Webhook 是 Stripe 在某件事发生时发送给你服务端的 HTTP 请求。(通用概念请参见什么是 Webhook。)Stripe 的履约指南明确指出:不能只依赖成功页面来履行订单,因为客户可能在付款后、该页面加载前就断开了连接。对于订阅和延迟支付方式,Webhook 是必需的。
值得处理的事件
| 事件 | 含义 | 你的应用应做什么 |
|---|---|---|
checkout.session.completed | Checkout 已完成 | 将订单标记为已付款,或开通访问权限 |
checkout.session.async_payment_succeeded | 延迟支付方式(例如银行扣款)稍后成功 | 立即履约 |
checkout.session.async_payment_failed | 该延迟支付失败 | 告知客户;不要履约 |
invoice.paid | 订阅付款成功,包括续费 | 延长访问期限 |
invoice.payment_failed | 续费失败 | 提醒用户;Stripe 可能会重试 |
customer.subscription.updated | 套餐已更改,或已安排取消 | 更新用户的套餐 |
customer.subscription.deleted | 订阅已结束 | 移除付费访问权限 |
正确的 Webhook 处理程序规则
这些规则直接来自 Stripe 的 Webhook 文档,AI 生成的处理程序有时会漏掉其中某一条:
- **验证签名。**每个事件都包含一个
Stripe-Signature请求头。你的处理程序需要使用端点的签名密钥(以whsec_开头)进行验证。如果不这样做,任何人都可以向你的服务端发送伪造的“付款成功”请求。 - **使用原始请求体。**如果你的框架在验证前先解析或修改了请求体,签名校验就会失败。
- 快速返回 2xx 响应,然后再执行较慢的工作。超时会被视为失败。
- **处理重复事件。**Stripe 可能会多次投递同一个事件。应记录已处理的事件 ID,或者让履约操作可以安全地重复执行。
- **不要假设事件顺序。**Stripe 不保证事件按发生的顺序到达。
- **预计会有重试。**在正式模式下,Stripe 会在最多三天内重试失败的投递,因此短暂的故障不会丢失付款——但你的处理程序必须能够应对迟到的事件。
Webhook 需要一个公开的 HTTPS 地址,因此通常只有在应用发布之后才能正常工作(开发人员可以使用 Stripe CLI 将事件转发到本地机器)。
覆盖完整流程的提示词
使用 Stripe Checkout 为“Pro 礼包”添加一次性购买(价格 ID 保存在 STRIPE_PRICE_ID 中)。在服务端使用机密中的 STRIPE_SECRET_KEY 创建 Checkout 会话,并在会话中包含已登录用户的 ID。添加一个 POST /api/stripe/webhook 端点,使用原始请求体并通过 STRIPE_WEBHOOK_SECRET 验证 Stripe 签名,处理 checkout.session.completed,并将该用户标记为已拥有 Pro 礼包。确保同一事件重复到达时也是安全的。添加成功页面和取消页面。切勿将密钥暴露给浏览器。
如果需要订阅,再添加:“对 STRIPE_PRICE_ID 使用订阅模式。处理 invoice.paid、invoice.payment_failed、customer.subscription.updated 和 customer.subscription.deleted。添加一个“管理账单”按钮,打开 Stripe 客户门户。”
测试模式
Stripe 有独立的沙盒(测试)环境和正式环境,密钥也互相独立。沙盒密钥以 pk_test_、sk_test_ 或 rk_test_ 开头;正式密钥以 pk_live_、sk_live_ 或 rk_live_ 开头。测试交易不会转移资金。
来自 Stripe 测试文档的常用测试卡(有效期任意填写未来日期,CVC 填写任意三位数字):
| 卡号 | 结果 |
|---|---|
4242 4242 4242 4242 | 付款成功 |
4000 0000 0000 0002 | 卡被拒绝 |
4000 0000 0000 3220 | 需要 3D Secure 验证,然后成功 |
至少要测试以下内容:
- 成功付款会为正确的用户解锁正确的内容
- 银行卡被拒时会显示清晰的提示,并且不解锁任何内容
- 付款后立即关闭浏览器标签页,访问权限仍然会生效(这证明是 Webhook 在起作用,而不仅仅是成功页面)
- 在 Stripe 页面上取消,会将用户返回你的应用,且没有任何扣款
- 对于订阅:在客户门户中取消,并确认访问权限在应当结束时结束
正式上线
- 激活你的 Stripe 账户,填写你的企业和银行信息。
- **在应用的机密中替换为正式密钥。**Stripe 建议使用受限密钥,只授予你的集成所需的权限,而不是使用不受限制的密钥。
- 创建正式环境的 Webhook 端点,指向你已发布的应用。它有自己的签名密钥,与测试环境的不同——记得更新。
- 在正式模式下重新创建产品和价格;测试模式下的 ID 在正式模式中不存在。
- 完成一笔真实的小额购买,并将其退款。
所有密钥都应保存在项目的机密中,绝不要放在代码或聊天中。我们的安全检查清单更详细地介绍了密钥和 Webhook 验证。
税务、退款与手续
收款会带来代码无法解决的义务。以下内容不构成税务建议,请咨询会计师。
- **销售税、增值税和商品及服务税。**根据你和客户所在的地区,你可能需要注册、收取并申报税款。Stripe Tax 可以在结账时计算并收取税款,监控你的销售可能产生纳税义务的地区,并协助注册和申报——但责任仍在你自己。销售记录方类服务商是一种替代方案,它会承担更多此类工作。
- **退款和争议。**上线前确定你的退款政策,并将其放在网站上。争议(拒付)时有发生;请保留购买和交付内容的记录。
- **收据和发票。**Stripe 可以通过邮件发送收据;企业可能需要正式的发票。
- **手续费。**每家服务商都按交易收费。请查看服务商当前的定价页面,而不要依赖文章中的数字。
哪种方案适合你的应用
- **捐款或少量产品:**付款链接。参见如何搭建非营利机构捐赠网站。
- **带购物车的商店:**使用包含商品明细的 Checkout 和 Webhook。参见如何搭建在线商店。
- **SaaS 或会员:**订阅模式的 Checkout、Webhook 和客户门户。参见如何搭建 SaaS MVP和如何为 SaaS 产品定价。
- **向卖家付款的市场平台:**这是一种不同的、监管更严格的方案(Stripe Connect 或类似方案)。请单独规划。
在 Mythex 中添加支付
你在 Mythex 上构建的应用中的支付功能使用的是你自己的 Stripe 账户和密钥;应用中没有一键“连接 Stripe”的功能。通常的流程如下:
- 获取 Stripe 测试密钥。
- 将
STRIPE_SECRET_KEY(稍后再添加 Webhook 密钥)添加到项目机密中——可通过/secrets、项目设置,或代理需要密钥时显示的机密卡片完成。 - 使用类似上面的提示词,请代理实现 Checkout。
- 在预览中使用测试卡进行测试。在注册 Webhook 之前先发布,因为它需要你的公开 URL。
- 切换到正式密钥后,再次发布,以便正式应用获取这些密钥。
请参见文档中的使用 Stripe 接受付款和在后端处理 Webhook。
常见问题
在应用中收款最简单的方法是什么?
Stripe 付款链接无需编写代码:你在 Stripe 控制台中创建它,然后从应用中链接过去即可。如果你的应用需要知道是谁付了款,并自动解锁某些功能,则应使用 Stripe Checkout 加上 Webhook。
收款一定需要 Webhook 吗?
如果你的应用需要对付款做出反应,例如解锁账户、将订单标记为已付款、处理续费,那么需要。Stripe 的文档指出,不能只依赖成功页面,因为客户可能已经付款却从未到达该页面。订阅同样必须使用 Webhook。
怎样在不花真钱的情况下测试支付?
使用 Stripe 的沙盒(测试)API 密钥和测试卡号,例如 4242 4242 4242 4242,有效期任意填写未来日期,CVC 填写任意三位数字。测试交易不会转移真实资金。
Stripe 会替我处理销售税和增值税吗?
Stripe Tax 可以在结账时计算并收取税款,并监控你在哪些地区可能需要办理注册,但你仍然要对自己的纳税义务负责。请根据你的具体情况咨询会计师。