feat: add payment provider webhooks

This commit is contained in:
Codex
2026-06-28 22:42:27 +08:00
parent dee82e670f
commit db65295ddc
11 changed files with 1286 additions and 39 deletions

View File

@@ -27,6 +27,9 @@ Supabase Auth 可继续作为最终 JWT 用户体系目标;本地重构期先
- `app_private.auth_sessions`:迁移期 session token hash。
- 阿里云短信 `SendSms` provider使用租户级 AccessKey、签名、模板发送。
- 腾讯云短信 `SendSms` provider使用租户级 SecretId/SecretKey、SdkAppId、签名、模板发送。
- `POST /api/commerce/payments/create`:按订单创建微信支付 JSAPI 或支付宝 WAP 支付参数。
- `POST /api/commerce/payments/notify/wechat_pay`:微信支付 API v3 通知验签、AES-GCM 解密、幂等落库和权益开通。
- `POST /api/commerce/payments/notify/alipay`:支付宝 RSA2 通知验签、幂等落库和权益开通。
## 短信 Provider
@@ -129,10 +132,73 @@ Supabase Auth 可继续作为最终 JWT 用户体系目标;本地重构期先
支付不走 Supabase 内置能力。推荐继续扩展 `commerce`
- `POST /api/commerce/orders` 只负责创建订单,金额以后端套餐为准。
- `POST /api/commerce/payments/:provider/create` 后续按 provider 创建支付参数或收银台地址。
- `POST /api/commerce/payments/:provider/notify` 统一落 `payment_events`,先验签、再幂等、再更新订单和权益。
- `POST /api/commerce/payments/create` 按 provider 创建支付参数或收银台地址。
- `POST /api/commerce/payments/notify/<provider>` 统一落 `payment_events`,先验签、再幂等、再更新订单和权益。
- 支付成功继续复用 `grantSvipEntitlement`,避免微信/支付宝/XPay 各写一套开通逻辑。
当前支持:
- `wechat_pay`:微信支付 API v3 JSAPI 下单;通知验签后用 API v3 key 解密 `resource`
- `alipay`:支付宝 WAP/H5 支付参数生成;通知按 RSA2 验签。
- `manual`:仅本地/运营手工确认,不作为生产自动支付。
### 微信支付配置示例
```json
{
"provider": "wechat_pay",
"mode": "tenant_collect",
"status": "active",
"configPublic": {
"appId": "wx...",
"merchantId": "1900000001",
"merchantSerialNo": "商户证书序列号",
"notifyUrl": "https://api.example.com/api/commerce/payments/notify/wechat_pay?tenantId=<tenantId>",
"wechatpayPublicKey": "微信支付平台证书公钥或平台公钥"
},
"secret": {
"secretScope": "payment",
"secretKey": "wechat_pay",
"secretJson": {
"privateKey": "商户 API 证书私钥 PEM",
"apiV3Key": "32位 API v3 key"
}
}
}
```
### 支付宝配置示例
```json
{
"provider": "alipay",
"mode": "tenant_collect",
"status": "active",
"configPublic": {
"appId": "2021000000000000",
"notifyUrl": "https://api.example.com/api/commerce/payments/notify/alipay?tenantId=<tenantId>",
"returnUrl": "https://h5.example.com/pay/success"
},
"secret": {
"secretScope": "payment",
"secretKey": "alipay",
"secretJson": {
"privateKey": "应用私钥 PEM",
"alipayPublicKey": "支付宝公钥 PEM"
}
}
}
```
支付回调处理规则:
- `payment_events(provider,event_id)` 幂等。
- 通知验签/解密失败直接拒绝,不更新订单。
- 通知金额必须等于后端订单金额。
- 订单已支付时重复通知只返回幂等成功,不重复开通权益。
- 支付成功事务内更新 `orders``payments``payment_events``entitlements`
- 支付密钥只允许放在 `app_private.tenant_secrets` 或生产 KMS/Vault。
B 端合作商年费、服务费、服务器资源费不走学生端 `orders`,而是走平台账务:
- `platform_saas_plans`:平台售卖给合作商的 SaaS 套餐。