新增 affiliate_dash 履约 executor(阶段 2)

- executor 常量/守卫 + affiliate-dash-executor(preparePaidTask/resolveDeliveryLink)
- 履约业务实现:prepareAffiliateDashTask(幂等建单, client_order_no=task_no, data 透传 91单号/game_account)
  + syncAffiliateDashTaskStatus(状态合并: delivering→redeeming / delivered→核销→redeemed /
  ship_failed→retry_pending / cancelled→closed)
- registry 注册 + 测试(212 全绿)
- 真实建单联调通过(线上 skin.khhao.com,幂等不重复扣款)
- 修复 POST /orders 响应 data.order 映射层级
This commit is contained in:
yml2213
2026-08-05 14:56:36 +08:00
parent a6ba5f1c7f
commit 867ffd2f3c
7 changed files with 457 additions and 3 deletions
@@ -443,3 +443,28 @@ order_site 处理要求:
**真实联调验收**`listAffiliateDashProducts` 直连线上 `https://skin.khhao.com` → total=33 商品,字段映射正确,签名链路与 affiliate_dash `BuildOpenV1Sign` 一致。
**联调中发现并修复**:签名 `path` 必须为**纯路径**(不含 query string);首次实现把 `/products?page=1&size=5` 整串参与签名导致线上 401「签名校验失败」,已改为 `URL.pathname` 参与签名(§3.1 表头 `path=<仅路径>` 属实)。
---
## 16. 阶段 2 落地记录(v2.2 · 已完成)
产出文件(`apps/backend/src/services/fulfillment/`):
| 文件 | 内容 |
| --- | --- |
| `executors/types.ts` | `FULFILLMENT_EXECUTOR_KEYS.AFFILIATE_DASH='affiliate_dash'` + `isAffiliateDashExecutor` 守卫 |
| `executors/affiliate-dash-executor.ts`(新) | `{ key, preparePaidTask, resolveDeliveryLink }` 仿 feifei:补 claim token → `prepareAffiliateDashTask`;失败降级 `MANUAL_REVIEW` + `notifyTaskAutoManualReview``resolveDeliveryLink` 返回本站统一 claimUrl |
| `executors/registry.ts` | `EXECUTORS` Map 注册 affiliateDashExecutor |
| `affiliate-dash/index.ts`(新) | `isAffiliateDashTask``normalizeAffiliateDashFlow`context_json `affiliateDash` 块)、`prepareAffiliateDashTask`(幂等建单、`client_order_no=task_no``data` 透传 91单号/game_account、写 `LINK_GENERATED` + task event)、`syncAffiliateDashTaskStatus`(状态合并:delivering→redeeming、delivered→核销→redeemed/manual_review、ship_failed→retry_pending、cancelled→closed)、`buildAffiliateDashClientOrderNo` |
| 测试 | `registry.test.ts` 新增 affiliate_dash 映射 + 动作暴露断言(4→4 项) |
**真实建单联调(线上 skin.khhao.com**
| 步骤 | 结果 |
| --- | --- |
| 建单 `lucky_coin_x2`20 积分) | `FO20260805145602108a92eac8d``paid``can_ship=true` ✅ |
| 同 client_order_no 幂等重试 | 同单号 + `idempotent=true`,不重复扣款 ✅ |
| GET /orders/{order_no} 查询 | `paid`,金额/状态正确 ✅ |
| GET /orders/{order_no}/delivery | `data` 透传(91单号 + game_account)正确 ✅ |
**联调中发现并修复**`POST /orders` 响应是 `data.order`(非 `data` 直接),首次实现 map 错了层级导致 orderNo 全空;已改为取 `data.order` 并暴露 `idempotent` 标志。幂等校验要求**同单号参数完全一致**,否则 400「参数与原订单不一致」——重试时必须复用原参数。