Stripe 支付集成
概述
MysticX 使用 Stripe 处理订阅计费和一次性积分包购买,通过 Better Auth Stripe 插件集成。
产品
订阅
| 产品 | 月付 | 年付(7 折) |
|---|---|---|
| Gold | $19.99/月 | $167.92/年(约 $13.99/月) |
| Diamond | $69.99/月 | $587.92/年(约 $48.99/月) |
积分包(一次性购买)
| 积分包 | 价格 |
|---|---|
| 入门包(2,000 积分) | $9.99 |
| 热门包(5,000 积分) | $19.99 |
| 超值包(12,000 积分) | $39.99 |
| 大礼包(30,000 积分) | $79.99 |
积分包使用即时 price_data(无需预先创建 Stripe Price ID)。
设置
1. Stripe Dashboard 配置
产品和价格
在 Stripe Dashboard 中创建产品:
- Gold Monthly — $19.99/月 循环
- Gold Yearly — $167.92/年 循环
- Diamond Monthly — $69.99/月 循环
- Diamond Yearly — $587.92/年 循环
在环境变量中设置 Price ID 或使用默认值。
Webhook 端点
将 Webhook 指向:{APP_URL}/api/auth/stripe/webhook
必需事件:
checkout.session.completedinvoice.payment_succeededcustomer.subscription.updatedcustomer.subscription.deleted
客户门户
启用 Stripe 客户门户并配置以下设置:
- 按比例计费:升级立即生效
- 降级:在当前周期结束时生效
- 取消:在当前周期结束时生效
- 允许客户更新支付方式
2. 环境变量
env
STRIPE_SECRET_KEY=sk_live_...
STRIPE_WEBHOOK_SECRET=whsec_...订阅生命周期
新订阅
- 用户在定价页面点击"订阅"
- 应用通过 Better Auth 创建 Stripe Checkout Session
- Stripe 重定向到结账页面
- 完成后,Webhook 触发
checkout.session.completed - 应用更新用户等级并创建订阅记录
- 发放积分(月度积分 + 按比例补偿)
升级(Gold → Diamond)
- Stripe 处理周期中按比例计费(立即收取差额)
- Webhook 触发
customer.subscription.updated - 应用更新等级为 DIAMOND
- 发放积分差额
降级(Diamond → Gold)
- 变更在当前周期结束时生效(不立即收费)
- 下一个计费周期时 Webhook 触发
- 应用更新等级为 GOLD
取消订阅
- 用户通过客户门户或应用取消
- 订阅状态变为
cancel_at_period_end - 访问权限持续到周期结束
- 周期结束时 Webhook 触发
customer.subscription.deleted - 应用更新等级为 FREE
支付失败
- Stripe 按催缴计划重试(建议:2 周内重试 3 次)
- 如果所有重试均失败,订阅将被取消
- 应用处理优雅降级
一次性积分购买
- 用户在积分购买弹窗中选择积分包
- 应用使用即时
price_data创建 Stripe Checkout Session - 完成后,Webhook 发放积分并附加等级奖励
- 交易记录到
CreditTransaction(按 invoice ID 保证幂等性)
安全措施
- 频率限制:每用户每 60 秒最多 5 次购买尝试
- 幂等性:所有积分发放通过 invoice ID 检查已有
CreditTransaction - 元数据完整性:Checkout Session 包含用户 ID 和积分包元数据以供验证
- Webhook 签名验证:所有 Webhook 通过
STRIPE_WEBHOOK_SECRET验证
返回后轮询
Stripe 重定向回应用后:
- 客户端轮询订阅/积分状态(最多 5 次尝试,间隔 2 秒)
- 处理 Webhook 在重定向后才到达的竞态条件
- 确认后显示成功状态
关键实现说明
- Stripe Customer ID 在首次购买时通过 Better Auth 插件自动创建
- Customer ID 存储在用户记录中(
stripeCustomerId) - 所有订阅状态变更通过 Webhook 进行(绝不通过直接 API 轮询获取状态)
- 定价页面位于
/membership,显示当前计划、升降级选项和管理订阅按钮