SuperAPI AI 工具集

payment-integration

编程与开发

查看项目

更新于 10-16 10:37

技能介绍

用途

该技能面向 Web 与移动应用中的支付处理与订阅计费实现,主要覆盖 Stripe 集成(Checkout、Elements、PaymentIntents)、订阅生命周期管理、带幂等性的 webhook 处理、PCI 合规、按量与基于用量的计费、税费计算、退款处理,以及用于移动订阅的 RevenueCat。

适用场景包括:新增支付处理、构建订阅计费、处理 Stripe webhook、实现定价页面、管理支付失败,或集成移动应用内购买。

核心原则

  1. 绝不处理原始卡数据——使用 Stripe Elements 或 Checkout 让卡号完全不经服务器,从而保持 PCI SAQ-A(最简合规级别)而非 SAQ-D。
  2. Webhook 是可信来源——绝不信任客户端支付确认。客户端 PaymentIntent 成功不代表什么,直到 webhook 处理器确认 payment_intent.succeeded。系统应围绕 webhook 事件构建。
  3. 处处幂等——webhook 可能被多次投递,每个 webhook 处理器必须幂等,使用 Stripe 事件 ID 作为去重键。
  4. 优雅处理失败——支付失败原因众多(余额不足、卡过期、欺诈检测)。在订阅生命周期中内置重试流程、催款邮件和优雅降级。
  5. 使用 Stripe 测试模式测试——使用测试 API 密钥、测试卡号和测试时钟进行订阅生命周期测试,绝不使用真实支付方式测试。

主要能力与关键模式

模式 1:用于订阅的 Stripe Checkout

适用时机:希望由 Stripe 托管完整结账 UI,包括支付表单、优惠码和税费计算时。

服务端创建 Checkout Session 的示例(TypeScript / Next.js):先获取或创建 Stripe 客户,然后创建订阅模式的 checkout session,配置 success_url、cancel_url、订阅 metadata(userId)、14 天试用、automatic_tax 启用、允许优惠码、要求填写账单地址以计税、customer_update 地址与姓名自动更新,以及自动续费披露文案(custom_text.submit)与要求同意服务条款(consent_collection.terms_of_service)。客户端从定价卡向 /api/checkout 发送 priceId、userId、email,拿到 url 后跳转 Stripe Checkout。

理由:Stripe Checkout 负责 PCI 合规、3D Secure 认证、税费计算、优惠码和本地化。自建结账表单需数百小时工作并承担持续的 PCI 合规负担。除非有强需求要自建 UI,否则使用 Checkout。

模式 2:带幂等性的 Webhook 处理器

适用时机:每一个 Stripe 集成。Webhook 是获知支付状态的唯一可靠方式。

实现要点:以事件类型为键定义处理器,覆盖 checkout.session.completed(更新用户订阅 ID 与状态为 active)、customer.subscription.updated(同步订阅状态、套餐价格 ID、当前周期结束时间、是否期末取消)、customer.subscription.deleted(状态置 canceled、清除套餐)、invoice.payment_failed(状态置 past_due 并发送催款邮件,含应缴金额与下次重试时间)、invoice.paid(状态恢复 active)。

POST 处理器流程:(1) 用 stripe.webhooks.constructEvent 验证签名,失败返回 400;(2) 幂等性检查,查询事件 ID 是否已处理,已处理直接返回;(3) 调用对应事件处理器,成功后记录已处理事件;(4) 处理器报错时返回 500,触发 Stripe 自动重试。

理由:Stripe 至少投递一次 webhook,可能重复。存储已处理事件 ID 的幂等检查避免重复处理;签名验证防止伪造 webhook 攻击;返回 500 触发 Stripe 指数退避自动重试。

模式 3:自助服务客户门户

适用时机:让客户自行管理订阅(升级、降级、取消、更新支付方式),无需联系支持。

实现:创建 stripe.billingPortal.sessions,传入 customer 和 return_url。通过 stripe.billingPortal.configurations.create 一次性配置门户:subscription_update 允许价格与数量变更、按比例计费(create_prorations)、指定产品与价格;subscription_cancel 启用、模式为 at_period_end(不立即取消)、启用取消原因选项;payment_method_update、invoice_history 均启用。

理由:自助计费可减少 60-80% 支持工单。Stripe 客户门户是托管方案,处理套餐变更、按比例计费、带原因采集的取消、支付方式更新和发票历史,无需自建 UI。

模式 4:基于用量的计费

适用时机:定价基于消耗量(API 调用、存储、计算分钟、席位)而非固定订阅。

实现:用 stripe.subscriptionItems.createUsageRecord 上报用量,action 用 increment(累加)而非 set(替换)。后台任务按小时聚合:查询活跃的用量型订阅,获取用户小时用量,大于 0 时上报并记录用量报告。应用内通过 Redis 计数器跟踪用量(redis.incr 键并设置 7 天过期),检查是否接近套餐上限(达到 80% 发送警告邮件,达到上限抛出 UsageLimitExceededError)。

理由:按量计费使成本与价值对齐。按小时聚合减少对 Stripe 的 API 调用,同时保持数据足够新鲜用于开票。基于 Redis 的跟踪为限流提供亚毫秒级用量检查。

Stripe 测试卡参考

卡号 场景
4242 4242 4242 4242 支付成功
4000 0000 0000 3220 需要 3D Secure
4000 0000 0000 9995 拒绝(余额不足)
4000 0000 0000 0341 附加到客户失败
4000 0025 0000 3155 需要认证

使用任意未来到期日期和任意 3 位 CVC。

反模式

反模式 问题 更好做法
信任客户端支付确认 用户可伪造成功 Webhook 处理器才是可信来源
服务器处理原始卡号 PCI SAQ-D 合规(非常昂贵) 使用 Stripe Elements 或 Checkout
webhook 处理器无幂等性 重复扣款、重复开通 按事件 ID 去重
立即取消订阅 用户在计费周期中失去访问 期末取消(cancel_at_period_end)
在应用中硬编码价格 不改部署无法改价 价格 ID 存数据库或环境变量
支付失败无催款流程 静默收入流失(非自愿流失) 自动重试 + 催款邮件
用真实支付方式测试 有真实扣款风险,无测试时钟 仅使用 Stripe 测试模式

检查清单

  • [ ] Stripe API 密钥存于环境变量(绝不写入代码)
  • [ ] 启用 webhook 签名验证
  • [ ] webhook 处理器幂等(事件 ID 去重)
  • [ ] 处理所有订阅状态变化(created、updated、canceled、past_due)
  • [ ] 实现支付失败催款流程(邮件 + 重试)
  • [ ] 配置客户门户用于自助计费
  • [ ] 订阅按钮旁展示自动续费条款(价格、频率、试用结束、如何取消);采集明示同意;确认邮件重复这些条款
  • [ ] 在线取消与注册一样简便(门户启用 subscription_cancel),无强制挽留电话(California ARL、FTC ROSCA)
  • [ ] 所有开发与预发布使用测试模式
  • [ ] 确认 PCI 合规级别(使用 Stripe Checkout/Elements 为 SAQ-A)
  • [ ] 启用税费计算(Stripe Tax 或外部服务商)
  • [ ] 为套餐变更配置按比例计费(升级/降级)

(资料原文检查清单以 "We" 截断,后续内容暂未提供。)