支付集成

项目中关于Stripe支付相关配置

发给 ChatGPT / Claude 等 AI,可更快消化本页并上手上站。

Created: 09/05/2026
Updated: 10/19/2026

朋友,可能你看到这篇文章的时候和我写的时候相隔很久,文章中所说可能已经不是对应官网的最新信息,需要你将文章发给AI让其确认是否还可行后再去做,感谢理解

Stripe 支付与订阅接入指南

本指南介绍如何在基于 TanStack 模板的 SaaS 应用中接入与配置 Stripe 处理一次性权益购买与循环订阅(支持国际信用卡/借记卡,并在 CNY 人民币场景下支持微信支付与支付宝)。


前置准备:账号与卡片

开通 Stripe 前,您需要拥有香港主流银行账户或境外银行卡。

1. 银行卡与 Stripe 开户参考

2. 替代方案:Wise 在线开卡

如果您暂时无法前往香港开卡,可采用 Wise 在线开卡 方案:


一、核心架构与支付全流程

系统采用“管理后台在线配置凭据 + 服务端定价目录唯一可信源 + 前端发起会话 + Webhook 权威履约”的现代全栈支付架构设计,全面适配 Node.js 与 Cloudflare Workers 等边缘运行时。

1. 核心架构特性

  • 凭据后台化管理:所有 Key 统一在管理后台(/admin/settings -> Payment)配置并持久化,支持热切换测试与生产环境,同时兼容环境变量(.env)兜底。
  • 灵活的价格策略(动态生成 vs 固定 Price 映射):
    • 基础支付支持动态价格(Dynamic Price Data),根据代码中的定价目录直接生成 Stripe 价格,无需手动建品;
    • 订阅升降级支持配置价格映射字典(stripe_price_ids_mapping),无缝对接 Stripe 原生 Subscription Schedule 调度机制。
  • 全链路异步验签与边缘兼容:采用 constructEventAsync 异步验证 Webhook 签名,彻底解决 Web Crypto / SubtleCrypto 在 Serverless/Workers 环境下的兼容性问题。
  • 双重回调保障:前台 Redirect 跳回提供即时交互反馈,后台 Webhook 异步兜底确保订单 100% 可靠履约与状态对齐。

2. 端到端支付调用时序

整个交易与履约闭环共分为 4 步:

[前端页面 /pricing]
        │
   1. POST /api/payment/checkout  (传 product_id, payment_provider, redirect)
        ▼
[系统服务端]
   - 校验 product_id,查 src/config/pricing.ts (服务端唯一权威源)
   - 创建内部初始订单 (状态: PENDING)
   - 调用 Stripe API 构建 Checkout Session
        │
   2. 返回 { checkout_url }
        ▼
[Stripe 托管收银台] ── 用户完成支付
        │
        ├────────────────────────────────────────┐
   3. 同步浏览器跳回 (体验层)                     4. 异步 Webhook (权威资金履约层)
        │                                        │
        ▼                                        ▼
[GET /api/payment/callback]            [POST /api/payment/notify/stripe]
- 校验 order_no 状态                    - 异步验签 Webhook (whsec_...)
- 重定向至个人中心或对账页              - 订单更新为 PAID,写入流水
                                       - 发放对应积分/激活或续期订阅
  1. 发起结账:客户端调用 POST /api/payment/checkout,传入 { product_id, payment_provider, redirect }。
  2. 校验与建单:服务端根据商品目录校验价格,向 Stripe 创建带有商户订单号(orderNo)的 Checkout 会话,返回收银台地址 checkout_url。
  3. 前端跳回(引导反馈):用户付款后被引导跳回 /api/payment/callback,服务端做基础状态校验后重定向至个人中心。
  4. Webhook 权威履约:Stripe 异步通知 POST /api/payment/notify/stripe,严格验签通过后更新数据库订单为 PAID、自动为用户充值积分权益、或激活/续期/变更/退款订阅。

二、商品与定价目录(src/config/pricing.ts)

商品目录定义在 src/config/pricing.ts,这是服务端唯一权威可信源,客户端提交的任何金额或权益数据一律忽略。

1. 配置示例

export const pricingCatalog: Record<string, PricingProduct> = {
  // 一次性点数包(例如 Starter 永久/按次包)
  starter_lifetime: {
    productId: 'starter_lifetime',
    productName: 'Starter Pack',
    planName: 'Starter Pack',
    description: 'Starter credit pack',
    type: PaymentType.ONE_TIME,
    priceInCents: 990,
    currency: 'usd',
    credits: 1500,
    creditsValidDays: 365,
    monthlyDisplayPrice: '$9.9',
    copyKey: 'starter_pack',
    buttonKey: 'buy_once',
    creditsKey: 'pack',
  },
  // 订阅型计划(例如 Lite 按月订阅)
  starter_monthly: {
    productId: 'starter_monthly',
    productName: 'Lite',
    planName: 'Lite',
    description: 'Lite Monthly',
    type: PaymentType.SUBSCRIPTION,
    priceInCents: 990,
    currency: 'usd',
    credits: 2000,
    creditsValidDays: 30,
    monthlyDisplayPrice: '$9.9',
    originalPrice: '$14.9',
    copyKey: 'lite',
    buttonKey: 'subscribe',
    creditsKey: 'month',
    plan: { name: 'Lite', interval: PaymentInterval.MONTH, intervalCount: 1 },
  },
};

提示:模板默认内置了各级别计划,分别覆盖 monthly(月付)、yearly(年付)和 lifetime(一次性点数包)。修改售价或增加点数套餐仅需在此文件中调整。


三、本地开发:配置测试环境 API 密钥

在开发与联调阶段,使用 Stripe 的测试模式(Test Mode),所有操作均不产生实际扣费。

步骤 1:获取测试密钥

  1. 登录 Stripe 控制台。
  2. 在控制台右上角打开 Test mode(测试模式) 开关。
    image
  3. 依次进入 Developers(开发者)> API keys(API 密钥)。
  4. 复制标准密钥中的:
    • Publishable key(可发布密钥):以 pk_test_ 开头。
    • Secret key(私钥):以 sk_test_ 开头(若无请点击 Reveal live/test key 或 Create secret key 生成)。

步骤 2:填入管理后台

  1. 访问本地管理后台:http://localhost:3000/admin/settings(选择 Payment 标签页)。
  2. 在 Stripe 分组中:
    • 开启 Enable Stripe 开关(stripe_enabled)。
    • 填入 stripe_publishable_key(pk_test_...)。
    • 填入 stripe_secret_key(sk_test_...)。
  3. 点击页面底部的 Save(保存)。

步骤 3:本地支付全链路测试

  1. 访问前台定价页:http://localhost:3000/pricing。
  2. 选择任意套餐并点击购买,页面将自动跳转至 Stripe 托管收银台。
  3. 使用 Stripe 官方提供的测试卡输入信息:
    • 卡号:4242 4242 4242 4242
    • 有效期:任意未来月份(如 12/28)
    • CVC:任意 3 位数(如 123)
    • 邮编:任意 5 位数
  4. 点击支付完成结账,通过本地 Webhook 转发即可触发服务端自动发放权益。

四、生产部署:配置正式环境 API 密钥

项目准备上线接收真实资金时,切换为正式模式:

  1. 在 Stripe 控制台右上角关闭 Test mode(退出测试模式)。
    image
  2. 依次进入 Developers(开发者)> API keys。
  3. 复制正式的 Publishable key(以 pk_live_ 开头)与 Secret key(以 sk_live_ 开头)。
  4. 登录线上生产环境后台:https://你的域名/admin/settings。
  5. 将正式的 pk_live_... 与 sk_live_... 粘贴到对应输入框并保存。

五、关键环节:配置 Webhook(支付回调与权威履约)

为什么必须配置 Webhook?

  1. 防止掉单(异常兜底):用户在收银台付完款后若直接关闭浏览器或网络中断,前台回调无法触发。系统必须依靠服务端 Webhook 异步回调确保订单即时入账和权益发放。
  2. 处理自动续费:月付/年付订阅到期后,Stripe 的后续扣款是后台静默发生的。系统依靠 Webhook 事件自动为用户延长订阅有效期并下发新周期的权益额度。
  3. 订阅状态与计划变更同步:当用户在客户门户升级、降级、取消待生效、恢复续费或银行卡扣款失败时,由 Webhook 实时同步本地状态。
  4. 退款自动冲减:当在 Stripe Dashboard 触发全额或部分退款时,系统通过退款事件自动回收尚未消耗的权益额度并标记订单退款。
  5. 安全防伪验签:请求头附带 stripe-signature,服务端使用 stripe_signing_secret 进行时序安全异步签名验证,杜绝伪造回调。

1. 系统完整支持的 Webhook 事件清单

系统在 src/core/payment/stripe.ts 与 src/modules/payment/service.ts 中针对以下 6 个核心事件进行了完整的状态机映射与业务履约处理:

Stripe 事件类型 内部事件映射 业务处理逻辑
checkout.session.completed CHECKOUT_SUCCESS 初次结账成功:一次性点数包即时发放入账;订阅首次支付成功激活订阅并下发首期额度。
invoice.payment_succeeded PAYMENT_SUCCESS 订阅自动续费成功:延长用户订阅截止时间,发放新周期重置额度,记录发票信息。
invoice.payment_failed PAYMENT_FAILED 续费扣款失败:记录扣款异常日志,清除待生效的升级预定(pending_if_incomplete),防止错误更新。
customer.subscription.updated SUBSCRIBE_UPDATED 订阅计划与状态变更:同步升降级状态、更新当前周期起止时间、同步取消待生效标志(cancel_at_period_end)。
customer.subscription.deleted SUBSCRIBE_CANCELED 订阅彻底终止/取消:订阅期满或主动取消后正式停权,将本地订阅置为已取消状态。
charge.refunded PAYMENT_REFUNDED 全额/部分退款:自动匹配关联订单,按退款比例安全冲减用户积分并记录退款账本流水。

⚠️ 注意:未在上述列表中的其他 Stripe 事件会被系统安全过滤(抛出 WebhookIgnoredError),接口会自动返回 HTTP 200 确认送达,不影响正常业务运行。

2. Webhook 具体配置步骤

  1. 登录 Stripe 控制台,点击右上角进入 Developers(开发者)。
  2. 点击左侧菜单的 Webhooks,点击 + Add destination(或 Add endpoint)。
  3. 配置端点 URL:
    • 严格填入系统的标准接收回调地址:
      https://你的域名/api/payment/notify/stripe
      
      (本地联调时填入内网穿透域名,例如 https://xxxx.ngrok-free.app/api/payment/notify/stripe)
  4. 选择要监听的事件(Select events):
    在搜索框中逐一检索并勾选上述 6 个核心事件:
    • checkout.session.completed
    • invoice.payment_succeeded
    • invoice.payment_failed
    • customer.subscription.updated
    • customer.subscription.deleted
    • charge.refunded
  5. 确认无误后点击 Add endpoint 保存。
  6. 进入刚创建好的 Webhook 详情页,在 Signing secret(签名密钥) 处点击 Reveal(显示),复制以 whsec_ 开头的字符串。
  7. 登录系统管理后台(/admin/settings -> Payment -> Stripe),将该密钥粘贴至 Webhook Signing Secret(stripe_signing_secret)并保存。
    (如使用环境变量兜底,对应 .env 中的 STRIPE_SIGNING_SECRET=whsec_xxx)

3. Webhook 本地调试(Stripe CLI)

本地联调推荐使用 Stripe 官方 CLI 工具,无需配置内网穿透:

# 1. 登录 Stripe CLI
stripe login

# 2. 将 Webhook 转发至本地服务端口(假设本地开发端口为 3000)
stripe listen --forward-to localhost:3000/api/payment/notify/stripe

终端启动后会输出类似如下密钥:

Ready! Your webhook signing secret is whsec_xxxxxxxxxxxxxxxxxxxxxxxxxxxx

将该 whsec_... 复制填入本地管理后台的 stripe_signing_secret 中即可开始本地联调。

如需模拟特定事件触发,可新开终端运行:

stripe trigger checkout.session.completed
stripe trigger invoice.payment_succeeded
stripe trigger customer.subscription.updated
stripe trigger customer.subscription.deleted
stripe trigger charge.refunded

六、进阶:配置订阅价格映射(stripe_price_ids_mapping)

系统在发起常规结账时支持动态生成 Price 数据,但在处理订阅方案升降级(Plan Change)时:

  • 原地升级(In-place Upgrade):立即生效并由 Stripe 计算差价折算(Proration)。
  • 期末降级(Period-end Downgrade):通过 Stripe Subscription Schedules 预定在当前周期结束时切换至新套餐,当前权益不退款且保留至期末。

为了支持上述功能,需要在 Stripe 控制台预建对应商品的价格并完成映射:

  1. 进入 Stripe 控制台 > Product Catalog(产品目录),为每个订阅套餐创建对应的 Recurring 价格,并记录以 price_ 开头的 Price ID。
  2. 进入管理后台 /admin/settings -> Payment -> Stripe,在 Price IDs Mapping(stripe_price_ids_mapping)中填入 JSON 映射字典:
{
  "starter_monthly": "price_1Rxxxxxxxxx001",
  "pro_monthly": "price_1Rxxxxxxxxx002",
  "enterprise_monthly": "price_1Rxxxxxxxxx003",
  "starter_yearly": "price_1Rxxxxxxxxx004",
  "pro_yearly": "price_1Rxxxxxxxxx005",
  "enterprise_yearly": "price_1Rxxxxxxxxx006"
}

配置后,系统在处理用户前台升降级操作时会自动无缝调用 Stripe 原生 Schedule 接口。


七、客户自助门户(Stripe Customer Portal)

系统已内置集成 Stripe 官方的 Hosted Billing Portal:

  • 用户在个人中心账单页(/settings/billing)点击管理订阅时,服务端会调用 stripe.billingPortal.sessions.create 生成一次性安全跳转链接;
  • 用户可在 Stripe 官方页面自助下载历史发票 PDF、更新付款信用卡或解绑取消订阅;
  • 操作完成后,Stripe 会自动将用户导回应用的账单页,并通过 Webhook 实时同步最新状态。

八、在 Stripe 中开通微信支付与支付宝

如果您的 Stripe 账户主体支持开通微信支付和支付宝:

  1. 登录 Stripe 控制台,在全局搜索栏输入 Payment methods(支付方式)。
  2. 在支付方式列表中找到 WeChat Pay(微信支付) 与 Alipay(支付宝),点击 Turn on(启用)。
  3. 根据页面指引提交所需主体材料并等待 Stripe 审核通过。
  4. 生效规则:在系统实现中,当订单货币为人民币 cny 且结算类型为一次性付款时,Stripe 收银台会自动激活微信支付与支付宝渠道供用户选择。

九、常见问题与排错自检

  • Q1:前台点击支付提示 "Payment provider 'stripe' is not configured"?
    • 检查:进入后台 /admin/settings,确认 stripe_enabled 开关已开启,且 stripe_secret_key 已正确填写。
  • Q2:付款成功后权益没有到账?
    • 排查:
      1. 检查 Webhook 地址是否精确配置为 https://你的域名/api/payment/notify/stripe。
      2. 检查管理后台的 stripe_signing_secret 是否与 Stripe 对应端点的 whsec_... 完全一致。
      3. 在 Stripe 控制台 Webhooks 列表中查看推送日志的 HTTP 响应状态码(正常应为 200 OK)。
  • Q3:Cloudflare Workers / Edge 部署时 Webhook 报错?
    • 说明:系统底层已采用 constructEventAsync 异步验签,支持 Web Crypto 规范,确保在 Workers 和 Node.js 环境下均可平滑验签。
  • Q4:测试模式与生产环境混淆?
    • 排查:pk_test_ 必须搭配 sk_test_ 与测试 Webhook 密钥;上线前务必统一切换为 pk_live_、sk_live_ 以及生产环境端点生成的 whsec_...。