docs(douyin-mashida): 新增皮肤领取流程设计文档 + 联调清单补充
- `09-皮肤领取流程.md`:为什么改(固定链接/输订单号的问题)、新流程图、 为什么链接必须是路径式(# 是打手页)、商品图怎么来(内部 SKU → 英文 sku → 图片, 复用权威映射表 + 漏图守卫测试)、配置项表、兼容性(旧链接保留)、下一步(真正发货) - `08-公网联调.md`:联调 checklist 补「皮肤领取页两项配置」(含 `#` 告警)、 把「手机打开链接」改为买家领取链接并补任务/token 与四表对账
This commit is contained in:
+12
-5
@@ -162,15 +162,22 @@ npm run douyin-mashida:preflight -- --public-url https://xxxx.ngrok-free.app --s
|
||||
2. 切公网地址 npm run douyin-mashida:set-public-url -- --public-url https://<域名>
|
||||
3. 填真实凭据 面板:uid = 抖店商户号,secret = 真实用户秘钥
|
||||
(baseUrl 保持 https://dy-openplatform-api.wanmahui.com)
|
||||
4. 前置自检 npm run douyin-mashida:preflight -- --public-url https://<域名> --secret <真密钥>
|
||||
4. 皮肤领取页两项配置 面板:
|
||||
claimLinkBase = https://<域名>/claim 皮肤订单领取页基址
|
||||
messageTemplate = 您的订单已发货,请点击领取:{link}
|
||||
⚠️ claimLinkBase 必须是**路径式**(不要带 #):
|
||||
#/claim 是打手领取页,配错会把买家带到打手流程
|
||||
5. 前置自检 npm run douyin-mashida:preflight -- --public-url https://<域名> --secret <真密钥>
|
||||
全 ✅ 才能开始
|
||||
5. 订阅推送 ★ npm run douyin-mashida:subscribe -- --public-url https://<域名>
|
||||
6. 订阅推送 ★ npm run douyin-mashida:subscribe -- --public-url https://<域名>
|
||||
(不做这步平台一条消息都不会推,见 §2)
|
||||
6. 平台侧下一笔小额真单 → 日志看:
|
||||
7. 平台侧下一笔小额真单 → 日志看:
|
||||
POST /api/v1/open/douyin-mashida/message 收到推送
|
||||
[douyin-mashida/certificate] 券码已同步 syncV2 成功
|
||||
7. 手机打开 cert_link 走一遍兑换(首次要过 ngrok 警示页)→ 本地看到 verifyV3 + order.message
|
||||
8. 对账 orders / order_items / redeem_certificates 三张表
|
||||
fulfillment_tasks / claim_tokens 已建任务与领取 token
|
||||
8. 手机打开买家领取链接 https://<域名>/claim/<token>(首次要过 ngrok 警示页)
|
||||
→ 看到物品图片 → 填游戏账号 → 领取 → 本地看到 verifyV3
|
||||
9. 对账 orders / order_items / redeem_certificates / fulfillment_tasks 四张表
|
||||
```
|
||||
|
||||
### 必须实测的 7 个点
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
# 09 - 皮肤自动发货:买家领取流程
|
||||
|
||||
> 本文档描述抖音码速达**皮肤类商品**的交付改造:从「固定兑换链接 + 用户输订单号」
|
||||
> 改为「每单一条领取链接 + 买家填游戏账号领取」。
|
||||
> 代码位置:`apps/backend/src/services/{fulfillment,claim}/`、`apps/backend/src/services/platforms/douyin-mashida/`、
|
||||
> `apps/frontend/src/pages/claim-skin/`。
|
||||
|
||||
## 1. 为什么要改
|
||||
|
||||
旧流程(`https://<域名>/redeem`,见文档 07)有三个毛病:
|
||||
|
||||
| 问题 | 说明 |
|
||||
| --- | --- |
|
||||
| 不认人 | 链接是**同一个**,谁拿到都能打开;靠买家手输订单号来"认领" |
|
||||
| 多一步 | 买家要先去抖店订单里复制 19 位订单号,再回到页面粘贴 |
|
||||
| 不合规风险 | 任何人输入别人的订单号都能看到脱敏摘要(虽无手机号,但没必要暴露) |
|
||||
|
||||
新流程:**一个订单一条链接**,链接自带 token,打开就知道是谁的单,直接领。
|
||||
|
||||
## 2. 新流程
|
||||
|
||||
```text
|
||||
买家付款
|
||||
└─ 平台推送 trade_TradePaid → 建单 + order_items
|
||||
└─ 按【内部 SKU】分流
|
||||
├─ 命中 AFFILIATE_DASH_SKU_MAPPING(皮肤/礼包类)→ 自动发货
|
||||
│ ├─ 建履约任务(皮肤执行器,requires_claim)
|
||||
│ ├─ 生成 claim token → 领取链接 = claimLinkBase + '/' + token
|
||||
│ ├─ coupons.syncV2:cert_link = 该订单的领取链接(买家在抖店卡券里点开直达)
|
||||
│ └─ order.message:按 messageTemplate 把链接推给买家
|
||||
└─ 未命中 → manual_dispatch(接单平台/人工)
|
||||
```
|
||||
|
||||
买家侧:
|
||||
|
||||
```text
|
||||
打开 https://<域名>/claim/<token> ← 路径式,没有 #(与打手领取页 #/claim 分开)
|
||||
├─ 展示:物品图片 + 内部 SKU + 数量 + 订单号 + 商品标题
|
||||
├─ token 失效 → 友好提示,不展示表单
|
||||
├─ 待领取 → 填「游戏账号 / 角色ID」→ 二次确认 → 领取
|
||||
└─ 领取成功 → 保存账号到任务 + 调 coupons.verifyV3 核销平台券 → 成功态
|
||||
```
|
||||
|
||||
## 3. 为什么链接必须是**路径式**
|
||||
|
||||
仓库里已经有一个 `#/claim/{token}` 页面,那是**打手**用的(要走游戏 UID 绑定、领取身份校验那一套)。
|
||||
皮肤买家链接如果用 hash 形式,买家会被带进打手流程。
|
||||
|
||||
因此:
|
||||
|
||||
- 买家页走**独立 BrowserRouter 分支**(照 `/redeem` 的做法,见 `apps/frontend/src/App.tsx`)
|
||||
- 后端拼链接**只**用抖音配置的 `claimLinkBase`,**不要**经过 `buildClaimUrl()`
|
||||
(后者读全局 `orders.claimBaseUrl`,默认值是 hash 形式 `…/#/claim`)
|
||||
- 后台面板对 `claimLinkBase` 里出现 `#` 的情况会直接报错提示
|
||||
|
||||
## 4. 商品图怎么来
|
||||
|
||||
图片按 affiliate_dash 的**英文 sku** 命名,放在前端 `apps/frontend/public/images/products/`(Vite publicDir,原样对外):
|
||||
|
||||
```text
|
||||
内部 SKU(平台 sku_order_list[].code) 英文 sku(= 图片文件名)
|
||||
幸运币2个 → lucky_coin_x2.webp
|
||||
套装-浪漫天命 → suit_romantic_destiny.webp
|
||||
```
|
||||
|
||||
映射复用**已有**的权威表 `services/platforms/affiliate-dash/sku-mapping.ts`(`AFFILIATE_DASH_SKU_MAPPING`),
|
||||
由 `product-image.ts` 的 `resolveProductImageUrl()` 输出 `/images/products/<英文sku>.webp`。
|
||||
映射不到返回空串,前端显示占位图(不猜、不拼不存在的文件)。
|
||||
|
||||
单测里有一条**守卫**:映射表每个 sku 都必须有对应图片文件,新增商品漏图会直接测试失败。
|
||||
|
||||
## 5. 配置项(后台「抖音码速达接入配置」面板)
|
||||
|
||||
| 字段 | 作用 | 留空/关闭时 |
|
||||
| --- | --- | --- |
|
||||
| `claimLinkBase` | 皮肤订单领取页基址,如 `https://<域名>/claim` | 回退到通用 `certLink` |
|
||||
| `messageTemplate` | 付款后发给买家的领取消息,支持 `{link}` `{sku}` `{orderNo}` `{productTitle}` | 用默认文案 |
|
||||
| `claimMessageEnabled` | 是否在付款后发领取消息 | 关闭则只把链接写进卡券 |
|
||||
| `certLink` | **通用兜底**兑换链接(非皮肤订单、或解析不出领取链接时用) | — |
|
||||
|
||||
## 6. 兼容性
|
||||
|
||||
- 旧订单的卡券里已经写死了旧链接,**永远指向 `/redeem`**(收不回来)→ 旧页面**保留可用**,不删。
|
||||
- 新订单才会走领取链接;`certLink` 继续作为兜底,非皮肤订单行为完全不变。
|
||||
- 买家游戏账号存在 `fulfillment_tasks.claim_submission_json`:
|
||||
**不写** `work_orders.material_json`(那是发给打手的工单素材,写进去等于泄露买家隐私)。
|
||||
|
||||
## 7. 下一步(尚未实现)
|
||||
|
||||
领取成功后任务停在「已领取」,真正把物品发到买家账号仍需要履约:
|
||||
|
||||
- 皮肤类是否全自动发放(对接发货平台/卡密),还是先出一张人工工单;
|
||||
- 失败/退款场景要能 `coupons.cancelVerify` 冲正并把链接置回可用;
|
||||
- 接单平台类订单的领取链接沿用同一套 token + 页面,还是另有形态。
|
||||
Reference in New Issue
Block a user