fix(paywall): clarify response fields and payment channel options
This commit is contained in:
+35
-20
@@ -325,7 +325,9 @@ if (data.blocked === true && data.blockReason === "daily_limit") {
|
||||
|
||||
## 5. POST /api/chat/send 完整响应结构
|
||||
|
||||
`data` 字段的**全部字段**(现有 + 新增),所有 `/api/chat/send` 响应都包含:
|
||||
`data` 字段的**全部字段**(现有 + 新增),所有 `/api/chat/send` 响应都包含:
|
||||
|
||||
> 注意:`privateLocked` / `privateHint` / `isPrivate` **不属于** `/api/chat/send` 的响应字段;它们只出现在 `GET /api/chat/history` 的 `data.messages[]` 单条历史消息里。私密消息由后端异步打标,因此前端要在刷新/拉取历史时根据 `privateLocked=true` 渲染模糊锁定卡片。
|
||||
|
||||
| 字段 | 类型 | 现有/新增 | 说明 |
|
||||
|------|------|----------|------|
|
||||
@@ -341,8 +343,8 @@ if (data.blocked === true && data.blockReason === "daily_limit") {
|
||||
| `isGuest` | bool \| null | 现有 | 是否游客 |
|
||||
| `timestamp` | int | 现有 | Unix 毫秒时间戳 |
|
||||
| `blocked` | bool \| null | 现有 | 是否每日限流拦截(功能①) |
|
||||
| `blockReason` | string \| null | 现有 | `"daily_limit"` |
|
||||
| `blockDetail` | object \| null | 现有 | `{ type, usedToday, limit }` |
|
||||
| `blockReason` | string \| null | 现有 | `"daily_limit"` / `"total_limit"` |
|
||||
| `blockDetail` | object \| null | 现有 | 每日限制:`{ type, usedToday, limit }`;游客总量限制:`{ type, usedTotal, limit }` |
|
||||
| `paywallTriggered` | bool | 新增 | 是否触发图片付费墙(功能②) |
|
||||
| `showUpgrade` | bool | 新增 | **前端是否展示开会员引导** |
|
||||
| `imageType` | string \| null | 新增 | `null` / `"elio_schedule"` |
|
||||
@@ -398,20 +400,21 @@ if (data.blocked === true && data.blockReason === "daily_limit") {
|
||||
| `plan_name` | string | 展示名称 |
|
||||
| `order_type` | string | 传给支付服务 B 的订单类型 |
|
||||
| `amount_cents` | int | 金额,单位为分 |
|
||||
| `currency` | string | 当前为 `CNY` |
|
||||
| `original_amount_cents` | int \| null | 原价/划线价,单位为分;仅 VIP 套餐返回 |
|
||||
| `daily_price_cents` | int \| null | 日均展示价,单位为分;仅 VIP 套餐返回 |
|
||||
| `currency` | string | VIP 套餐当前为 `USD`;DOL 充值项当前为 `CNY` |
|
||||
| `vip_days` | int \| null | VIP 增加天数,`null` 表示永久或非 VIP 商品 |
|
||||
| `dol_amount` | int \| null | DOL 积分数量,VIP 商品为 `null` |
|
||||
|
||||
当前套餐:
|
||||
|
||||
| plan_id | plan_name | order_type | amount_cents | 发放内容 |
|
||||
|---|---|---:|---:|---|
|
||||
| `vip_monthly` | 月度会员 | `vip_monthly` | 999 | VIP +30 天 |
|
||||
| `vip_quarterly` | 季度会员 | `vip_quarterly` | 2499 | VIP +90 天 |
|
||||
| `vip_annual` | 年度会员 | `vip_annual` | 5999 | VIP +365 天 |
|
||||
| `vip_lifetime` | 永久会员 | `vip_lifetime` | 19999 | 永久 VIP |
|
||||
| `dol_100` | 100 DOL | `dol` | 600 | DOL +100 |
|
||||
| `dol_500` | 500 DOL | `dol` | 2800 | DOL +500 |
|
||||
| plan_id | plan_name | order_type | amount_cents | original_amount_cents | daily_price_cents | currency | 发放内容 |
|
||||
|---|---|---:|---:|---:|---:|---|---|
|
||||
| `vip_monthly` | Monthly | `vip_monthly` | 1990 | 2490 | 66 | USD | VIP +30 天 |
|
||||
| `vip_quarterly` | Quarterly | `vip_quarterly` | 4990 | 5990 | 55 | USD | VIP +90 天 |
|
||||
| `vip_annual` | Annual | `vip_annual` | 16990 | 19990 | 47 | USD | VIP +365 天 |
|
||||
| `dol_100` | 100 DOL | `dol` | 600 | null | null | CNY | DOL +100 |
|
||||
| `dol_500` | 500 DOL | `dol` | 2800 | null | null | CNY | DOL +500 |
|
||||
|
||||
#### POST /api/payment/create-order
|
||||
|
||||
@@ -438,7 +441,7 @@ Content-Type: application/json
|
||||
| 字段 | 必填 | 说明 |
|
||||
|---|---|---|
|
||||
| `planId` | 是 | 来自 `GET /api/payment/plans` 的 `plan_id` |
|
||||
| `payChannel` | 是 | 当前支持 `stripe` / `ezpay` |
|
||||
| `payChannel` | 是 | 支付通道取值约定:`stripe` / `ezpay` / `paycools`。当前生产代码若仍只放开 `stripe` / `ezpay`,需要同步把 A/B 两侧白名单加上 `paycools` |
|
||||
| `autoRenew` | 是 | 是否自动续费;DOL 和永久会员建议传 `false` |
|
||||
|
||||
成功响应:
|
||||
@@ -455,7 +458,18 @@ Content-Type: application/json
|
||||
}
|
||||
```
|
||||
|
||||
`payParams` 是支付服务 B 返回给前端的拉起支付信息。对于 PayPal / Stripe Checkout / ezPay 这类浏览器跳转支付,B 必须在 `payParams` 内提供可直接打开的支付链接。
|
||||
`payParams` 是支付服务 B 返回给前端的拉起支付信息。对于 Stripe Checkout / ezPay / PayCools 这类浏览器跳转支付,B 必须在 `payParams` 内提供可直接打开的支付链接。PayCools 返回的支付链接应放在 `checkout_url`、`payment_url` 或 `url` 中。
|
||||
|
||||
当前 Stripe 返回为 Checkout 链接模式。前端创建订单成功后应优先打开:
|
||||
|
||||
1. `data.paymentUrl`
|
||||
2. `data.checkoutUrl`
|
||||
3. `data.url`
|
||||
4. `data.payParams.paymentUrl`
|
||||
5. `data.payParams.checkoutUrl`
|
||||
6. `data.payParams.url`
|
||||
|
||||
打开支付链接后继续轮询 `GET /api/payment/order-status?order_id=...`;支付服务 B 收到 Stripe webhook 后会发布 MQ,后端 A 消费后把订单从 `pending` 更新为 `paid`。
|
||||
|
||||
前端读取支付链接的优先级:
|
||||
|
||||
@@ -470,7 +484,7 @@ Content-Type: application/json
|
||||
|
||||
| 状态码 | 场景 |
|
||||
|---|---|
|
||||
| `400` | `planId` 无效,或 `payChannel` 不是 `stripe` / `ezpay` |
|
||||
| `400` | `planId` 无效,或 `payChannel` 不是后端当前放开的支付通道 |
|
||||
| `401` | 未登录或 token 无效 |
|
||||
| `502` | `PAYMENT_SERVICE_URL` 未配置,或支付服务 B 创建订单失败 |
|
||||
| `500` | 后端 A 创建订单过程中发生未知错误 |
|
||||
@@ -545,10 +559,10 @@ Content-Type: application/json
|
||||
{
|
||||
"user_id": "用户 UUID",
|
||||
"order_type": "vip_monthly",
|
||||
"pay_channel": "stripe",
|
||||
"pay_channel": "paycools",
|
||||
"automatic_renewal": true,
|
||||
"amount_cents": 999,
|
||||
"currency": "CNY"
|
||||
"amount_cents": 1990,
|
||||
"currency": "USD"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -567,7 +581,8 @@ B 必须返回:
|
||||
|
||||
- `pay_params` 结构由支付服务 B 决定,后端 A 不解析,前端原样使用。
|
||||
- 浏览器跳转支付必须返回可打开的 URL,推荐统一使用 `pay_params.checkout_url`。
|
||||
- 当前 A/B 已确认支持的 `pay_channel` 是 `stripe` / `ezpay`;如果要接 PayPal,需要先由支付服务 B 的 `/orders` 支持 `paypal`,再把后端 A 的渠道校验和前端选项一起放开。
|
||||
- PayCools 返回支付链接时,建议放在 `pay_params.checkout_url`;前端也兼容 `payment_url` / `approval_url` / `url`。
|
||||
- 当前支付对接文档约定的 `pay_channel` 是 `stripe` / `ezpay` / `paycools`;生产代码也需要同步支持这些取值。如果要接其他通道,需要先由支付服务 B 的 `/orders` 支持该通道,再把后端 A 的渠道校验和前端选项一起放开。
|
||||
- 后端 A 会把 `order_id`、`user_id`、`order_type`、`plan_id`、`status=pending` 写入本地 `orders` 表。
|
||||
- 发放什么权益由 A 侧 `plan_id` 决定,B 不需要知道 VIP 天数或 DOL 数量。
|
||||
|
||||
@@ -684,7 +699,7 @@ PAYMENT_WEBHOOK_SECRET=<MQ 消息签名密钥,可空>
|
||||
2. GET /api/payment/plans 加载套餐
|
||||
3. 用户选择 planId、payChannel、autoRenew
|
||||
4. POST /api/payment/create-order
|
||||
5. 从 data.payParams 读取 checkout_url/payment_url/approval_url/url 并打开支付页,或按约定调用支付 SDK
|
||||
5. 从 data.payParams 读取 checkout_url/payment_url/approval_url/url 并打开支付页,PayCools 链接也走这个逻辑,或按约定调用支付 SDK
|
||||
6. 每 3~5 秒 GET /api/payment/order-status?order_id=...
|
||||
7. 收到 paid 或 WebSocket payment_success 后停止轮询
|
||||
8. payType=vip 时调用 /api/payment/vip-status 并刷新本地会员状态
|
||||
|
||||
Reference in New Issue
Block a user