支付成功后自动开通权限流程
概述
当用户支付成功后,系统会自动开通相应的订阅权限和Token额度。本文档说明完整的自动开通流程。
流程说明
1. 创建支付订单
当用户选择套餐并创建支付订单时:
# src/users/billing.py - create_payment()
payment = PaymentRecord(...)
# 保存计划信息到支付记录的外部数据中
payment.external_data = {
"plan": plan.value, # 例如: "personal"
"months": months # 订阅月数
}
关键点:
- 支付记录中保存了订阅计划信息
- 如果免费计划(金额为0),会立即激活,无需支付
2. 支付回调处理
当支付渠道(微信/支付宝/Stripe)发送支付成功回调时:
# src/users/billing.py - handle_payment_callback()
# 1. 验证支付回调签名
# 2. 更新支付状态为 COMPLETED
# 3. 从支付记录中获取订阅计划
plan = payment.external_data.get("plan") # 优先使用创建订单时保存的计划
# 4. 升级订阅
await user_service.upgrade_subscription(payment.user_id, plan)
# 5. 同步更新Token计费配置
await token_billing_service.upgrade_plan(payment.user_id, plan.value)
3. 订阅升级
# src/users/service.py - upgrade_subscription()
# 1. 更新用户订阅信息
subscription.plan = new_plan
subscription.status = SubscriptionStatus.ACTIVE
subscription.started_at = datetime.utcnow()
subscription.expires_at = datetime.utcnow() + timedelta(days=30)
# 2. 同步更新Token计费配置
await token_billing_service.upgrade_plan(user_id, new_plan.value)
4. Token计费配置更新
# src/users/token_billing.py - upgrade_plan()
# 更新用户Token余额表中的套餐配置
UPDATE user_token_balance SET
plan_code = :plan_code,
monthly_quota = :monthly_quota,
updated_at = NOW()
WHERE user_id = :user_id
自动开通的内容
支付成功后,系统会自动完成以下操作:
订阅状态更新
- 套餐类型更新为新套餐
- 订阅状态设置为
ACTIVE - 设置订阅开始时间和到期时间(30天)
Token额度更新
- 更新
user_token_balance表中的套餐代码 - 更新月度Token限额(根据新套餐配置)
- 例如:
- 免费版:50,000 Token/月
- 个人版:500,000 Token/月
- 专业版:2,000,000 Token/月
- 企业版:无限Token
- 更新
权限更新
- 根据新套餐更新用户权限
- 包括:API访问权限、历史记录保留天数、专家访问权限等
API端点
支付回调端点
POST /api/v1/users/payment/callback/{provider}
参数:
provider: 支付渠道(wechat/alipay/stripe)payment_id: 支付订单ID(可选,可从回调数据中解析)callback_data: 支付回调数据(JSON或表单数据)
示例:
# 微信支付回调
curl -X POST "http://localhost:8000/api/v1/users/payment/callback/wechat" \
-H "Content-Type: application/json" \
-d '{
"out_trade_no": "payment_id_here",
"transaction_id": "wx_transaction_id",
"total_fee": 1900,
"trade_state": "SUCCESS"
}'
测试支付回调
模拟支付成功回调
from src.users.billing import billing_service, PaymentProvider
from uuid import UUID
# 假设有一个支付订单ID
payment_id = UUID("your-payment-id-here")
# 模拟支付成功回调
callback_data = {
"transaction_id": "test_transaction_123",
"total_fee": 1900,
"trade_state": "SUCCESS"
}
# 处理回调
success = await billing_service.handle_payment_callback(
payment_id=payment_id,
provider=PaymentProvider.WECHAT,
callback_data=callback_data
)
if success:
print("支付成功,权限已自动开通")
else:
print("支付处理失败")
注意事项
1. 支付记录存储
当前实现使用内存字典 _payments 存储支付记录,生产环境需要改为数据库存储:
# 当前实现(仅用于开发)
self._payments: Dict[UUID, PaymentRecord] = {}
# 生产环境应改为数据库存储
# 需要创建 payments 表并实现持久化
2. 回调签名验证
当前 _verify_callback() 方法返回 True,生产环境必须实现真实的签名验证:
async def _verify_callback(
self,
provider: PaymentProvider,
callback_data: Dict[str, Any]
) -> bool:
"""验证支付回调签名"""
if provider == PaymentProvider.WECHAT:
# 实现微信支付签名验证
# 使用微信支付API密钥验证签名
pass
elif provider == PaymentProvider.ALIPAY:
# 实现支付宝签名验证
pass
# ...
return True # 当前简化处理
3. 计划信息获取
支付回调处理中,优先从支付记录的 external_data 中获取计划信息,确保准确性:
# 优先使用创建订单时保存的计划
plan_value = payment.external_data.get("plan")
if plan_value:
plan = SubscriptionPlan(plan_value)
else:
# 如果没有,尝试从回调数据获取(可能不准确)
plan = callback_data.get("plan", SubscriptionPlan.PERSONAL)
4. 错误处理
- 如果订阅升级失败,会记录警告日志但不会阻止支付状态更新
- 如果Token计费配置更新失败,会记录警告日志但不会回滚订阅升级
相关文件
src/users/billing.py- 支付服务和回调处理src/users/service.py- 用户服务和订阅管理src/users/token_billing.py- Token计费服务src/users/router.py- 支付回调API端点
流程图
用户选择套餐
↓
创建支付订单(保存计划信息)
↓
用户完成支付
↓
支付渠道发送回调
↓
验证回调签名
↓
更新支付状态为 COMPLETED
↓
从支付记录获取订阅计划
↓
升级用户订阅
↓
更新Token计费配置
↓
权限自动开通完成
总结
✅ 支付成功后会自动开通权限
流程包括:
- 支付回调验证
- 订阅状态更新
- Token额度更新
- 权限配置更新
所有操作在支付回调处理中自动完成,用户无需手动操作。