计费与支付
逐步启用 Stripe、Creem、Dodo 或 Waffo,验证结账、Webhook、积分、取消和退款。
支付默认关闭
Flare 带有 Stripe、Creem、Dodo 和 Waffo 的适配实现,默认 product.billing.enabled 为 [],所有网关产品映射为空。这表示源码能力已包含,不能理解为复制仓库后就能收款。在线演示也不提供真实收款验收环境。
模板自身的订阅价格来自 packages/config/src/index.ts,与 MuseMVP 官网销售源码模板的价格、商品 ID 和结账规则相互独立。
第一步:建立自己的商品
当前 catalog 有两个示例:
| planId | amount / currency | 购买类型 | credits |
|---|---|---|---|
pro-monthly | 1900 / USD | recurring | 1000 |
lifetime | 9900 / USD | one-time | 10000 |
金额是货币最小单位的整数,不是浮点美元。改价格时同时检查币种、周期、积分、网关商品与前端展示。不要只修改定价页文字。
在选定网关创建对应商品,然后填写该 plan 的 products:Stripe 使用 price_ 价格 ID;Dodo 使用 pdt_ 产品 ID;Creem 使用对应产品 ID;Waffo 填写网关商品标识。测试和正式环境必须使用匹配的 Key、商品与 Webhook。
第二步:启用网关并配置密钥
例如在原文件中将 product 的解析输入改为:
export const product = productSchema.parse({
billing: { enabled: ['stripe'], defaultGateway: 'stripe' },
});这是替换原有 product 初始化语句,不是在文件末尾重复声明。defaultGateway 必须属于 enabled。可以启用多个网关,但每个网关都必须配置完整商品映射及密钥。
| 网关 | 服务端变量 |
|---|---|
| Stripe | STRIPE_SECRET_KEY、STRIPE_WEBHOOK_SECRET |
| Creem | CREEM_API_KEY、CREEM_WEBHOOK_SECRET |
| Dodo | DODO_API_KEY、DODO_WEBHOOK_SECRET |
| Waffo | WAFFO_MERCHANT_ID、WAFFO_PRIVATE_KEY |
本地填 apps/web/.dev.vars;部署填根目录 .env 或 CI 加密变量。Waffo 私钥以单行保存,换行使用 \n。密钥不能进入 publicConfig、浏览器或公开日志。
第三步:登记签名通知
Webhook 地址为 https://your-domain.com/api/webhooks/<gateway>,例如 /api/webhooks/stripe。这是 Flare 自己的路径,不是 Next.js 模板的支付路径。
网关签名验证、事件 ID 去重、订单映射、账本写入和 outbox 共同决定支付结果。浏览器从付款页返回成功 URL 并不证明已经到账;应等服务端签名事件完成处理,再在账单与用量中查看订单和积分。
checkout 输入为 {planId,gateway,requestId},requestId 必须为 UUID。一次业务尝试的重试应保留其标识,避免重复建单;新的购买才使用新的标识。用户必须登录,且 plan 与 gateway 在服务端允许范围内。
第四步:验证客户操作
/app/billing 使用自己的订单发起 portal 或 cancel,对应 POST /api/billing/manage。四个网关都保留已有 portal/cancel 适配;实际账户是否开放某项能力应以网关响应为准,失败需要展示错误。
退款与取消续费是两件事。当前 Stripe、Creem、Dodo 支持针对最新可退支付的全额退款;Waffo 的退款创建走网关后台,再由签名事件对账。部分退款不会自动按比例回退积分。不要自行加一个客户端余额减法来填补此差异。
管理后台与重试
/app/admin 可查看订单、Webhook、退款与审计。重复事件应返回已有结果,不能重复发放积分。操作未知结果或网络超时后,先查询网关状态及本地审计;不要盲目再次退款。任务租约、幂等账本和 outbox 必须保持原有边界。
退款并不等于停止下次续费。验收时分别确认本次支付状态、退款状态与订阅状态。
上线前验证
- 运行
pnpm muse:doctor --target production --json,确认启用网关的配置齐全。 - 在受控测试环境完成结账,确认金额、币种、周期与商品一致。
- 重放同一签名事件,确认只产生一份权益及积分。
- 验证失败付款、取消、portal、退款,以及用户之间的订单隔离。
- 核对 Webhook 日志与账本,不把跳转页或本地 mock 测试当作真实支付成功。
常见问题:无支付按钮先检查 enabled;结账失败检查产品映射与环境;通知失败检查原始请求签名与 webhook secret;积分未到账先查事件处理状态,避免手工重复补发。继续阅读 环境变量 与 部署。