摘要
一句话总结
t3dotgg/stripe-recommendations 是一个开源的 Stripe 订阅集成指南,通过将 Stripe 视为唯一真实数据源并采用全量覆盖的同步机制,帮助 JS/TS SaaS 应用解决状态不同步与竞态条件问题。
核心要点
- 反“脑裂”设计:将 Stripe 视为唯一真实数据源(SSOT),不信任 Webhook 传递的局部数据和事件顺序,放弃复杂的增量更新。
- 全量覆盖同步:提供核心函数
syncStripeDataToKV,直接从 Stripe 拉取特定客户的最新完整订阅数据,并覆盖写入本地 KV 存储(如 Redis/Upstash)。 - 前置客户绑定:在发起 Checkout 流程前,强制检查并创建 Stripe Customer,将其与本地应用的
userId绑定,消除匿名结账带来的追踪难题。 - 双重触发机制:为防止 Webhook 延迟影响用户体验,在用户支付成功重定向至
/success页面时主动触发同步,同时在后台通过 Webhook 再次触发同步。 - 极简事件监听:在 Stripe 超过 258 种事件类型中,仅筛选并监听 18 种与订阅状态直接相关的核心事件。
- 实战避坑配置:建议在 Stripe 设置中开启“限制客户只能有一个订阅”以防止重复结账,并建议禁用退款率较高的 “Cash App Pay” 支付方式。
- 适用技术栈:专为基于 JavaScript/TypeScript 的 SaaS 应用设计,依赖已验证的用户身份系统和 KV 存储。
风险与不足
(注:以下为指南明确指出的不包含或未解决的范围,需开发者自行处理)
- 未涵盖测试环境与生产环境的 Stripe 密钥(Secret/Publishable Key)管理。
- 未解决多环境下的价格 ID(Price ID)管理问题。
- 不包含向用户前端暴露和展示订阅数据的具体实现代码。
- 不支持额度或用量追踪(Usage tracking,例如每月 100 次的调用限制)。
- 未提供免费试用(Free trials)逻辑的管理方案。
功能与定位
这是一个开源的架构指南与代码示例库,旨在为 SaaS 应用提供一种简单、可靠的 Stripe 支付(特别是订阅功能)集成方案。该方案的核心目标是消除 Stripe 与应用本地数据库之间的状态不同步(“脑裂”)问题和竞态条件。
典型使用场景
- 在基于 JavaScript/TypeScript 的 SaaS 应用中集成 Stripe 订阅支付。
- 处理 Stripe Checkout 流程与 Webhook 事件。
- 解决用户支付成功后状态更新延迟或不一致的问题。
核心功能
- 单一状态同步机制:提供
syncStripeDataToKV核心函数,直接从 Stripe 拉取特定客户的最新完整订阅数据,并覆盖写入本地 KV 存储(如 Redis),放弃处理复杂的增量更新。 - 前置客户绑定:在发起 Checkout 流程前,强制检查并创建 Stripe Customer,将其与本地应用的
userId绑定,避免匿名结账带来的状态追踪难题。 - 双重触发更新:
- 前端重定向触发:用户支付成功跳转回
/success页面时,主动触发同步函数,防止 Webhook 延迟导致的用户体验问题。 - Webhook 触发:监听特定的 Stripe 订阅相关事件(如
checkout.session.completed、customer.subscription.updated等),在后台触发相同的同步函数。
- 前端重定向触发:用户支付成功跳转回
特色与差异点
- 反“脑裂”设计哲学:不信任 Webhook 传递的局部数据和事件顺序。将 Stripe 视为唯一真实数据源(SSOT),每次更新都重新拉取当前状态,大幅降低了状态管理的复杂度。
- 极简的事件处理:Stripe 拥有超过 258 种事件类型,该方案仅筛选并监听与订阅状态直接相关的 18 种核心事件,忽略其他无关事件。
- 实战经验总结:包含作者在实际项目(如 T3 Chat)中总结的避坑技巧,例如建议禁用退款率高的 “Cash App Pay”,以及在 Stripe 设置中开启“限制客户只能有一个订阅”以防止重复结账。
使用方式概览
- 环境准备:需要 TypeScript、JS 后端、已验证的用户身份系统以及一个 KV 存储(如 Redis/Upstash)。
- 结账路由:在用户点击订阅时,后端先查询 KV 存储获取
stripeCustomerId,若无则创建并绑定,随后使用该 ID 创建 Stripe Checkout Session。 - 成功回调:在
/success路由中,获取用户 ID 并调用syncStripeDataToKV更新状态,然后重定向用户。 - Webhook 处理:配置
/api/stripe接收 Webhook,验证签名后,提取事件中的customerId并调用syncStripeDataToKV。
限制与注意事项
该指南仅专注于核心的订阅状态同步,以下问题不在本方案的解决范围内,仍需开发者自行处理:
- 测试环境与生产环境的 Stripe 密钥(Secret/Publishable Key)管理。
- 多环境下的价格 ID(Price ID)管理。
- 向用户前端暴露和展示订阅数据的具体实现。
- 额度/用量追踪(Usage tracking,如每月 100 次调用限制)。
- 免费试用(Free trials)逻辑的管理。
链接
- https://github.com/t3dotgg/stripe-recommendations
- https://github.com/t3dotgg/stripe-recommendations/blob/main/README.md