forked from wangziqi/gongxue-base
feat: add payment provider webhooks
This commit is contained in:
@@ -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 套餐。
|
||||
|
||||
@@ -92,11 +92,13 @@
|
||||
| SVIP 套餐 | 可联调 | `/api/catalog/svip-plans` |
|
||||
| 创建订单/订单列表 | 可联调 | `/api/commerce/orders` |
|
||||
| 手工支付确认 | 迁移期 | 可用于测试,不是生产支付 |
|
||||
| 微信支付 JSAPI | 可联调 | `/api/commerce/payments/create`、`notify/wechat_pay`,已覆盖 API v3 签名、通知解密、幂等和权益开通 |
|
||||
| 支付宝 WAP/H5 | 可联调 | `/api/commerce/payments/create`、`notify/alipay`,已覆盖 RSA2 通知验签、幂等和权益开通 |
|
||||
| 权益查询/校验 | 可联调 | `/api/commerce/entitlements` |
|
||||
| 激活码兑换 | 可联调 | 事务开通权益 |
|
||||
| 优惠券后台配置 | 可联调 | `/api/tenant-admin/coupons` |
|
||||
| 优惠券前台兑换/下单抵扣 | 待补齐 | 后端还需接入下单计算 |
|
||||
| 微信/支付宝/小程序支付 | 待补齐 | 需 provider、验签、幂等、退款、补偿 |
|
||||
| 退款/补偿/对账 | 待补齐 | 需退款接口、支付补偿任务、对账、异常订单处理 |
|
||||
|
||||
## 租户后台与平台后台
|
||||
|
||||
|
||||
@@ -49,8 +49,8 @@
|
||||
### P1 商用功能完善
|
||||
|
||||
1. 支付
|
||||
- 微信支付、支付宝、XPay 或实际使用的支付网关 adapter。
|
||||
- webhook 验签、幂等、退款、支付补偿任务。
|
||||
- 已完成微信支付 JSAPI、支付宝 WAP/H5 的创建支付参数和 webhook 幂等开通权益。
|
||||
- 继续补退款、支付补偿任务、对账、异常订单处理。
|
||||
- 租户自有商户收款和平台代收/服务商模式。
|
||||
|
||||
2. 国内登录和短信
|
||||
|
||||
@@ -146,7 +146,7 @@ tenant:<tenantId>:theme
|
||||
| 知识手册 | `/api/catalog/handbook-subjects`、`handbook-chapters`、`handbook-entries` |
|
||||
| 分数线 | `/api/scoreline/fields`、`schools`、`majors`、`records`、`trend`、`years` |
|
||||
| 资料下载 | `/api/catalog/assets`、`/api/catalog/assets/download` |
|
||||
| 商城 | `/api/catalog/svip-plans`、`POST /api/commerce/orders` |
|
||||
| 商城 | `/api/catalog/svip-plans`、`POST /api/commerce/orders`、`POST /api/commerce/payments/create` |
|
||||
| 订单/权益 | `/api/commerce/orders`、`/api/commerce/entitlements` |
|
||||
| 激活码兑换 | `POST /api/commerce/activation-codes/redeem` |
|
||||
| 个人中心 | `GET/PATCH /api/profile/me` |
|
||||
@@ -245,6 +245,74 @@ identity.unionId
|
||||
- 如果登录前已经解析到推广码,登录成功后再调用 `/api/referral/bind` 完成首绑保护。
|
||||
- 手机号授权后续应走独立的“绑定手机号”接口,不要把微信手机号解密逻辑写在页面里。
|
||||
|
||||
## 支付对接
|
||||
|
||||
支付流程必须以后端订单金额和后端回调为准,前端只负责拉起支付。
|
||||
|
||||
### 创建订单
|
||||
|
||||
```text
|
||||
POST /api/commerce/orders
|
||||
body: {
|
||||
"planId": "<svipPlanId>",
|
||||
"quantity": 1,
|
||||
"payProvider": "wechat_pay | alipay",
|
||||
"payMethod": "jsapi | wap",
|
||||
"regionId": "<regionId>"
|
||||
}
|
||||
```
|
||||
|
||||
返回 `orderNo` 后,再创建支付参数:
|
||||
|
||||
```text
|
||||
POST /api/commerce/payments/create
|
||||
body: {
|
||||
"orderNo": "<orderNo>",
|
||||
"provider": "wechat_pay",
|
||||
"openId": "<微信小程序登录后的 openId>"
|
||||
}
|
||||
```
|
||||
|
||||
微信小程序返回的 `paymentParams` 可直接映射到 `Taro.requestPayment`:
|
||||
|
||||
```text
|
||||
appId
|
||||
timeStamp
|
||||
nonceStr
|
||||
package
|
||||
signType
|
||||
paySign
|
||||
```
|
||||
|
||||
支付宝 H5/WAP 返回:
|
||||
|
||||
```text
|
||||
paymentParams.url
|
||||
```
|
||||
|
||||
H5 可以跳转到该 URL。小程序端如果后续要接支付宝小程序,需要新增独立 provider/method,不要复用 H5 WAP URL。
|
||||
|
||||
支付完成后前端不要自行开通会员。前端应轮询或重新请求:
|
||||
|
||||
```text
|
||||
GET /api/commerce/orders
|
||||
GET /api/commerce/entitlements
|
||||
```
|
||||
|
||||
后端支付回调地址由租户支付账户配置:
|
||||
|
||||
```text
|
||||
/api/commerce/payments/notify/wechat_pay?tenantId=<tenantId>
|
||||
/api/commerce/payments/notify/alipay?tenantId=<tenantId>
|
||||
```
|
||||
|
||||
前端禁止:
|
||||
|
||||
- 传入自定义金额。
|
||||
- 伪造支付成功状态。
|
||||
- 保存商户号私钥、API v3 key、支付宝应用私钥。
|
||||
- 在页面里实现 webhook 验签或权益开通。
|
||||
|
||||
## 第一阶段页面建议
|
||||
|
||||
1. `pages/bootstrap/index`
|
||||
|
||||
Reference in New Issue
Block a user