项目中关于Stripe支付相关配置
发给 ChatGPT / Claude 等 AI,可更快消化本页并上手上站。
朋友,可能你看到这篇文章的时候和我写的时候相隔很久,文章中所说可能已经不是对应官网的最新信息,需要你将文章发给AI让其确认是否还可行后再去做,感谢理解
Stripe 支付与订阅接入指南
本指南介绍如何在基于 TanStack 模板的 SaaS 应用中接入与配置 Stripe 处理一次性权益购买与循环订阅(支持国际信用卡/借记卡,并在 CNY 人民币场景下支持微信支付与支付宝)。
前置准备:账号与卡片
开通 Stripe 前,您需要拥有香港主流银行账户或境外银行卡。
1. 银行卡与 Stripe 开户参考
- 港卡办理指引:参考香港主流银行开户攻略。
- 个人开通 Stripe:参考如何用大陆护照+个人港卡注册 Stripe 个人账户。
2. 替代方案:Wise 在线开卡
如果您暂时无法前往香港开卡,可采用 Wise 在线开卡 方案:
- Wise 开通的美元账户可绑定至 PayPal 或辅助海外收结汇。
- 参考:Wise 在线开卡指南 与 未办理港卡看过来:Creem + 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,写入流水
- 发放对应积分/激活或续期订阅
- 发起结账:客户端调用
POST /api/payment/checkout,传入{ product_id, payment_provider, redirect }。 - 校验与建单:服务端根据商品目录校验价格,向 Stripe 创建带有商户订单号(
orderNo)的 Checkout 会话,返回收银台地址checkout_url。 - 前端跳回(引导反馈):用户付款后被引导跳回
/api/payment/callback,服务端做基础状态校验后重定向至个人中心。 - 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:获取测试密钥
- 登录 Stripe 控制台。
- 在控制台右上角打开 Test mode(测试模式) 开关。

- 依次进入 Developers(开发者)> API keys(API 密钥)。
- 复制标准密钥中的:
- Publishable key(可发布密钥):以
pk_test_开头。 - Secret key(私钥):以
sk_test_开头(若无请点击 Reveal live/test key 或 Create secret key 生成)。
- Publishable key(可发布密钥):以
步骤 2:填入管理后台
- 访问本地管理后台:
http://localhost:3000/admin/settings(选择 Payment 标签页)。 - 在 Stripe 分组中:
- 开启 Enable Stripe 开关(
stripe_enabled)。 - 填入
stripe_publishable_key(pk_test_...)。 - 填入
stripe_secret_key(sk_test_...)。
- 开启 Enable Stripe 开关(
- 点击页面底部的 Save(保存)。
步骤 3:本地支付全链路测试
- 访问前台定价页:
http://localhost:3000/pricing。 - 选择任意套餐并点击购买,页面将自动跳转至 Stripe 托管收银台。
- 使用 Stripe 官方提供的测试卡输入信息:
- 卡号:
4242 4242 4242 4242 - 有效期:任意未来月份(如
12/28) - CVC:任意 3 位数(如
123) - 邮编:任意 5 位数
- 卡号:
- 点击支付完成结账,通过本地 Webhook 转发即可触发服务端自动发放权益。
四、生产部署:配置正式环境 API 密钥
项目准备上线接收真实资金时,切换为正式模式:
- 在 Stripe 控制台右上角关闭 Test mode(退出测试模式)。

- 依次进入 Developers(开发者)> API keys。
- 复制正式的 Publishable key(以
pk_live_开头)与 Secret key(以sk_live_开头)。 - 登录线上生产环境后台:
https://你的域名/admin/settings。 - 将正式的
pk_live_...与sk_live_...粘贴到对应输入框并保存。
五、关键环节:配置 Webhook(支付回调与权威履约)
为什么必须配置 Webhook?
- 防止掉单(异常兜底):用户在收银台付完款后若直接关闭浏览器或网络中断,前台回调无法触发。系统必须依靠服务端 Webhook 异步回调确保订单即时入账和权益发放。
- 处理自动续费:月付/年付订阅到期后,Stripe 的后续扣款是后台静默发生的。系统依靠 Webhook 事件自动为用户延长订阅有效期并下发新周期的权益额度。
- 订阅状态与计划变更同步:当用户在客户门户升级、降级、取消待生效、恢复续费或银行卡扣款失败时,由 Webhook 实时同步本地状态。
- 退款自动冲减:当在 Stripe Dashboard 触发全额或部分退款时,系统通过退款事件自动回收尚未消耗的权益额度并标记订单退款。
- 安全防伪验签:请求头附带
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 具体配置步骤
- 登录 Stripe 控制台,点击右上角进入 Developers(开发者)。
- 点击左侧菜单的 Webhooks,点击 + Add destination(或 Add endpoint)。
- 配置端点 URL:
- 严格填入系统的标准接收回调地址:(本地联调时填入内网穿透域名,例如
https://你的域名/api/payment/notify/stripehttps://xxxx.ngrok-free.app/api/payment/notify/stripe)
- 严格填入系统的标准接收回调地址:
- 选择要监听的事件(Select events):
在搜索框中逐一检索并勾选上述 6 个核心事件:checkout.session.completedinvoice.payment_succeededinvoice.payment_failedcustomer.subscription.updatedcustomer.subscription.deletedcharge.refunded
- 确认无误后点击 Add endpoint 保存。
- 进入刚创建好的 Webhook 详情页,在 Signing secret(签名密钥) 处点击 Reveal(显示),复制以
whsec_开头的字符串。 - 登录系统管理后台(
/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 控制台预建对应商品的价格并完成映射:
- 进入 Stripe 控制台 > Product Catalog(产品目录),为每个订阅套餐创建对应的 Recurring 价格,并记录以
price_开头的 Price ID。 - 进入管理后台
/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 账户主体支持开通微信支付和支付宝:
- 登录 Stripe 控制台,在全局搜索栏输入
Payment methods(支付方式)。 - 在支付方式列表中找到 WeChat Pay(微信支付) 与 Alipay(支付宝),点击 Turn on(启用)。
- 根据页面指引提交所需主体材料并等待 Stripe 审核通过。
- 生效规则:在系统实现中,当订单货币为人民币
cny且结算类型为一次性付款时,Stripe 收银台会自动激活微信支付与支付宝渠道供用户选择。
九、常见问题与排错自检
- Q1:前台点击支付提示 "Payment provider 'stripe' is not configured"?
- 检查:进入后台
/admin/settings,确认stripe_enabled开关已开启,且stripe_secret_key已正确填写。
- 检查:进入后台
- Q2:付款成功后权益没有到账?
- 排查:
- 检查 Webhook 地址是否精确配置为
https://你的域名/api/payment/notify/stripe。 - 检查管理后台的
stripe_signing_secret是否与 Stripe 对应端点的whsec_...完全一致。 - 在 Stripe 控制台 Webhooks 列表中查看推送日志的 HTTP 响应状态码(正常应为
200 OK)。
- 检查 Webhook 地址是否精确配置为
- 排查:
- Q3:Cloudflare Workers / Edge 部署时 Webhook 报错?
- 说明:系统底层已采用
constructEventAsync异步验签,支持 Web Crypto 规范,确保在 Workers 和 Node.js 环境下均可平滑验签。
- 说明:系统底层已采用
- Q4:测试模式与生产环境混淆?
- 排查:
pk_test_必须搭配sk_test_与测试 Webhook 密钥;上线前务必统一切换为pk_live_、sk_live_以及生产环境端点生成的whsec_...。
- 排查: