Stripe 集成教程

===

Stripe 是很多 SaaS 产品的默认支付方案。它能处理信用卡、订阅、发票、税务、收据、客户门户和 Webhook,适合从早期产品一路扩展到更复杂的商业化阶段。

但 Stripe 集成不能只理解成"接一个付款按钮"。真正可靠的 Stripe 集成,要处理产品价格、Checkout Session、Customer、Webhook、订单履约、订阅状态、支付失败和客户自助管理。

本文基于 Stripe 官方文档整理:

先决定你要卖什么

接 Stripe 前,先明确你的商业模型。

你是卖一次性商品,还是卖 SaaS 订阅?是一个价格,还是多个套餐?是按月付费,还是按年付费?是否有免费试用?是否需要团队席位?是否需要优惠码?

Stripe 里通常会有 Product 和 Price。Product 表示你卖的产品或套餐,Price 表示价格、币种、计费周期。

比如:

bash 复制代码
Product:Pro Plan
Price:$19 / month
Price:$190 / year

不要把价格只写死在代码里。更稳妥的做法,是在 Stripe Dashboard 配好产品和价格,在你的系统里保存对应的 price_id。

优先使用 Stripe Checkout

早期 SaaS 最推荐使用 Stripe Checkout,而不是从零自定义支付表单。

Stripe Checkout 是 Stripe 托管的支付页。你在服务端创建 Checkout Session,前端把用户跳转到 Stripe 提供的 URL,用户在 Stripe 页面完成付款。

这样你可以少处理很多敏感支付细节,也能更快支持多种支付方式、税务、优惠码和订阅。

只有当你对支付页面有很强定制需求时,才考虑更复杂的嵌入式或自定义方案。

配置密钥和环境

Stripe 有测试环境和生产环境,也有不同类型的密钥。

常见环境变量:

ini 复制代码
STRIPE_SECRET_KEY=sk_test_xxx
STRIPE_WEBHOOK_SECRET=whsec_xxx
STRIPE_PRICE_PRO_MONTHLY=price_xxx
STRIPE_PRICE_PRO_YEARLY=price_xxx

SECRET_KEY 只能放服务端。前端不能接触 secret key。

测试环境和生产环境的 key、price_id、webhook secret 都要分开。很多支付问题不是代码错了,而是测试 key、生产 price、错误 webhook secret 混用。

创建 Checkout Session

当用户点击"购买"或"升级"时,前端应该请求你的服务端。服务端根据用户身份、套餐和价格创建 Checkout Session。

Stripe 官方 API 文档说明,Checkout Session 代表一次用户付款或订阅的会话。创建后,你可以把用户重定向到 Session 的 URL。

核心参数通常包括:

复制代码
mode:payment 或 subscription
line_items:购买的 price 和数量
success_url:支付完成后跳转地址
cancel_url:用户取消后跳转地址
customer 或 customer_email:关联客户
metadata:你的本地业务信息

对 SaaS 订阅,常用 mode=subscription;一次性付款用 mode=payment。

metadata 很重要

Stripe 是支付系统,你的系统才是业务系统。两者之间需要关联。

创建 Checkout Session 时,建议在 metadata 里放入本地业务信息,比如:

复制代码
user_id
plan
team_id
order_id

这样 Webhook 回来时,你能知道这笔支付对应哪个用户、哪个团队、哪个订单。

但不要在 metadata 里放敏感信息或过大的数据。metadata 应该只放用于关联和排查的轻量字段。

不要只依赖 success_url

很多新手会在用户跳转到 success_url 后开通权限,这是非常危险的。

用户跳转成功不等于你一定可靠地完成了支付处理。用户可能关闭页面,网络可能中断,跳转可能失败,或者有人伪造访问成功页。

Stripe 官方 fulfillment 文档明确建议:自动履约必须使用 Webhook,确保每笔支付都能被处理。成功页可以让用户立刻看到结果,但不能作为唯一依据。

正确做法是:支付完成后,Stripe 发送 Webhook,你的服务端验证事件,确认支付状态,然后开通权限。

配置 Webhook

Stripe 支付集成的核心,是 Webhook。

常见事件包括:

复制代码
checkout.session.completed
invoice.paid
invoice.payment_failed
customer.subscription.updated
customer.subscription.deleted

一次性付款通常重点处理 checkout.session.completed。订阅产品除了 Checkout 完成,还要处理续费成功、支付失败、订阅取消和套餐变更。

Webhook 入口要做签名校验、事件落库、幂等处理和日志记录。不要重复开通同一个订单,也不要因为重复事件给用户重复发放权益。

履约要幂等

Stripe 官方 fulfillment 文档提醒:同一个 Checkout Session 的履约函数可能被调用多次,甚至并发调用。

所以你的履约逻辑必须幂等。

比如你可以用 checkout_session_id 或本地 order_id 做唯一约束。如果订单已经开通过,就直接返回成功;如果没有开通,再执行授权、写入订阅记录、发送邮件。

支付系统里,重复处理比处理失败更危险。重复开通、重复发货、重复发优惠都可能造成损失。

保存 Stripe Customer 和 Subscription

对订阅型 SaaS,你需要在本地保存 Stripe 的关键 ID:

复制代码
stripe_customer_id
stripe_subscription_id
stripe_price_id
subscription_status
current_period_end
cancel_at_period_end

这些字段能帮助你判断用户当前是否有权限、什么时候到期、是否取消、是否需要提醒更新付款方式。

不要每次用户访问都实时请求 Stripe 判断权限。你应该用 Webhook 同步关键状态到本地数据库,再在本地判断权限。

支付失败要有处理流程

订阅不是只处理第一次付款。

后续续费可能失败,银行卡可能过期,用户可能取消订阅,账单可能需要重试。Stripe 会通过 Webhook 通知这些状态变化。

至少要处理:

复制代码
invoice.paid:续费成功,延长权益
invoice.payment_failed:支付失败,提醒用户更新付款方式
customer.subscription.deleted:订阅结束,回收或降级权限
customer.subscription.updated:套餐或状态变化

如果你只处理第一次 Checkout 成功,订阅系统很快就会和真实支付状态不一致。

接入 Customer Portal

Stripe Customer Portal 可以让用户自助管理付款方式、发票、订阅取消、升级降级等操作。

Stripe 官方文档说明,Customer Portal 能让客户在一个地方管理支付信息、发票和订阅。

对早期 SaaS 来说,接入 Customer Portal 比自己做完整账单管理后台更省时间,也更可靠。

你需要在服务端创建 portal session,然后把用户跳转到 Stripe 的 portal URL。

本地测试要使用 Stripe CLI

Stripe Webhook 本地调试可以使用 Stripe CLI,把事件转发到你的本地服务。

测试时至少覆盖:

复制代码
一次性付款成功
订阅创建成功
续费成功
支付失败
订阅取消
Webhook 重复发送
Webhook 签名错误

支付系统不能只测"付款成功"。失败、取消、重复和延迟事件,才是最容易出问题的地方。

一个 Stripe 集成流程

可以按下面流程实现:

markdown 复制代码
1. 在 Stripe 创建 Product 和 Price
2. 保存 price_id 到你的配置
3. 用户点击购买
4. 服务端创建 Checkout Session
5. 前端跳转到 Stripe Checkout
6. 用户完成支付
7. Stripe 发送 Webhook
8. 服务端验签并幂等处理
9. 更新本地订单或订阅状态
10. 开通用户权限
11. 提供 Customer Portal 管理订阅

这条链路里,最重要的是第 7 到第 10 步。

写在最后

Stripe 集成的难点不在付款按钮,而在支付完成后的业务状态同步。

一个可靠的 SaaS 支付系统,要把 Checkout、Webhook、幂等履约、本地订阅状态、支付失败处理和客户门户串起来。

下一篇,我们继续聊另一个支付方案:PayPal 接入避坑。

相关推荐
Mandy的名字被占用了6 小时前
晨风AI+知识付费系统|学练考全闭环,重构教育变现新模式
人工智能·后端
why技术6 小时前
分享一套我一直在使用的 AICoding 组合拳,小而美的典范。
前端·后端·ai编程
GetcharZp7 小时前
SRS实战:一个开源流媒体服务,支持6大协议,80ms低延迟,轻松搭建自己的直播平台
后端
Csvn7 小时前
📊 SQL 入门 Day 7:子查询 — 查询中的查询
后端·sql
IT_陈寒10 小时前
为什么我的JavaScript异步代码总是不按顺序执行?
前端·人工智能·后端
星栈10 小时前
Node 框架怎么选?Express、Koa、Egg、NestJS 场景化选型指南
后端·node.js
锋行天下11 小时前
打造企业内部知识库系统RAG全栈项目
前端·后端·架构
码事漫谈12 小时前
Kimi K3 真实体验:全网评价整理,优缺点一次性说清楚
后端
Fanta丶12 小时前
16.Activiti8 SpringBoot3.X 部署与测试
后端
用户2080468045612 小时前
Python3 数据类型转换新手实战指南
后端