mirror of
https://github.com/unnoo/zsxq-skill.git
synced 2026-09-14 19:59:58 +08:00
fix: harden Skill Pay order flow
This commit is contained in:
+5
-11
@@ -105,8 +105,8 @@ User (user_id) — 已登录账户
|
||||
|
||||
- **禁止输出或传播认证 token** —— token 是登录凭证,不在终端明文输出,不分享给他人
|
||||
- **写入/删除操作前必须确认用户意图**(发帖、编辑、评论、回答、定时发布、设置精华/置顶、修改星球资料、创建笔记、删除主题或笔记、取消定时任务、提交 NPS 反馈等)
|
||||
- **Skill Pay 仅支持 WorkBuddy 宿主**;在 Claude Code(CC)等非 WorkBuddy 环境中,必须在创建订单前说明不支持并停止,不得调用 `call_zsxq_api` 创建订单
|
||||
- **创建订单前必须按订单类型查询或计算价格,并确认类型、对象与实际应付金额;接口金额单位为“分”,向用户统一换算成“元”展示;付费提问和赞赏订单还要确认将传入接口的整数 `amount`,支付必须由用户本人授权**;`PAYMENT_REQUIRED` 仅表示待支付,不代表支付成功,禁止自动重试创建订单
|
||||
- **Skill Pay 仅支持 WorkBuddy 且宿主必须提供官方 `weixinpay_pay`**;任一条件不满足时,必须在创建订单前说明不支持并停止,不得调用 `call_zsxq_api` 创建订单
|
||||
- **创建订单前必须按原子 reference 查询或计算价格,并确认类型、对象与实际应付金额;固定价格不得由用户改写,支付必须由用户本人授权**;`PAYMENT_REQUIRED` 即使返回 `success: false` 也只表示待支付,不代表失败或支付成功,禁止自动重试创建订单
|
||||
- 不确定 `group_id` / `topic_id` / `comment_id` / `note_id` 时,先用查询命令确认,再执行写入或删除
|
||||
- **笔记是公开内容**,任何持有链接的人均可访问 —— 涉及隐私或敏感信息不要写进笔记
|
||||
- `api raw` 写入不得绕过原子操作的安全约束;探索模式发现的写入接口同样需要用户确认
|
||||
@@ -134,16 +134,10 @@ User (user_id) — 已登录账户
|
||||
|
||||
## Skill Pay
|
||||
|
||||
Skill Pay 仅支持在 WorkBuddy 中使用。处理购买意图时先确认当前宿主:若不是 WorkBuddy(如 Claude Code / CC),告知用户需切换到 WorkBuddy 并停止,不得创建订单;确认是 WorkBuddy 后,再读取对应 reference 并使用底层接口工具 `call_zsxq_api`。
|
||||
处理 Skill Pay 购买意图时,读取购买场景进行编排;创建订单、价格、支付授权和安全恢复的参数与错误语义只以原子 reference 为准。
|
||||
|
||||
| 操作 | 工具与参数 | Reference |
|
||||
|------|------------|-----------|
|
||||
| 查询购买价格 | `call_zsxq_api`:按订单类型读取价格或续费折扣 | [`wechat-order-create.md#下单前查询价格`](references/wechat-order-create.md#下单前查询价格) |
|
||||
| 创建微信订单 / 触发 Skill Pay | `call_zsxq_api`:创建订单 ⚠️ | [`wechat-order-create.md`](references/wechat-order-create.md) |
|
||||
| 请求微信支付授权 | 宿主官方 `weixinpay_pay`:传入 `paymentCode` ⚠️ | [`wechat-order-create.md#宿主微信支付授权`](references/wechat-order-create.md#宿主微信支付授权) |
|
||||
| SkillHub 预下单安全恢复 | 使用 `payment_retry_token`,可带匹配的 `out_trade_no`;不重发 `body` ⚠️ | [`wechat-order-create.md`](references/wechat-order-create.md) |
|
||||
|
||||
> ⚠️ 创建订单是财务相关写入。首次下单前按订单类型查询或计算价格,再确认类型、对象与实际应付金额;接口金额统一换算成“元”向用户展示,`1 元 = 1 星球币`。付费提问和赞赏订单还要确认将传入接口的整数 `amount`。支付卡片必须由用户本人确认。
|
||||
- 购买场景:[`scenarios/purchase-with-skill-pay.md`](references/scenarios/purchase-with-skill-pay.md)
|
||||
- 创建订单原子操作:[`wechat-order-create.md`](references/wechat-order-create.md)
|
||||
|
||||
## 星球管理(group)
|
||||
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
## 所需输入
|
||||
|
||||
- 订单类型及业务含义
|
||||
- 与类型对应的目标 ID:`group_id`、`topic_id`、`comment_id`、`user_id` 或 `back_issue_id`;轻读查价需要 `group_id` 和 `back_issue_id`
|
||||
- 与类型对应的目标 ID;赞赏评论需要 `topic_id` 和 `comment_id`,轻读需要 `group_id` 和 `back_issue_id`
|
||||
- 按订单类型查询或计算出的应付金额
|
||||
- 付费提问和赞赏订单以“分”为单位的接口整数 `amount`
|
||||
- 需要用户定价时,由用户指定的金额
|
||||
- 按需提供:优惠券码、验证信息
|
||||
|
||||
## 使用的原子操作
|
||||
@@ -46,20 +46,9 @@
|
||||
|
||||
使用只读操作核对目标名称/内容及 ID,并只保留该订单类型必要的字段。
|
||||
|
||||
先按 [wechat-order-create:下单前查询价格](../wechat-order-create.md#下单前查询价格)查询或计算价格:
|
||||
完整执行 [wechat-order-create:下单前查询价格](../wechat-order-create.md#下单前查询价格);需要用户定价时,同时执行其[金额换算规则](../wechat-order-create.md#金额换算规则)。字段路径、价格公式、固定价格不可改写及停止规则均以该原子 reference 为准,本场景不另行定义。
|
||||
|
||||
- 付费加入和礼品卡读取星球公开信息中的基础价,均无折扣。
|
||||
- 续费读取成员视角的星球信息,根据当前用户有效期选择提前续费、过期 30 天内或过期超过 30 天的折扣比例,再计算续费价。
|
||||
- 轻读读取轻读详情价格;创建星球邀请码固定为 `800 元(80000 分)`。
|
||||
|
||||
接口金额单位为“分”,面向用户统一换算成“元”并展示币种;续费还要呈现基础价、适用折扣和当前有效期。以下订单的金额由用户指定,并且还必须确认即将传给接口的整数 `amount`:
|
||||
|
||||
- `question_fee`
|
||||
- `reward_user`
|
||||
- `reward_topic`
|
||||
- `reward_comment`
|
||||
|
||||
所有金额按 `金额(分) ÷ 100` 换算成“元”展示,且 `1 元 = 1 星球币`。例如接口金额 `1234` 应向用户展示为 `12.34 元(等值 12.34 星球币)`。实际应付金额无法核对,或接口分值与展示元值无法可靠对应,则停止并让用户补充。只有上述四类订单把金额作为 `amount` 传入创建订单请求,其它订单不传 `amount`。
|
||||
赞赏评论时,若只有 `comment_id` 而没有所属 `topic_id`,停止并请用户补充主题;取得两者后再用 `get_topic_comments` 核对。轻读只有链接或 `back_issue_id`、无法可靠取得所属 `group_id` 时同样停止并请用户补充,不得猜测。
|
||||
|
||||
### 第三步:创建订单前确认
|
||||
|
||||
@@ -67,17 +56,13 @@
|
||||
|
||||
### 第四步:处理支付挑战
|
||||
|
||||
收到 `PAYMENT_REQUIRED` 时:
|
||||
|
||||
1. 保存响应中的 `out_trade_no`,保持字符串精度。
|
||||
2. 按 [wechat-order-create:宿主微信支付授权](../wechat-order-create.md#宿主微信支付授权)读取 `_meta.WeixinPay.WeixinPay-Required`(宿主未暴露 `_meta` 时读取 `payment.payment_code`),并将原值作为 `paymentCode` 调用官方 `weixinpay_pay`,展示微信支付授权卡片。
|
||||
3. 将支付决定交给用户,不自动确认、不循环催促、不声称已支付。
|
||||
收到 `code == "PAYMENT_REQUIRED"` 且 `status_code == 402` 时,即使响应为 `success: false`,也按 [wechat-order-create:宿主微信支付授权](../wechat-order-create.md#宿主微信支付授权)完整执行支付码冲突、缺失和 `expires_at` 过期检查。将 `out_trade_no` 原样保存为字符串;由用户在官方支付卡片中决定是否支付。
|
||||
|
||||
### 第五步:完成或停止
|
||||
|
||||
- 用户完成支付:说明订单后续由知识星球原支付回调履约;当前工具无法查单时,不声称支付成功或已履约,可引导用户在知识星球相应页面核对结果。
|
||||
- 用户取消/拒绝/支付超时:停止,不创建第二张订单。
|
||||
- `SKILLHUB_PREORDER_FAILED`:进入安全恢复分支,仅用原响应的 `payment_retry_token` 和可选 `out_trade_no` 重试同一路径,省略 `body`。
|
||||
- `SKILLHUB_PREORDER_FAILED`:按原子 reference 的恢复响应字段与冲突检查进入安全恢复分支。
|
||||
- 其它失败:按原子 reference 的失败语义停止并报告。
|
||||
|
||||
## 分支与停止条件
|
||||
@@ -85,7 +70,7 @@
|
||||
- **宿主不是 WorkBuddy,或 WorkBuddy 未提供官方 `weixinpay_pay`**:说明当前无法完成 Skill Pay,停止且不得创建订单
|
||||
- **订单语义不唯一**:列出订单类型候选,等待用户选定
|
||||
- **对象 ID 不明确/命中多个**:列出候选(ID + 名称/摘要),等待用户选定
|
||||
- **价格接口字段缺失、续费有效期无法判断、实际应付金额无法核对,或四类金额订单的 `amount` 缺失/不是整数分值**:停止,等待用户确认
|
||||
- **原子 reference 要求的对象或价格数据缺失**:停止并请求缺失信息;固定价格订单不得由用户提供任意金额替代查询结果
|
||||
- **订单类型不在支持列表中**:停止并说明当前 Skill Pay 不支持该类型
|
||||
- **`PAYMENT_REQUIRED`**:交给宿主展示支付卡片;不得再次创建订单
|
||||
- **`SKILLHUB_PREORDER_FAILED`**:只用签名 token 恢复 SkillHub 预下单;token 无效/过期则停止
|
||||
@@ -95,14 +80,14 @@
|
||||
|
||||
## 用户确认点
|
||||
|
||||
1. **创建订单前**:确认订单类型、对象 ID、实际应付金额及必要字段;付费提问和赞赏订单同时确认接口整数分值 `amount`、换算后的元值与等值星球币
|
||||
1. **创建订单前**:按原子 reference 确认订单类型、对象、实际应付金额及必要字段
|
||||
2. **支付授权时**:由宿主展示微信支付卡片,必须由用户本人确认;agent 不代操作
|
||||
3. **取消/过期后重新下单前**:视为新财务操作,重新展示完整订单摘要并再次确认
|
||||
|
||||
## 完成标准
|
||||
|
||||
- 已创建唯一订单并把唯一的支付挑战交给支持 Skill Pay 的宿主;或在明确停止条件处安全停止
|
||||
- `out_trade_no` 原样保存且未发生重复下单
|
||||
- `out_trade_no` 原样保存为字符串且未发生重复下单
|
||||
- 不把 `PAYMENT_REQUIRED` 当作支付成功;支付与履约状态表述符合知识星球原支付链路的实际边界
|
||||
- 若发生预下单恢复,仅重试 SkillHub 预下单,没有再次发送订单 body
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
> [!CAUTION]
|
||||
> 创建订单会产生真实待支付订单,完成支付会发生真实资金交易。首先确认当前宿主是 WorkBuddy 且提供官方 `weixinpay_pay`;非 WorkBuddy(如 Claude Code / CC)必须说明不支持并停止,不得创建订单。通过宿主检查后,首次调用前还必须向用户确认:
|
||||
> 1. 订单类型及中文含义
|
||||
> 2. 购买/支付对象(相应的 `group_id`、`topic_id`、`comment_id`、`user_id` 或 `back_issue_id`;轻读查价需同时确认 `group_id` 和 `back_issue_id`)
|
||||
> 3. 按[下单前查询价格](#下单前查询价格)取得的应付金额;接口金额单位为“分”,必须按 `金额 ÷ 100` 换算成“元”向用户展示,不得改写金额。`question_fee`、`reward_user`、`reward_topic`、`reward_comment` 还须确认用户指定并将传入接口的整数 `amount`
|
||||
> 2. 购买/支付对象(相应的 `group_id`、`topic_id`、`comment_id`、`user_id` 或 `back_issue_id`;赞赏评论需同时确认 `topic_id` 和 `comment_id`,轻读查价需同时确认 `group_id` 和 `back_issue_id`)
|
||||
> 3. 按[下单前查询价格](#下单前查询价格)取得的应付金额;接口金额单位为“分”,必须按 `金额 ÷ 100` 换算成“元”向用户展示,不得改写固定价格。`question_fee`、`reward_user`、`reward_topic`、`reward_comment` 由用户以“元”指定金额时,必须按 `amount = 元 × 100` 精确换算成整数分,并同时确认元值和将传入接口的 `amount`
|
||||
> 4. 用户明确提供的优惠券或验证信息等可选字段
|
||||
> 5. 用户在微信支付卡片中仍需再次确认支付;agent 不得代替用户授权支付
|
||||
|
||||
@@ -23,12 +23,12 @@
|
||||
|
||||
| 订单类型 | 查询方式 | 金额字段或规则 |
|
||||
|----------|----------|----------------|
|
||||
| `membership_fee` | `GET /v2/groups/{group_id}/public_info` | `body.resp_data.public_info.policies.payment.amount`,无折扣 |
|
||||
| `gift_card_fee` | `GET /v2/groups/{group_id}/public_info` | 与加入星球相同,读取 `body.resp_data.public_info.policies.payment.amount`,无折扣 |
|
||||
| `renewal_fee` | `GET /v2/groups/{group_id}` | 读取基础价、当前用户有效期和续费折扣,按下方规则计算 |
|
||||
| `membership_fee` | `GET /v2/groups/{group_id}/public_info` | 确认 `body.resp_data.public_info.type` 为 `pay`,读取 `body.resp_data.public_info.policies.payment.amount`,无折扣 |
|
||||
| `gift_card_fee` | `GET /v2/groups/{group_id}/public_info` | 确认 `body.resp_data.public_info.type` 为 `pay`;与加入星球相同,读取 `body.resp_data.public_info.policies.payment.amount`,无折扣 |
|
||||
| `renewal_fee` | `GET /v2/groups/{group_id}` | 确认 `body.resp_data.group.type` 为 `pay`,读取基础价、当前用户有效期和续费折扣,按下方规则计算 |
|
||||
| `back_issue` | `GET /v2/groups/{group_id}/back_issues/{back_issue_id}` | `body.resp_data.back_issue.amount` |
|
||||
| `group_invite_code` | 无需查询 | 固定 `800 元`,即 `80000 分` |
|
||||
| `question_fee`、`reward_user`、`reward_topic`、`reward_comment` | 无价格查询接口 | 使用用户明确指定并确认的整数 `amount` |
|
||||
| `question_fee`、`reward_user`、`reward_topic`、`reward_comment` | 无价格查询接口 | 使用用户明确指定的元金额,按 `元 × 100` 换算并确认整数 `amount`(分) |
|
||||
|
||||
调用示例均为底层接口工具参数:
|
||||
|
||||
@@ -55,6 +55,8 @@
|
||||
|
||||
以上字段路径包含 `call_zsxq_api` 的外层 `body`;若当前宿主直接返回业务响应体,则从 `resp_data` 开始读取。
|
||||
|
||||
轻读价格接口同时需要 `group_id` 和 `back_issue_id`。若用户只提供轻读链接或 `back_issue_id`,且无法从已知上下文或链接中可靠取得所属 `group_id`,停止并请用户补充所属星球;不得猜测 `group_id`,也不得跳过查价直接下单。
|
||||
|
||||
### 续费价格计算
|
||||
|
||||
`GET /v2/groups/{group_id}` 的星球数据位于 `body.resp_data.group`(宿主直接返回业务响应体时为 `resp_data.group`)。在 `group` 内读取:
|
||||
@@ -83,7 +85,8 @@
|
||||
|
||||
以下情况停止,不得创建订单:
|
||||
|
||||
- 星球不是 `type: "pay"`,或响应缺少 `policies.payment.amount`。
|
||||
- 付费加入或礼品卡的 `body.resp_data.public_info.type` 不是 `pay`,续费的 `body.resp_data.group.type` 不是 `pay`,或对应星球对象缺少 `policies.payment.amount`。
|
||||
- 续费接口返回当前用户不是星球成员,或响应缺少 `body.resp_data.group`。
|
||||
- 续费时缺少 `user_specific.validity.end_time`,导致无法选择折扣档位。
|
||||
- 接口返回的金额不是非负整数,或折扣比例不在 `[50, 100]`。
|
||||
- 轻读响应缺少 `body.resp_data.back_issue.amount`(或业务响应体中的 `resp_data.back_issue.amount`),或返回的 `group_id` / `back_issue_id` 与用户选择不一致。
|
||||
@@ -115,7 +118,7 @@
|
||||
| `path` | **是** | 固定为 `/v2/wechat_orders` |
|
||||
| `body.req_data` | 首次调用 **是** | 订单请求体;字段见下表 |
|
||||
| `payment_retry_token` | 仅预下单失败重试 | `SKILLHUB_PREORDER_FAILED` 返回的短期签名凭据;重试时无需再传 `body` |
|
||||
| `out_trade_no` | 否 | 与 `payment_retry_token` 一起校验订单;单独传入会被拒绝。订单号可为字符串或整数,推荐原样按字符串保存以避免精度丢失 |
|
||||
| `out_trade_no` | 否 | 与 `payment_retry_token` 一起校验订单;单独传入会被拒绝。**只能作为字符串原样保存和传递**,不得转换为数值;恢复时可省略,由签名凭据确定订单 |
|
||||
|
||||
`body.req_data` 字段:
|
||||
|
||||
@@ -127,7 +130,7 @@
|
||||
| `comment_id` | 按类型 | `reward_comment` |
|
||||
| `user_id` | 按类型 | `question_fee`、`reward_user` 的被提问/被赞赏用户 |
|
||||
| `back_issue_id` | 按类型 | `back_issue` |
|
||||
| `amount` | 按类型 | 仅 `question_fee`、`reward_user`、`reward_topic`、`reward_comment` 必填;整数,单位为“分”,向用户展示时除以 100 换算为“元” |
|
||||
| `amount` | 按类型 | 仅 `question_fee`、`reward_user`、`reward_topic`、`reward_comment` 必填;整数,单位为“分”。用户以“元”指定时乘以 100 换算 |
|
||||
| `pay_type` | 否 | 支付方式,缺省使用微信支付 |
|
||||
| `coupon_code` | 否 | `membership_fee`、`renewal_fee` 使用的优惠券码 |
|
||||
| `message` | 否 | `membership_fee` 的验证信息,0–30 字符 |
|
||||
@@ -146,18 +149,19 @@
|
||||
| `group_invite_code` | 购买创建星球邀请码 | `type` | — |
|
||||
| `back_issue` | 购买轻读 | `type`、`back_issue_id` | — |
|
||||
|
||||
金额换算规则:
|
||||
### 金额换算规则
|
||||
|
||||
- 接口 `amount` 的单位是“分”,必须传整数。
|
||||
- 用户通常以“元”指定金额:`接口 amount(分) = 用户金额(元) × 100`。只能接受最多两位小数且乘积为整数分的元金额;无法精确换算时停止并请用户重新给出金额,不得四舍五入或截断。
|
||||
- 向用户展示时使用“元”:`展示金额(元) = amount ÷ 100`。
|
||||
- `1 元 = 1 星球币`,因此换算后的元数值也等于星球币数量。
|
||||
- 示例:`amount: 100` 表示 `1 元`,等值 `1 星球币`;`amount: 1234` 表示 `12.34 元`,等值 `12.34 星球币`。
|
||||
- 示例:用户指定 `10 元`时传 `amount: 1000`;用户指定 `12.34 元`时传 `amount: 1234`,等值 `12.34 星球币`。
|
||||
|
||||
`pay_type` 省略时使用微信支付。除表中字段外,不要自行补充参数;尤其不要给付费加入、礼品卡、续期、创建星球邀请码或轻读订单传 `amount`。
|
||||
|
||||
## 输出
|
||||
|
||||
知识星球订单和 SkillHub 预下单均成功时,底层接口工具调用成功,业务结果为 402:
|
||||
知识星球订单和 SkillHub 预下单均成功时,底层接口工具调用本身不是协议错误,但结构化业务结果是 402 支付挑战。此时 `success: false` 是协议约定;必须以 `code == "PAYMENT_REQUIRED"` 且 `status_code == 402` 识别待支付状态,不得按普通失败处理,也不得重试创建订单:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -170,7 +174,7 @@
|
||||
"payment_code": "MOCK_PAYMENT_CODE",
|
||||
"prompt": "请完成微信支付。",
|
||||
"out_trade_no": "90000000000000000001",
|
||||
"expires_at": 1750924800
|
||||
"expires_at": 4102444800
|
||||
},
|
||||
"out_trade_no": "90000000000000000001"
|
||||
}
|
||||
@@ -188,13 +192,44 @@
|
||||
}
|
||||
```
|
||||
|
||||
订单号可能同时出现在顶层 `out_trade_no`、`payment.out_trade_no` 和 `_meta.X-Out-Trade-No`。读取时,每个已出现的值都必须是非空字符串;多个位置同时存在时必须完全一致,否则停止并报告。订单号必须始终按原字符串保存和传递,不得转换为数值。
|
||||
|
||||
收到 `PAYMENT_REQUIRED` 不是失败,也不是支付成功;应让支持 Skill Pay 的宿主展示微信支付授权卡片,由用户确认。
|
||||
|
||||
`expires_at` 是 Unix 时间戳,单位为**秒**。与当前时间比较时使用当前 Unix 秒值(不能直接用毫秒级 `Date.now()`);当前时间大于或等于 `expires_at` 时支付码已过期,必须停止。示例中的 `4102444800` 是模拟值,不对应真实订单。
|
||||
|
||||
SkillHub 预下单失败时,知识星球订单已经创建,响应会包含安全恢复所需字段:
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"status_code": 502,
|
||||
"code": "SKILLHUB_PREORDER_FAILED",
|
||||
"error": "MOCK_SKILLHUB_ERROR",
|
||||
"message": "SkillHub 预下单失败,可使用 payment_retry_token 重试,不会重复创建知识星球订单。",
|
||||
"out_trade_no": "90000000000000000001",
|
||||
"order_type": "membership_fee",
|
||||
"payment_retry_token": "MOCK_PAYMENT_RETRY_TOKEN",
|
||||
"payment": {
|
||||
"provider": "WEIXINPAY",
|
||||
"pay_data": {
|
||||
"type": "prepay_id",
|
||||
"value": "MOCK_PREPAY_ID"
|
||||
},
|
||||
"out_trade_no": "90000000000000000001",
|
||||
"payment_retry_token": "MOCK_PAYMENT_RETRY_TOKEN",
|
||||
"expires_at": 4102444800
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
优先从顶层 `payment_retry_token` 读取恢复凭据;顶层缺失时可读取 `payment.payment_retry_token`。两处同时存在但值不一致,或两处均缺失/为空时停止并报告,不得重发订单 `body`。恢复凭据的 `expires_at` 同样是 Unix 秒级时间戳;过期后停止。
|
||||
|
||||
## 宿主微信支付授权
|
||||
|
||||
收到 `PAYMENT_REQUIRED` 后,直接按以下协议请求支付授权,无需访问外部接入文档:
|
||||
|
||||
1. 从 `_meta.WeixinPay.WeixinPay-Required` 读取支付码;若宿主没有暴露 `_meta`,则读取 `payment.payment_code`。两处同时存在但值不一致时停止并报告,不得猜测使用哪一个。
|
||||
1. 分别读取 `_meta.WeixinPay.WeixinPay-Required` 和 `payment.payment_code`。前者缺失或为空(包括 `_meta: {}`)时回退到后者;两处同时存在但值不一致时停止并报告;两处均缺失或为空时也停止,不得以空支付码调用支付工具。
|
||||
2. 原样保留支付码,不解码、不修改、不向用户展示。若宿主提供官方 `weixinpay_pay`,仅将该支付码作为 `paymentCode` 参数调用:
|
||||
|
||||
```text
|
||||
@@ -202,18 +237,18 @@ weixinpay_pay(paymentCode="<WeixinPay-Required 的原值>")
|
||||
```
|
||||
|
||||
3. 宿主展示微信支付卡片后,将支付决定交给用户本人。agent 不得代替用户点击确认、自动授权或把创建订单时的确认视为支付授权。
|
||||
4. 保存 `out_trade_no`,但不要把它传给 `weixinpay_pay`。支付能力调用完成只表示已发起或处理授权流程;支付是否成功及订单是否履约,以知识星球原支付回调或业务页面状态为准。
|
||||
4. 将 `out_trade_no` 原样保存为字符串,但不要把它传给 `weixinpay_pay`,也不得转换为数值。支付能力调用完成只表示已发起或处理授权流程;支付是否成功及订单是否履约,以知识星球原支付回调或业务页面状态为准。
|
||||
|
||||
以下情况必须停止,不得自动再次创建订单:
|
||||
|
||||
- 宿主没有官方 `weixinpay_pay`,或无法识别支付元数据:保留 `out_trade_no`,告知用户需在支持 Skill Pay 的宿主中完成支付。
|
||||
- 用户取消或拒绝授权,支付能力返回失败,或支付码已超过响应中的 `expires_at`:报告当前状态并停止。
|
||||
- 用户取消或拒绝授权,支付能力返回失败,或当前 Unix 秒值大于等于响应中的 `expires_at`:报告当前状态并停止。
|
||||
- 支付能力返回结果无法确定是否支付成功:不得声称成功,也不得仅凭用户口头陈述重放订单请求;引导用户在知识星球业务页面核对。
|
||||
|
||||
## 推荐工作流
|
||||
|
||||
1. 确认当前宿主是 WorkBuddy 且提供官方 `weixinpay_pay`。否则在创建订单前说明限制并停止。
|
||||
2. 查询并核对目标 ID。轻读查价需同时取得 `group_id` 和 `back_issue_id`。按[下单前查询价格](#下单前查询价格)取得或计算价格,按逐类型传参规则整理必要字段,向用户以“元”展示对象、基础价/折扣(如适用)、应付金额和等值星球币;付费提问和赞赏订单还要确认用户指定并将传入接口的整数 `amount`,然后取得明确确认。
|
||||
2. 查询并核对目标 ID。赞赏评论需同时取得 `topic_id` 和 `comment_id`;轻读查价需同时取得 `group_id` 和 `back_issue_id`。按[下单前查询价格](#下单前查询价格)取得或计算固定价格,按逐类型传参规则整理必要字段,向用户以“元”展示对象、基础价/折扣(如适用)、应付金额和等值星球币;四类用户定价订单按[金额换算规则](#金额换算规则)将用户指定的元金额精确换算为整数分,再同时确认元值和 `amount`。
|
||||
3. 使用 `call_zsxq_api` 创建订单。不要用 CLI `api raw` 绕过支付元数据;除付费提问和赞赏外,不要把查询或计算出的价格作为 `amount` 传入订单。
|
||||
4. 收到 `PAYMENT_REQUIRED` 后,按[宿主微信支付授权](#宿主微信支付授权)处理支付码和 `out_trade_no`,由用户本人在微信支付卡片中确认。
|
||||
5. 支付完成后的状态与履约由知识星球原支付链路处理。没有官方查单能力时,如实说明无法在本工具内核验,不要重复创建订单。
|
||||
@@ -228,7 +263,7 @@ weixinpay_pay(paymentCode="<WeixinPay-Required 的原值>")
|
||||
}
|
||||
```
|
||||
|
||||
恢复请求可省略 `body`。路径必须仍为 `/v2/wechat_orders`;不得重新发送原订单 body,否则可能创建重复订单。
|
||||
恢复请求必须省略 `body`。路径仍为 `/v2/wechat_orders`;不得重新发送原订单 body,否则可能创建重复订单。`out_trade_no` 可省略;若提供,只能原样使用响应中的字符串。
|
||||
|
||||
## 失败语义
|
||||
|
||||
|
||||
Reference in New Issue
Block a user