跳转到主要内容
Vibestrap 的支付系统优先服务模板使用者:配置产品,传一个 productId, 模板负责 checkout、webhook、订单入库、积分发放、license 签发和账单门户。

最快路径

大多数项目只需要改三个地方:
  1. 在 Stripe 创建 Products + Prices。
  2. 把 price ID 填进 .env.local
  3. src/config/site.ts 调整套餐和积分包。
调用 checkout 时保持很小:
await createCheckoutAction({ productId: 'pro' });
await createCheckoutAction({ productId: 'credits_standard' });
未登录也能点的购买链接使用:
/checkout?productId=pro
未登录用户会先去登录,登录后回到 /checkout,自动进入托管收银台。

配置层次

siteConfig.billing 是新手最先看的配置:
billing: {
  enabled: true,
  defaultProductId: 'pro',
  successPath: '/settings/billing?status=success',
  cancelPath: '/pricing?status=canceled',
}
siteConfig.demoPlans 定义示例 SaaS 的 4 档套餐。 siteConfig.payment 是高级 Provider 层:默认启用 Stripe;需要备用通道时 再打开 Creem 或 NOWPayments。

Provider 门面

Provider 代码仍然在同一个契约后面:
interface PaymentProvider {
  createCheckout(opts): Promise<{ id: string; url: string }>;
  createPortalLink(opts): Promise<{ url: string }>;
}
Stripe、Creem、NOWPayments 的 webhook 都会被归一化成同一种 NormalizedEventsrc/payment/handlers/core.ts 里的共享 handler 负责写 payment、发积分、签 license、记录 affiliate commission。

幂等

Provider 重试 webhook 是常态。payment 表对 invoiceIdsessionId 都有唯一索引;handler 用 conflict protection 插入订单,再按 paymentId 幂等发放权益。 所以同一个 webhook 重放,不应该产生重复订单、重复积分、重复 license 或重复佣金。

Provider 选择

Provider适合备注
Stripe默认 SaaS 收款订阅、一次性、积分包、账单门户。
Creem备用卡支付/本地通道当 Stripe 不适合你的市场时再启用。
NOWPayments加密货币一次性付款不支持订阅,只适合 invoice 流程。

验证

  1. .env.local 配好 Stripe key 和 price ID。
  2. 运行 pnpm dev
  3. 打开 /checkout?productId=pro
  4. 完成测试支付。
  5. 确认 payment 表出现记录,并且积分/license 正确发放。
  6. 重放 webhook;数据库不应该新增重复数据。