docs(douyin-mashida): 记录「平台会改写券码」这个坑与核销实测结论

- 07 §4.11:新增「平台会改写我们提交的券码」——实测 3 笔里 2 笔被平台改名,
  连带 10017 核销码不匹配(且要 ~10.5s 才返回,会伪装成网关超时);
  写明处理方式(回查落库 + 核销用平台券码 + 失败自愈 + 超时 20s)
- 00 总览:实测结论表补上「核销成功」「平台改写券码」「order.message 已调用」
This commit is contained in:
yml2213
2026-10-09 14:09:05 +08:00
parent de2fb3e008
commit f72eeb7648
2 changed files with 33 additions and 3 deletions
+4
View File
@@ -81,6 +81,7 @@
| `routes/admin/platform-config/douyin-mashida.ts` | 49 | 后台 GET/POST + 审计 |
| `services/admin/platform-config/douyin-mashida-service.ts` | 75 | 配置读写,secret 出参置空 + 掩码,掩码回写不覆盖 |
| `db/migrations/094_redeem_certificates.sql` | 57 | `redeem_certificates` 表 |
| `db/migrations/095_redeem_certificates_platform_cert.sql` | 30 | 记录**平台侧实际券码**(平台会改名,核销必须用它) |
| `scripts/douyin-mashida-gateway-stub.ts` | 320 | **本地网关桩**:假装码速达,校验签名并回 `code=10000` |
| `scripts/douyin-mashida-push.ts` | 300 | **推送模拟器**:造签名消息打本地后端 |
| `scripts/douyin-mashida-set-public-url.ts` | 290 | **公网联调切换**:改 `certLink` 为隧道地址 + 打印平台侧配置 + 自检隧道 |
@@ -253,6 +254,9 @@ git add apps/backend/src/app.ts \
| 兑换页状态 | ✅ `redeemable`,展示真实商品名与真实支付时间 |
| **平台自动推送**(订阅后真单付款) | ✅ 6 秒到达,来源 IP `118.31.56.230`,端到端约 7 秒完成建单+发券+同步 |
| `pay_time` 字符串形态 | ⚠️ 实测发现并已修复(见 07 §4.8) |
| **核销(verifyV3)** | ✅ 真单核销成功,平台侧 `status=3 已使用 / verify_num=1` |
| **平台会改写券码** | ⚠️ 3 笔里 2 笔被平台改名 → 已修(核销改用平台侧券码 + 失败自愈,迁移 095) |
| `order.message` 发消息 | ✅ 兑换成功后已调用,无错误日志(成功日志默认被 integration 阈值 warn 挡住) |
| `messagetest` 自测入口 | ⚠️ 始终 `20006 data参数内容解析异常`,未探明其 data 要求;不影响真实链路 |
## 十、自检结果(本次)
@@ -167,7 +167,33 @@ applyRawBigIntegerOverrides(parsed, rawText) // p_id / order_id / s_id / s_ids
`resolveOrderItemSkuNick`)和 `redeem-service.ts:buildSummary`,
**只对 `source === 'douyin_mashida'` 生效**,其它平台展示逻辑不变。
### 4.11 平台真实推送的形态(实测抓到的原文)
### 4.11 ★ 平台会**改写我们提交的券码**(最坑的一条)
`coupons.syncV2` 返回 `10000 成功`,**不代表平台沿用了你提交的 `cert_no`**。
实测 3 笔订单里有 **2 笔**,平台把我们的 `DYC…` 券码换成了它自己生成的券码:
| 订单 | 我们提交的 cert_no | 平台侧实际 cert_no |
| --- | --- | --- |
| `6930318258716179555` | `DYCM7HXC1TEJGB3VC4A` | 沿用我们的 |
| `6930292726686514275` | `DYCAEPGNV5W4KDW2GJW` | `ExsweiKSgejRcM3Z06`(平台生成) |
| `6930310175251856483` | `DYC05EJH7G66VG0EVFN` | `S683sWRJXaY74DZkrT`(平台生成) |
**连带后果**:拿自己的券码去 `coupons.verifyV3`,平台报
`10017 卡券核销失败[isv.business-failed:010021|核销码与订单不匹配]` ——
而且这个错误**要 ~10.5 秒才返回**,越过 10 秒超时后前端只看到
`douyin_mashida_gateway_timeout`,真实原因完全被掩盖。
**处理**(迁移 095 + `certificate-service`):
1. 同步成功后立即用 `coupons.list`(按 `order_id`)回查平台侧真实券码,
存进 `platform_cert_no` / `platform_cert_id` / `platform_status`;
2. 核销时 `resolveRedeemVerifyCertNo()`:**平台侧券码优先**,取不到才退回我方券码;
3. 核销失败自愈:回查平台 → 若平台侧已核销则按对账结果标记本地已核销(修状态漂移);
若是券码被改名则用平台券码**重试一次**;
4. 回查不到券 → 标记 sync 失败并告警(暴露"syncV2 成功但平台无券");
5. 出网超时默认 10s → **20s**。
### 4.12 平台真实推送的形态(实测抓到的原文)
订阅配好后,一笔真实付款的推送**约 6 秒**到达,来源 IP 是平台服务器(`118.31.56.230`),
body 原文(注意 `p_id`/`s_ids` 是**裸数字**、`pay_time` 是**秒级**):
@@ -181,13 +207,13 @@ body 原文(注意 `p_id`/`s_ids` 是**裸数字**、`pay_time` 是**秒级**
- `p_id` 是 19 位裸数字 → 正好验证了 §4.1 的精度修复(落库/回执全程精确);
- 端到端耗时:付款 12:55:05 → 推送 12:55:11 → 建单+发券+`syncV2` 完成 12:55:12。
### 4.12 平台推送是**订阅制**(不配就永远收不到)
### 4.13 平台推送是**订阅制**(不配就永远收不到)
填好 `uid`/`secret` 只代表我们能调平台,平台**不会**自动推消息过来:
必须调「消息设置」`message.config` 配置 `message_url` + `topics` + `status=1`。
而且**不补推**订阅之前的历史订单。详见 [08-公网联调.md](08-公网联调.md) §2。
### 4.13 退款/取消消息文档没列字段
### 4.14 退款/取消消息文档没列字段
`refund_*`、`trade_TradeCanceled`、`trade_TradeSuccess` 这几条文档里 `props` 是空的(很可能只是文档缺失)。
代码按「有 `p_id` 就作废券、没有就留痕等人工」处理 —— **不抛错**,避免平台无意义重推。