feat(fulfillment): 接入Rock发货平台(0666.pro)代理履约、通用库存池与UID强一致风控
1. 数据库新增 012_rock_fulfillment 迁移,创建 rock_configs 配置表与 rock_tokens 通用库存表,补齐黑色ROCK长袖T恤与蓝色运动服上衣商品目录; 2. 封装 RockClient 与 RockService,实现 0666.pro 平台 Bearer Token 极简连通校验、批量采购50个入库、水位监控巡检与自动补货; 3. 新增 RockProvider 实现标准履约路由,引入 Anti-Ghost 旧绑定基线比对与 UID 强一致门禁,扫错号硬阻断并记录为 mismatch 状态; 4. 针对黑色ROCK与蓝色运动服实现动态发货(绑定后发货前动态选择 skin),并提取腾讯官方发货流水号 fulfillId 对账; 5. 新增全局自动发货总开关(Kill Switch),支持一键软熔断降级转人工接单处理; 6. 前端新增 PlatformRock 管理大屏,提供总开关切换、Token配置与连通测试、库存监控、一键补货及错单解冻重置。
This commit is contained in:
@@ -0,0 +1,333 @@
|
||||
# Rock发货平台 (0666.pro) 代理接入与库存风控实施方案
|
||||
|
||||
> **编制日期**:2026-10-05
|
||||
> **指导原则**:
|
||||
> 1. **后台全反代,买家/打手对上游完全无感**(底层对接全部在后端完成,对外输出完全符合既有系统规范)。
|
||||
> 2. **Token 一次性绑定不可换绑,设立 UID 强一致防御门禁**(前置填 UID,阻断混淆旧数据,UID 不符绝对禁止领取)。
|
||||
> 3. **本地库存池机制,支持批量采购、安全水位预警与自动补货**。
|
||||
> 4. **先规划设计,严格门禁验证,暂不急于修改既有 Provider**。
|
||||
|
||||
---
|
||||
|
||||
## 一、 核心需求解构与风险防御矩阵
|
||||
|
||||
| 序号 | 需求要点 | 业务痛点 / 致命风险 | 应对防御方案 | 确信度 |
|
||||
| :--- | :--- | :--- | :--- | :--- |
|
||||
| **REQ-1** | **后台做代理,用户无感上游** | 若直接下发 0666 链接,买家会发现源头平台;且数据结构不一致破坏现有前端逻辑。 | • 后端封装中转代理,对外暴露统一的订单提货 API;<br>• 二维码仅输出腾讯官方活动链接(`gp.qq.com`),买家端完全无第三方痕迹;<br>• 数据字段对齐既有 `DeliveryOrderInfo` 与 `DeliveryBindResult`。 | **100%** |
|
||||
| **REQ-2** | **Token 无法换绑,绑定即作废** | 买家若扫错游戏账号,或乱扫码,该 Token 直接报废(21 积分/个损失),且无法解绑。 | • **前置输入门禁**:生成二维码前,强制买家输入/确认游戏角色 UID;<br>• **UID 强一致校验**:扫码后捕获角色 UID,**不等于预期 UID 严禁发货**;<br>• 阻断错误发货,保留 Token 供售后人工处理。 | **100%** |
|
||||
| **REQ-3** | **上游旧绑定信息防混淆** | 0666 平台下发 Token 或刚 refresh 时可能残留历史账号信息(`previous_bound_account` / 历史记录),容易被误判为“已绑定”。 | • **基线快照比对(Baseline Snapshotting)**:分配 Token 时抓取初始绑定快照;<br>• 仅当检测到买家扫码产生新的绑定事件且角色 UID 完全吻合时,才跃迁为 `bound` 状态。 | **100%** |
|
||||
| **REQ-4** | **后台批量采购与统一通用库存池** | 提取 Token 默认统一下单为“黑色通用 Token”(对应界面 `1 = 黑色`),该链接本身不预先区分黑蓝,是一个通用兑换凭证。 | • 建立本地统一的 `rock_tokens` 通用库存池,无需双池割裂;<br>• 后台一键采购 50 个通用 Token 存入库存;<br>• 发货时直接从通用池中锁定分配,零网络延迟。 | **100%** |
|
||||
| **REQ-5** | **安全水位告警与自动采购** | 库存用尽导致订单积压失败。 | • 设置通用 Token 低库存预警阈值(如低于 10 个);<br>• 接入系统既有通知渠道(飞书、钉钉、企微机器人等);<br>• 支持配置开关:低于阈值自动调用上游采购补充 50 个。 | **100%** |
|
||||
| **REQ-6** | **黑蓝区分时机:绑定后发货前动态选择** | 买家购买不同商品(黑色ROCK或蓝色运动服),上游链接本身无区别,何时决定发放黑色还是蓝色? | • **延后到发货阶段决策(Late-Binding Selection)**:<br>• 买家扫码通过 UID 强一致门禁后,系统根据订单商品的 SKU 属性,在最终调用兑换接口时自动填充对应 `skin`:<br> - 黑色商品传 `"skin": "黑色ROCK长袖T恤"`<br> - 蓝色商品传 `"skin": "蓝色运动服上衣"` | **100%** |
|
||||
| **REQ-7** | **绑定错误独立统计与追溯** | 买家扫错账号或扫了他人账号,虽然被系统阻断未发货,但该 Token 已无法在 0666 换绑,需明确统计损耗与售后责任。 | • **独立状态与指标面板**:Token 标记为 `mismatch`(绑定错误),后台大屏卡片高亮统计“绑错数量”;<br>• **全要素审计快照**:完整记录买家填写的 `expected_uid` 与扫码实际捕获的 `actual_role_id`、角色名、大区、发生时间,支持一键导出与人工处理。 | **100%** |
|
||||
| **REQ-8** | **Rock 自动发货全局总开关** | 遇到上游接口波动、积分不足、Token 缺货或价格调整时,需一键熔断。 | • **配置全局熔断开关 `rock_auto_delivery_enabled`**;<br>• 一旦关闭:黑色ROCK与蓝色运动服两个商品**彻底停走自动发货通道**,直接降级为人工打手抢单或客服处理,避免错单穿透。 | **100%** |
|
||||
|
||||
---
|
||||
|
||||
## 二、 系统架构与发货时序图
|
||||
|
||||
### 2.1 整体流程时序图(全反代 + UID 强校验)
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
actor Buyer as 买家 / 发货员
|
||||
participant Dash as Affiliate-Dash 后台
|
||||
participant Pool as 本地 Token 库存池
|
||||
participant Rock as 0666.pro 平台
|
||||
participant Tencent as 和平精英官方 (gp.qq.com)
|
||||
|
||||
Note over Buyer, Dash: 第零阶段:全局自动发货总开关检查 (Kill Switch)
|
||||
Buyer->>Dash: 打开提货页 /delivery/:orderNo
|
||||
alt rock_auto_delivery_enabled == false (总开关已关闭)
|
||||
Dash-->>Buyer: ⚠️ 该商品自动发货维护中,已转交人工客服/打手为您处理
|
||||
else rock_auto_delivery_enabled == true (允许自动发货)
|
||||
Note over Buyer, Dash: 第一阶段:前置输入 UID 锁定
|
||||
Dash-->>Buyer: 展示商品信息,要求确认/输入游戏角色 UID
|
||||
Buyer->>Dash: 提交预期游戏 UID (例如: 4331027062)
|
||||
|
||||
Note over Dash, Pool: 第二阶段:本地通用池分配 Token
|
||||
Dash->>Pool: 锁定 1 个可用的通用 Token (默认黑色通用凭证)
|
||||
Pool-->>Dash: 返回 Token 记录 (包含 redeem_code, bindUrl)
|
||||
Dash->>Dash: 记录 Token 初始状态快照 (排除上游历史旧信息)
|
||||
Dash-->>Buyer: 展示腾讯官方绑定二维码 (绝无 0666 标识)
|
||||
|
||||
Note over Buyer, Tencent: 第三阶段:买家微信/QQ 扫码授权
|
||||
Buyer->>Tencent: 手机扫码授权登录并绑定角色
|
||||
|
||||
Note over Dash, Rock: 第四阶段:轮询与 UID 强一致门禁
|
||||
loop 每 2~3 秒轮询
|
||||
Dash->>Rock: POST /api/user/tokens/{id}/refresh
|
||||
Rock-->>Dash: 返回 binding 信息 (role, roleId, region)
|
||||
end
|
||||
|
||||
alt 实际 roleId != 预期 UID (扫错账号)
|
||||
Dash->>Dash: 触发硬阻断!标记 deliveryStageBindMismatch
|
||||
Dash->>Pool: 将该 Token 状态标记为 mismatch (绑定错误),记录扫码角色与时间进入统计池
|
||||
Dash-->>Buyer: ⚠️ 绑定角色与订单 UID 不符,已阻断发货,请联系客服处理
|
||||
else 实际 roleId == 预期 UID (校验通过)
|
||||
Dash->>Dash: 状态变更为 bound,核验通过
|
||||
Dash-->>Buyer: 角色匹配成功 (唉终章 / 4331027062)
|
||||
|
||||
Note over Dash, Rock: 第五阶段:根据订单商品动态选择皮肤并兑换发货
|
||||
alt 订单购买的是黑色 ROCK
|
||||
Dash->>Rock: POST /api/redeem/{id} {"skin": "黑色ROCK长袖T恤", "currency": "幸运币", "account": "..."}
|
||||
else 订单购买的是蓝色运动服
|
||||
Dash->>Rock: POST /api/redeem/{id} {"skin": "蓝色运动服上衣", "currency": "幸运币", "account": "..."}
|
||||
end
|
||||
Rock-->>Dash: {"status": "success", "message": "领取成功"}
|
||||
Dash->>Pool: 标记 Token 状态为 redeemed,记录实际发放的 skin
|
||||
Dash-->>Buyer: 发货成功!生成发货凭证图
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、 本地库存模型与数据表设计
|
||||
|
||||
为了实现后台批量采购、库存水位控制与防错追踪,设计本地专属库存表:
|
||||
|
||||
### 3.1 Token 库存表 (`rock_tokens`)
|
||||
|
||||
所有 Token 在提取时统一默认采购为**“黑色通用 Token”**(上游类型传 `1 = 黑色`,即 `color = 'black'`),不预设皮肤,入库为通用库存。
|
||||
|
||||
```sql
|
||||
CREATE TABLE IF NOT EXISTS `rock_tokens` (
|
||||
`id` BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
`upstream_id` BIGINT UNSIGNED NOT NULL COMMENT '0666平台的Token ID,如 151153',
|
||||
`token_jwt` TEXT NOT NULL COMMENT 'Token完整JWT串',
|
||||
`redeem_code` VARCHAR(64) NOT NULL UNIQUE COMMENT '专属兑换码哈希',
|
||||
`color` VARCHAR(16) NOT NULL DEFAULT 'black' COMMENT '采购规格: 统一为 black 通用 Token',
|
||||
`status` VARCHAR(24) NOT NULL DEFAULT 'available' COMMENT '状态: available(可用)/locked(锁定)/bound(已绑)/redeemed(已发)/mismatch(绑错待查)/abnormal(异常)/expired(过期)',
|
||||
`assigned_order_no` VARCHAR(64) DEFAULT NULL COMMENT '当前绑定的内部订单号',
|
||||
`expected_uid` VARCHAR(64) DEFAULT NULL COMMENT '买家输入的预期游戏UID',
|
||||
`actual_role_name` VARCHAR(128) DEFAULT NULL COMMENT '扫码绑定的游戏角色名',
|
||||
`actual_role_id` VARCHAR(64) DEFAULT NULL COMMENT '扫码绑定的游戏角色UID',
|
||||
`actual_region` VARCHAR(64) DEFAULT NULL COMMENT '扫码绑定的大区',
|
||||
`bind_url` TEXT DEFAULT NULL COMMENT '腾讯官方绑定链接',
|
||||
`initial_snapshot` TEXT DEFAULT NULL COMMENT '分配时的初始旧绑定快照JSON(用于防混淆)',
|
||||
`cost_points` DECIMAL(10,2) DEFAULT '21.00' COMMENT '采购消耗积分',
|
||||
`redeemed_skin` VARCHAR(64) DEFAULT NULL COMMENT '实际兑换发放的皮肤名称(如: 黑色ROCK长袖T恤 / 蓝色运动服上衣)',
|
||||
`redeemed_currency` VARCHAR(64) DEFAULT NULL COMMENT '附赠的货币类型(默认: 幸运币)',
|
||||
`redeemed_amount` INT DEFAULT 0 COMMENT '附赠的货币数量(黑=10, 蓝=14)',
|
||||
`mismatch_at` DATETIME DEFAULT NULL COMMENT '判定为绑错UID的时间戳(用于统计大屏)',
|
||||
`mismatch_reason` VARCHAR(255) DEFAULT NULL COMMENT '绑错详情说明(如: 预期UID 4331027062 与扫码 3911959065 不符)',
|
||||
`expires_at` DATETIME DEFAULT NULL COMMENT 'Token官方过期时间',
|
||||
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
INDEX `idx_status_color` (`status`, `color`),
|
||||
INDEX `idx_assigned_order` (`assigned_order_no`),
|
||||
INDEX `idx_mismatch` (`status`, `mismatch_at`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='Rock平台Token本地通用库存池';
|
||||
```
|
||||
|
||||
### 3.2 Rock 平台配置表 / 系统配置扩展 (`rock_config`)
|
||||
|
||||
在系统配置项中持久化以下参数:
|
||||
- `rock_auto_delivery_enabled`: **Rock 自动发货全局总开关**(`true` 开启 / `false` 一键关闭,关闭后两款商品停走自动发货通道)
|
||||
- `rock_base_url`: `https://0666.pro`
|
||||
- `rock_bearer_token`: 上游当前有效的 Bearer Token(如抓包中的 `05c55d8b8c...`)
|
||||
- `rock_username`: 上游系统采购用户名(调 `GET /api/me` 自动获取,如 `王大锤`)
|
||||
- `rock_account_points`: 上游最新同步的积分余额(实时快照,如 `8271.2`)
|
||||
- `rock_min_points_warning`: 上游最低积分告警阈值(默认 `1050.0`,即至少满足一次 50 个 Token 自动补货)
|
||||
- `rock_token_warning_stock`: 通用 Token 告警安全水位(默认 10)
|
||||
- `rock_auto_purchase_enabled`: 自动补货开关(`true` / `false`)
|
||||
- `rock_auto_purchase_count`: 触发自动补货时单次采购量(默认 50,对应上游 `count=50` 黑色通用 Token)
|
||||
- `rock_purchase_cooldown_minutes`: 自动采购防抖冷却时间(默认 10 分钟,防并发击穿积分)
|
||||
|
||||
### 3.3 0666.pro 系统采购用户账号生命周期管理方案 (Upstream Account Lifecycle)
|
||||
|
||||
根据业务核验,0666.pro 平台登录方式为 **Bearer Token 登录** 与 **用户名+验证码登录**(无密码登录)。依照当前实施策略,**现阶段纯采用 Bearer Token 模式直接配置接入,后续再按需扩展验证码交互**:
|
||||
|
||||
#### 1. 凭据录入与自动校验 (Token-Only Direct Configuration)
|
||||
- **商户鉴权机制结论**:
|
||||
上游 0666.pro 平台**无独立固定密码**,仅支持“Bearer Token 登录”与“用户名+手机短信验证码登录”。根据实施规划,**先期直接采用 Token 配置方式,后续再视需要支持用户名+验证码交互**。
|
||||
- **后台极简配置**:
|
||||
在系统设置面板中,管理员直接粘贴从 0666.pro 网页或抓包中获取的当前有效 `Bearer Token`(64位十六进制串):
|
||||
> 💡 **Token 提取极简指引**:
|
||||
> 登录 0666.pro 网页后,按 `F12` 打开控制台,在 `Application (应用程序) -> Local Storage -> https://0666.pro` 中找到 `yd_token` 字段复制;或在控制台 Console 执行 `localStorage.getItem('yd_token')` 即可一键复制。
|
||||
- **即时连通性校验与自动同步**:
|
||||
点击【保存并测试连通】,后端立即发送 `GET https://0666.pro/api/me`:
|
||||
- 成功时:自动提取并展示上游用户名(`王大锤`)、账号状态(`active`)、当前可用积分(`8271.2`),折算展示“约可采购 393 个通用 Token”;
|
||||
- 失败时:界面提示错误详情(如凭证无效),阻止错误保存。
|
||||
|
||||
#### 2. 账号健康心跳与积分余额监控 (Heartbeat & Balance Tracker)
|
||||
- **定时心跳巡检**:后台定时任务(如每 10 分钟)调用 `GET /api/me`;
|
||||
- **大屏实时看板**:
|
||||
- 采购账号:`王大锤`(状态:`active 正常`)
|
||||
- 上游剩余积分:`8271.2` 点(看板自动折算可用 Token 配额)
|
||||
- 最后心跳时间:实时更新
|
||||
- **低积分提前预警**:
|
||||
当 `points < 1050.0`(不足一次 50 个采购)时,通过飞书/企微/钉钉机器人推送:
|
||||
> ⚠️ **【资金告警】0666.pro 平台采购账号积分不足!**
|
||||
> 账号:王大锤 | 剩余积分:840.0 点(不足一次 50 个自动补货)
|
||||
> 请及时前往 0666.pro 进行充值,避免断货。
|
||||
|
||||
#### 3. 凭据失效(401 Unauthorized)自动处置与熔断
|
||||
- 当采购接口返回 401(Token 到期失效或被注销)时:
|
||||
1. **系统自动软熔断**:自动将 `rock_auto_delivery_enabled` 置为报警待查状态,黑色 ROCK 与蓝色运动服两款商品立即降级为人工打手接单/客服处理,避免错单穿透;
|
||||
2. **高危警报推送**:立即向管理群推送高危紧急告警:“【紧急】0666 平台采购账号 Token 已失效,自动发货通道已自动熔断转人工,请管理员复制最新 Token 登录后台更新!”;
|
||||
3. **一键恢复**:管理员登录 0666.pro 获取新 Token 粘贴保存后,连通性测试通过即可一键恢复自动发货。
|
||||
- **后续扩展计划(Phase 2)**:未来若需支持脱离网页获取 Token,再在后台增加“输入手机号 -> 调 `/api/auth/send-code` -> 接收短信验证码 -> 调 `/api/auth/phone-login`”的在线登录换 Token 流程。
|
||||
|
||||
---
|
||||
|
||||
## 四、 核心防护算法与业务门禁细节
|
||||
|
||||
### 4.1 旧绑定信息清洗与基线比对(Anti-Ghost-Binding)
|
||||
|
||||
**真实抓包实锤证据 (`蓝色一个发货.har`)**:
|
||||
在买家尚未扫码前(Entry 1~6),上游 `refresh` 接口一直返回该手机号绑过的旧账号:
|
||||
- `bound_account: "总荒凉"`
|
||||
- `bound_account_id: "3751279035"`
|
||||
- `bind_changed_at: null`
|
||||
直到买家在手机微信真正完成扫码授权后(Entry 10),上游数据才发生跃迁:
|
||||
- `bound_account: "打破虚妄的浪漫"`
|
||||
- `bound_account_id: "3688825401"`
|
||||
- `previous_bound_account: "总荒凉"`(旧账号自动归入 previous)
|
||||
- `bind_changed_at: "2026-10-05 14:08:02"`
|
||||
- `bind_change_type: "rebind"`
|
||||
|
||||
若没有基线快照比对,系统在买家扫码前就会把旧账号“总荒凉”当作买家发货,导致灾难性货损!
|
||||
|
||||
**算法逻辑**:
|
||||
```go
|
||||
type BindingSnapshot struct {
|
||||
Bound bool `json:"bound"`
|
||||
RoleName string `json:"role_name"`
|
||||
RoleID string `json:"role_id"`
|
||||
BindChangedAt string `json:"bind_changed_at"`
|
||||
}
|
||||
|
||||
// 检查是否发生新的真实有效扫码
|
||||
func IsNewBindingValid(initialSnap BindingSnapshot, currentRefresh UpstreamRefreshResp, expectedUID string) (bool, string) {
|
||||
if !currentRefresh.Binding.Bound || currentRefresh.Binding.RoleID == "" {
|
||||
return false, "等待扫码绑定"
|
||||
}
|
||||
|
||||
// 若当前刷新的绑定状态与初始分配时的历史快照完全一致,说明买家尚未真正扫码,仍是历史残留
|
||||
if initialSnap.Bound && initialSnap.RoleID == currentRefresh.Binding.RoleID && initialSnap.BindChangedAt == currentRefresh.Token.BindChangedAt {
|
||||
return false, "等待买家扫码(忽略历史残留)"
|
||||
}
|
||||
|
||||
// 核心门禁:UID 必须 100% 强一致
|
||||
trimmedExpected := strings.TrimSpace(expectedUID)
|
||||
trimmedActual := strings.TrimSpace(currentRefresh.Binding.RoleID)
|
||||
if trimmedExpected != "" && trimmedActual != trimmedExpected {
|
||||
return false, fmt.Sprintf("绑定账号UID(%s)与订单预期UID(%s)不一致,严禁发货!", trimmedActual, trimmedExpected)
|
||||
}
|
||||
|
||||
return true, "ok"
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 绑定错误独立统计与追溯大屏 (Mismatch Audit & Metrics)
|
||||
|
||||
当买家扫错账号或拿他人微信扫码导致 UID 不一致时,系统触发以下处理:
|
||||
1. **Token 状态跃迁至 `mismatch`**:
|
||||
- 记录 `mismatch_at = NOW()`;
|
||||
- 记录 `mismatch_reason = fmt.Sprintf("预期UID(%s) 与 扫码UID(%s/%s) 不一致", expectedUID, actualRoleName, actualRoleID)`;
|
||||
- 阻断底层兑换调用,保留该 Token 在数据库中。
|
||||
2. **后台管理大屏独立统计卡片**:
|
||||
- 统计指标:`COUNT(status = 'mismatch')`,直观展示“绑定错误待排查 Token 数量”;
|
||||
- 列表展示维度:
|
||||
- 关联订单号 (`assigned_order_no`)
|
||||
- 买家填写的预期 UID (`expected_uid`)
|
||||
- 扫码实际角色与 UID (`actual_role_name` / `actual_role_id`)
|
||||
- 发生时间与大区
|
||||
- 支持客服人工处理:
|
||||
- **人工释放/重置**:若确认买家输入失误,允许客服人工纠偏重置为 `available` 或重新下发;
|
||||
- **上报作废**:调用上游 `POST /api/user/tokens/{id}/report` 标记为 `abnormal` 归档。
|
||||
|
||||
### 4.3 全局自动发货总开关与降级熔断机制 (Kill Switch)
|
||||
|
||||
针对黑色 ROCK 与蓝色运动服两款商品,设立全局软熔断总开关 `rock_auto_delivery_enabled`:
|
||||
1. **开关位置**:商户后台 / 平台设置中的一键 Switch 开关。
|
||||
2. **熔断效果**:
|
||||
- **当开启 (`true`) 时**:正常走全自动反代发货链路(分配 Token -> 出示二维码 -> 扫码强校验 -> 自动兑换发货)。
|
||||
- **当关闭 (`false`) 时**:
|
||||
- 黑色 ROCK 和蓝色运动服两款商品**彻底脱离自动发货流程**;
|
||||
- 订单状态保留在 `paid`,自动发货接口直接返回:
|
||||
```json
|
||||
{
|
||||
"can_ship": false,
|
||||
"cannot_ship_reason": "当前该商品自动发货通道维护中,已转交人工客服/打手为您处理"
|
||||
}
|
||||
```
|
||||
- 绝不调用 0666.pro 消耗 Token 或积分,由人工打手在接单平台抢单核验发货,或由客服人工处理;
|
||||
- 用于应对上游故障、Token 缺货、价格调整或恶意攻击时的秒级止血。
|
||||
|
||||
---
|
||||
|
||||
## 五、 库存管理、安全水位预警与自动采购逻辑
|
||||
|
||||
### 5.1 批量采购与入库流程
|
||||
1. 管理员在后台点击【采购 50 个黑色 Token】;
|
||||
2. 服务端带上 `rock_bearer_token`,向 `https://0666.pro/api/user/tokens/claim` 发送:
|
||||
```json
|
||||
{"color": "black", "count": "50"}
|
||||
```
|
||||
3. 上游返回 50 个 Token 数组,事务批量写入 `rock_tokens` 表,`status = 'available'`;
|
||||
4. 记录本次采购消耗的积分与操作日志。
|
||||
|
||||
### 5.2 水位巡检与告警通知
|
||||
1. **触发时机**:
|
||||
- 订单每次消耗锁定 Token 时;
|
||||
- 后台定时巡检 Cron(如每 5 分钟)。
|
||||
2. **判断逻辑**:
|
||||
$$\text{可用库存} = \operatorname{COUNT}\left(\text{status} = 'available' \land \text{color} = \text{target\_color}\right)$$
|
||||
- 若 $\text{可用库存} \le \text{告警阈值}$:
|
||||
- 发送机器人告警通知(复用系统现有的飞书/钉钉/企业微信 webhook):
|
||||
> **【库存告警】Rock平台黑色Token库存告急!**
|
||||
> 当前可用库存:**4 个**(预警阈值:10 个)
|
||||
> 请及时确认上游积分或检查自动补货状态。
|
||||
- 若开启了 `rock_auto_purchase_enabled`:
|
||||
- 检查是否在冷却期内(距上次自动采购时间 $\ge 10$ 分钟);
|
||||
- 触发自动采购任务,调用 claim 补充 50 个;
|
||||
- 采购成功后发送补货成功通知。
|
||||
|
||||
---
|
||||
|
||||
## 六、 实施规划路线图(分步推进)
|
||||
|
||||
```
|
||||
[Phase 1: 数据模型与库存池] -> [Phase 2: 采购与水位监控] -> [Phase 3: 反向代理与UID门禁] -> [Phase 4: Provider集成]
|
||||
- 创建 rock_tokens 数据表 - 实现手动采购API - 提货页输入UID前置流程 - 实现 RockProvider 接口
|
||||
- 系统配置项拓展 - 接入飞书/企微低库存预警 - 上游旧数据过滤与比对 - 接入系统统一发货工作台
|
||||
- 自动补货定时任务与冷却控制 - 强一致校验与硬阻断
|
||||
```
|
||||
|
||||
- **第一阶段(数据底座)**:创建 `rock_tokens` 数据结构与配置项存储,打通 0666.pro 的 Claim 接口。(已完成)
|
||||
- **第二阶段(库存与安全)**:在后台管理界面增加 Rock 库存面板,支持采购 50 个、库存查看、低水位告警与自动补货。(已完成)
|
||||
- **第三阶段(反代与安全门禁)**:实现代理转发与 UID 校验拦截器,杜绝因扫错号报废 Token。(已完成)
|
||||
- **第四阶段(业务无缝收口)**:完成标准 Provider 适配,系统无缝接管。(已完成)
|
||||
|
||||
---
|
||||
|
||||
## 七、 工程落地进度与实测验证记录 (Implementation Audit)
|
||||
|
||||
### 7.1 落地成果交付清单
|
||||
|
||||
| 模块层级 | 文件路径 | 核心功能与职责 | 状态 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| **SQL 迁移** | `backend/internal/database/migrations/012_rock_fulfillment.sql` | 创建 `rock_configs` 配置表、`rock_tokens` 通用库存表,初始化黑色ROCK与蓝色运动服目录数据 | ✅ 已就绪 |
|
||||
| **数据模型** | `backend/internal/model/rock.go` | 定义 `RockConfig` 与 `RockToken` 结构体及常量映射 | ✅ 已就绪 |
|
||||
| **通信客户端**| `backend/internal/service/rock_client.go` | 封装 0666.pro 平台全部 REST 接口 (GetMe, Claim, Refresh, Redeem, etc.) | ✅ 已就绪 |
|
||||
| **库存与风控**| `backend/internal/service/rock_service.go` | 实现库存行锁分配、Anti-Ghost 基线比对、UID强一致阻断、自动补货巡检与 mismatch 解冻 | ✅ 已就绪 |
|
||||
| **履约渠道** | `backend/internal/service/provider_rock.go` | 实现统一 `FulfillmentProvider` 接口,支持动态判定皮肤与腾讯官方流水提取 | ✅ 已就绪 |
|
||||
| **后台 API** | `backend/internal/handler/rock.go` | 提供配置查询/更新、测试连通、一键采购 50 个、库存分页与重置接口 | ✅ 已就绪 |
|
||||
| **前端 API** | `frontend/src/api/index.ts` | 增加 `rockApi` 与相关 TypeScript 类型声明 | ✅ 已就绪 |
|
||||
| **管理大屏** | `frontend/src/pages/PlatformRock.tsx` | 实现自动发货总开关、指标看板、Token 配置与连通测试、库存与错单审计列表 | ✅ 已就绪 |
|
||||
| **菜单与路由**| `frontend/src/App.tsx`, `MainLayout.tsx` | 注册 `/platform-rock` 路由与侧边栏商品管理子菜单 | ✅ 已就绪 |
|
||||
| **单元测试** | `backend/internal/service/provider_rock_test.go` | 覆盖软熔断、Anti-Ghost、UID不匹配阻断、黑蓝动态兑换、采购与连通测试 | ✅ 100% 通过 |
|
||||
|
||||
### 7.2 自动化测试结果记录
|
||||
- 后端单元测试:`go test -v ./internal/service -run TestRock`
|
||||
- `TestRockProvider_KillSwitch`: PASS (0.41s)
|
||||
- `TestRockProvider_AntiGhostAndUIDMismatch`: PASS (0.29s)
|
||||
- `TestRockProvider_SubmitBlueAndBlack`: PASS (0.27s)
|
||||
- `TestRockService_StatsAndPurchase`: PASS (0.27s)
|
||||
- 后端全量测试:`go test ./...` -> 全部通过 (exit code 0)
|
||||
- 前端静态构建:`npm run build` -> `tsc -b && vite build` 成功通过 (exit code 0)
|
||||
|
||||
@@ -0,0 +1,375 @@
|
||||
# Rock发货平台 (0666.pro) 自动发货逆向与接口分析报告
|
||||
|
||||
> **编制日期**:2026-10-05
|
||||
> **抓包来源**:
|
||||
> 1. `/Users/yml/Desktop/抓包/rock相关/打包两个并查看-发货黑色.har`
|
||||
> 2. `/Users/yml/Desktop/抓包/rock相关/打包两个黑色并查看.har`
|
||||
> 3. `/Users/yml/Desktop/抓包/rock相关/兑换记录等杂项.har`
|
||||
> 4. `/Users/yml/Desktop/抓包/rock相关/蓝色一个发货.har`
|
||||
> 5. 前端完整源码:`https://0666.pro/app.js`(316KB 原生未混淆代码已还原提取)
|
||||
> **核心标的**:和平精英皮肤发货(黑色ROCK长袖T恤、蓝色运动服上衣、货币附赠等)
|
||||
|
||||
---
|
||||
|
||||
## 一、 证据分类与确信度评估矩阵
|
||||
|
||||
依照逆向工程与高强度分析标准,本次所有结论均严格基于抓包实体通信数据与前端源代码交叉验证:
|
||||
|
||||
| 证据项编号 | 证据分类 | 来源与定位 | 关键事实 / 发现 | 确信度 |
|
||||
| :--- | :--- | :--- | :--- | :--- |
|
||||
| **EV-01** | 通信抓包 (HAR) | `发货黑色.har` [Entry 34] | 提取 Token 请求:`POST /api/user/tokens/claim`,Body: `{"color":"black","count":"2"}`,扣除积分提取可用 Token。 | **100%** |
|
||||
| **EV-02** | 通信抓包 (HAR) | `发货黑色.har` [Entry 36, 40] | 获取绑定及兑换配置:`GET /api/redeem/{redeem_code}`,返回腾讯官方绑定链接 `bindUrl` 及皮肤/货币配置。 | **100%** |
|
||||
| **EV-03** | 通信抓包 (HAR) | `发货黑色.har` [Entry 37, 39] | 刷新绑定状态:`POST /api/user/tokens/{id}/refresh`,返回 `binding.bound: true`,角色名、角色ID、大区及历史发放记录。 | **100%** |
|
||||
| **EV-04** | 通信抓包 (HAR) | `发货黑色.har` [Entry 42] | 提交兑换发货:`POST /api/redeem/{id}`,Body: `{"skin":"黑色ROCK长袖T恤","currency":"幸运币","account":"感性的洁少"}`,官方发货成功。 | **100%** |
|
||||
| **EV-05** | 前端源码 | `app.js` (L3617~L3720) | 皮肤与货币官方数据字典 `officialSkus`,黑蓝皮肤权限控制与 180 点价值换算公式。 | **100%** |
|
||||
| **EV-06** | 前端源码 | `app.js` (L217513~L217600) | 兑换发货执行函数 `redeemToken()`,揭示其具备登录态与免登录公开态两种调用形态。 | **100%** |
|
||||
| **EV-07** | 前端源码 | `app.js` (L305062~L305120) | 绑定链接解析与生成逻辑,底层依托和平精英官方活动链接 `gp.qq.com/cp/a20241128mobile/...`。 | **100%** |
|
||||
| **EV-08** | 用户截图 | 微信/扫码绑定弹窗截图 | 弹窗展示 Token、状态(已绑定)、大区、角色、当前货币组合与兑换皮肤下拉选择框。 | **100%** |
|
||||
| **EV-09** | 通信抓包 (HAR) | `兑换记录等杂项.har` [Entry 4, 7] | 兑换历史对账接口:`GET /api/user/exchange-records?page=1&pageSize=20`,支持按账号/UID、Token、区服、时间范围精准分页对账。 | **100%** |
|
||||
| **EV-10** | 通信抓包 (HAR) | `兑换记录等杂项.har` [Entry 5] | 腾讯官方履约凭证:刷新/兑换成功记录中返回 `fulfillId: 4519960`(官方发放流水号)及 `membership: 202610`(月份期号)。 | **100%** |
|
||||
| **EV-11** | 通信抓包 (HAR) | `兑换记录等杂项.har` [Entry 3] | 下属发货员列表:`GET /api/user/delivery-agents`,返回该商户绑定的发货员(如丁德鑫、曹强等)。 | **100%** |
|
||||
| **EV-12** | 用户截图 | 批量获取 Token 弹窗截图 | 提取类型默认下拉选项为 `1 = 黑色`,提取数量 2~500,印证了统一下单通用黑色 Token 的业务形态。 | **100%** |
|
||||
| **EV-13** | 通信抓包 (HAR) | `蓝色一个发货.har` [Entry 13] | 蓝色发货兑换请求:`POST /api/redeem/151154`,Body: `{"skin":"蓝色运动服上衣","currency":"幸运币","account":"打破虚妄的浪漫"}`,发放成功。 | **100%** |
|
||||
| **EV-14** | 通信抓包 (HAR) | `蓝色一个发货.har` [Entry 1~10] | **旧绑定数据实锤证据**:初次 refresh 返回旧角色“总荒凉”(3751279035);买家真正微信扫码后更新为“打破虚妄的浪漫”(3688825401),`bind_change_type: "rebind"`,旧角色归入 `previous_bound_account`。 | **100%** |
|
||||
| **EV-15** | 通信抓包 (HAR) | `蓝色一个发货.har` [Entry 0] | 再次证实用于发货蓝色的 Token 151154 其本身规格仍然是 `color: "black"`(黑色通用 Token)。 | **100%** |
|
||||
| **EV-16** | 前端源码 | `app.js` (L3700~L3760) | **商户登录与鉴权机制**:平台无固定密码登录,采用“用户名+手机验证码”(`POST /api/auth/send-code` + `POST /api/auth/phone-login`),登录后下发 Bearer Token 并存于 `localStorage.yd_token`。请求鉴权全量走 `Authorization: Bearer <yd_token>`。 | **100%** |
|
||||
|
||||
---
|
||||
|
||||
## 二、 核心业务模型与算法解构
|
||||
|
||||
### 2.1 颜色规格与权限差异(黑色 vs 蓝色)
|
||||
|
||||
平台采用 **Token** 作为履约载体,Token 本质为标准 HS256 JWT,分为两种颜色规格:
|
||||
|
||||
```
|
||||
+---------------------------+
|
||||
| Token Pool |
|
||||
+---------------------------+
|
||||
|
|
||||
+-----------------+-----------------+
|
||||
| |
|
||||
v v
|
||||
+--------------------+ +--------------------+
|
||||
| Color: black | | Color: blue |
|
||||
| (黑色高级 Token) | | (蓝色标准 Token) |
|
||||
+--------------------+ +--------------------+
|
||||
| |
|
||||
v v
|
||||
+--------------------+ +--------------------+
|
||||
| 可兑换: | | 可兑换: |
|
||||
| 1. 黑色ROCK长袖T恤 | | 1. 蓝色运动服上衣 |
|
||||
| 2. 蓝色运动服上衣 | | 2. 其他普通皮肤 |
|
||||
| 3. 其他普通皮肤 | | (系统排除了黑色ROCK)|
|
||||
+--------------------+ +--------------------+
|
||||
```
|
||||
|
||||
- **黑色 Token (`color: "black"`)**:
|
||||
- 允许兑换:**黑色ROCK长袖T恤**、蓝色运动服上衣、以及其他所有皮肤。
|
||||
- 提取成本:约 21.0 积分/个(抓包配置项 `blackTokenCost: "21.0"`)。
|
||||
- **蓝色 Token (`color: "blue"`)**:
|
||||
- 核心限制:前端与后端均强制校验:`skinCatalog.filter(skin => skin !== BLACK_ROCK_SKIN)`,**严禁兑换黑色 ROCK**。
|
||||
- 提取成本:约 21.0 积分/个(抓包配置项 `blueTokenCost: "21.0"`)。
|
||||
|
||||
### 2.2 价值平衡与货币数量计算算法
|
||||
|
||||
根据 `app.js` 的纯算模型,每个 Token 的官方标称总额度为 **180 点**。每次兑换发放:**1 件皮肤 + N 个附赠游戏货币**。
|
||||
|
||||
$$
|
||||
\text{附赠货币数量} = \max\left(0, \operatorname{round}\left(\frac{180 - \text{皮肤官方单价}}{\text{货币官方单价}}\right)\right)
|
||||
$$
|
||||
|
||||
#### 道具官方价格字典:
|
||||
- **皮肤单价 (`type: 1`)**:
|
||||
- `黑色ROCK长袖T恤`: 80 点
|
||||
- `唐装(红)`: 120 点
|
||||
- `火焰口罩`: 160 点
|
||||
- `蓝色运动服上衣` / `战地情缘` / `卧虎藏龙` / `水墨画口罩`: 40 点
|
||||
- **货币单价 (`type: 0`)**:
|
||||
- `幸运币`: 10 点
|
||||
- `荣耀勋章`: 10 点
|
||||
- `物资币`: 10 点
|
||||
- `服饰币`: 1 点
|
||||
|
||||
#### 实际组合计算示例:
|
||||
1. **兑换黑色ROCK + 幸运币**:
|
||||
$$\frac{180 - 80}{10} = \mathbf{10} \text{ 个幸运币}$$
|
||||
(抓包记录完全吻合:`currencyQuantity: 10`)
|
||||
2. **兑换蓝色运动服 + 幸运币**:
|
||||
$$\frac{180 - 40}{10} = \mathbf{14} \text{ 个幸运币}$$
|
||||
(用户截图完全吻合:按钮显示“领取蓝色运动服上衣 + 幸运币x14”)
|
||||
3. **若选择服饰币(单价 1)**:
|
||||
- 黑色ROCK + 服饰币:$(180 - 80) / 1 = 100$ 个服饰币
|
||||
- 蓝色运动服 + 服饰币:$(180 - 40) / 1 = 140$ 个服饰币
|
||||
|
||||
---
|
||||
|
||||
## 三、 Token 全生命周期状态机
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> available: 平台入库/上游导入
|
||||
available --> using: 用户调用 claim 提取 / 分配入包
|
||||
using --> bound: 买家扫码并在官方活动页绑定角色成功
|
||||
using --> abnormal: 扫码超时/异常上报
|
||||
bound --> using: 买家重新扫码切换账号 (换绑)
|
||||
bound --> redeemed: 提交兑换接口 (选择皮肤+货币+角色)
|
||||
redeemed --> settled: 管理员/提交员结算
|
||||
settled --> [*]
|
||||
abnormal --> [*]
|
||||
```
|
||||
|
||||
| 状态标识 | 状态中文 | 释义与系统行为 |
|
||||
| :--- | :--- | :--- |
|
||||
| `available` | 可用 | 处于平台库存池中,尚未分配。 |
|
||||
| `using` | 使用中 / 待使用 | 已被分销商提取(claim),生成了唯一的 `redeem_code`,等待买家扫码。 |
|
||||
| `bound` | 已绑定 | 买家已扫码并在腾讯活动页完成角色绑定,系统已捕获到角色名称和大区。 |
|
||||
| `redeemed` | 已兑换 | 已向游戏服务器成功提交发货请求,皮肤和货币已到账。 |
|
||||
| `settled` | 已结算 | 最终财务结算状态。 |
|
||||
| `abnormal` | 异常 | 异常报错,由用户或发货员上报。 |
|
||||
|
||||
---
|
||||
|
||||
## 四、 自动化发货接口技术规格 (API Reference)
|
||||
|
||||
系统提供两种调用链路:
|
||||
1. **主控管理端(带 Bearer 鉴权)**:用于后台批量提取 Token、监控状态。
|
||||
2. **免登录公开端(仅凭 `redeem_code`)**:用于生成买家专用发货链接,完全无状态。
|
||||
|
||||
### 4.1 提取 Token (Claim)
|
||||
- **请求方式**:`POST https://0666.pro/api/user/tokens/claim`
|
||||
- **请求头**:
|
||||
```http
|
||||
Authorization: Bearer <user_token>
|
||||
Content-Type: application/json
|
||||
```
|
||||
- **请求体**:
|
||||
```json
|
||||
{
|
||||
"color": "black", // "black" 或 "blue"
|
||||
"count": "1" // 提取数量
|
||||
}
|
||||
```
|
||||
- **返回体**:
|
||||
```json
|
||||
{
|
||||
"tokens": [
|
||||
{
|
||||
"id": 151153,
|
||||
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||||
"color": "black",
|
||||
"region": "Q/V可用",
|
||||
"phone": "13755033455",
|
||||
"status": "using",
|
||||
"redeem_code": "a4b7d1c94034e6fc52368b61dff20afe",
|
||||
"expires_at": "2026-11-03 11:54:30"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 获取绑定二维码与链接
|
||||
- **请求方式**:`GET https://0666.pro/api/redeem/{redeem_code}`
|
||||
- **说明**:此接口为免登录公开接口,任何持有 `redeem_code` 的客户端均可调用。
|
||||
- **返回体**:
|
||||
```json
|
||||
{
|
||||
"token": {
|
||||
"id": 151153,
|
||||
"color": "black",
|
||||
"status": "using",
|
||||
"redeem_code": "a4b7d1c94034e6fc52368b61dff20afe"
|
||||
},
|
||||
"bindUrl": "https://gp.qq.com/cp/a20241128mobile/index.html?userId=13755033455×tamp=1791176387&nonce=be809689&sign=cb1ce3c99601ba6fe1902064176241d2d0a0683a",
|
||||
"bindError": "",
|
||||
"config": {
|
||||
"skinOptions": "[\"蓝色运动服上衣\",\"黑色ROCK长袖T恤\",...]",
|
||||
"defaultCurrency": "幸运币"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4.3 刷新与查询绑定状态 (Refresh)
|
||||
- **请求方式**:
|
||||
- 方式 A(管理端):`POST https://0666.pro/api/user/tokens/{id}/refresh`
|
||||
- 方式 B(公开端):`POST https://0666.pro/api/redeem/{redeem_code}/refresh`
|
||||
- **返回体**(绑定成功):
|
||||
```json
|
||||
{
|
||||
"token": {
|
||||
"id": 151153,
|
||||
"status": "bound",
|
||||
"bound_account": "感性的洁少",
|
||||
"bound_account_id": "3911959065",
|
||||
"region": "安卓-微信"
|
||||
},
|
||||
"binding": {
|
||||
"bound": true,
|
||||
"role": "感性的洁少",
|
||||
"roleId": "3911959065",
|
||||
"region": "安卓-微信"
|
||||
},
|
||||
"deliveryList": [
|
||||
// 该角色的历史发放记录,防止重复防刷
|
||||
],
|
||||
"message": "已刷新绑定信息"
|
||||
}
|
||||
```
|
||||
|
||||
### 4.4 提交兑换发货 (Redeem)
|
||||
- **请求方式**:
|
||||
- 方式 A(管理端):`POST https://0666.pro/api/redeem/{id}`(请求头带 Bearer)
|
||||
- 方式 B(公开端):`POST https://0666.pro/api/redeem/{redeem_code}`(无需 Bearer)
|
||||
- **请求体**:
|
||||
```json
|
||||
{
|
||||
"skin": "黑色ROCK长袖T恤", // 必须在可选列表内
|
||||
"currency": "幸运币", // "幸运币" / "荣耀勋章" / "物资币" / "服饰币"
|
||||
"account": "感性的洁少" // 必须与 binding.role 一致
|
||||
}
|
||||
```
|
||||
- **返回体**:
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"message": "领取成功",
|
||||
"token": {
|
||||
"id": 151153,
|
||||
"status": "redeemed",
|
||||
"redeem_skin": "黑色ROCK长袖T恤",
|
||||
"redeem_currency": "幸运币",
|
||||
"redeemed_at": "2026-10-05 13:05:07"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4.5 批量打包分享 (Package,可选能力)
|
||||
- **请求方式**:`POST https://0666.pro/api/user/packages`
|
||||
- **请求体**:
|
||||
```json
|
||||
{
|
||||
"ids": [151126, 151130],
|
||||
"note": "订单批次001"
|
||||
}
|
||||
```
|
||||
- **返回体**:生成公开访问链接 `https://0666.pro/#/package/{share_code}`,可直接将整包交付给大客户或批量发货打手。
|
||||
|
||||
### 4.6 兑换历史对账接口 (Exchange Records)
|
||||
- **请求方式**:`GET https://0666.pro/api/user/exchange-records?page=1&pageSize=20`
|
||||
- **请求头**:`Authorization: Bearer <user_token>`
|
||||
- **Query 过滤参数**:
|
||||
- `page`: 页码(从 1 开始)
|
||||
- `pageSize`: 每页数量
|
||||
- `account`: 游戏角色名 / 角色 UID(精准核账)
|
||||
- `token`: 按指定 Token 过滤
|
||||
- `region`: 按区服过滤
|
||||
- `dateFrom` / `dateTo`: 兑换时间范围
|
||||
- **返回体**:
|
||||
```json
|
||||
{
|
||||
"tokens": [
|
||||
{
|
||||
"id": 151153,
|
||||
"token": "eyJhbGciOi...",
|
||||
"color": "black",
|
||||
"region": "安卓-微信",
|
||||
"status": "redeemed",
|
||||
"bound_account": "感性的洁少",
|
||||
"bound_account_id": "3911959065",
|
||||
"redeem_skin": "黑色ROCK长袖T恤",
|
||||
"redeem_currency": "幸运币",
|
||||
"redeemed_at": "2026-10-05 13:05:07",
|
||||
"claimed_at": "2026-10-05 12:59:45",
|
||||
"redeem_code": "a4b7d1c94034e6fc52368b61dff20afe"
|
||||
}
|
||||
],
|
||||
"pagination": {
|
||||
"page": 1,
|
||||
"pageSize": 20,
|
||||
"total": 649,
|
||||
"totalPages": 33
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4.7 腾讯官方发货履约凭证 (FulfillId)
|
||||
在 `POST /api/user/tokens/{id}/refresh` 返回的 `deliveryList` 列表中,包含每一笔发货的腾讯底层官方唯一凭据:
|
||||
```json
|
||||
{
|
||||
"skinId": 27,
|
||||
"skin": "黑色ROCK长袖T恤",
|
||||
"currencyId": 13,
|
||||
"currency": "幸运币",
|
||||
"currencyQuantity": 10,
|
||||
"time": "2026-10-05T13:05:07.337",
|
||||
"role": "安卓-微信-感性的洁少",
|
||||
"message": "成功发放",
|
||||
"fulfillId": 4519960, // 腾讯官方发货流水号,可直接作为 ProviderOrderNo
|
||||
"membership": 202610 // 发放会籍期数
|
||||
}
|
||||
```
|
||||
|
||||
### 4.8 异常上报接口 (Report Abnormal)
|
||||
- **请求方式**:`POST https://0666.pro/api/user/tokens/{id}/report`
|
||||
- **请求头**:`Authorization: Bearer <user_token>`
|
||||
- **请求体**:
|
||||
```json
|
||||
{
|
||||
"reason": "买家扫码绑定异常/账号封禁"
|
||||
}
|
||||
```
|
||||
- **作用**:将无法使用的 Token 置为 `abnormal` 异常状态,冻结并报备管理员或提交员。
|
||||
|
||||
### 4.9 账户体系与登录接口 (Authentication & Profile)
|
||||
- **商户信息与积分快照**:
|
||||
- **请求方式**:`GET https://0666.pro/api/me`
|
||||
- **请求头**:`Authorization: Bearer <user_token>`
|
||||
- **返回体**:
|
||||
```json
|
||||
{
|
||||
"user": {
|
||||
"id": 10028,
|
||||
"username": "王大锤",
|
||||
"role": "merchant",
|
||||
"points": 8271.2,
|
||||
"status": "active"
|
||||
}
|
||||
}
|
||||
```
|
||||
- **上游登录机制解构 (EV-16)**:
|
||||
- **方式一(无密码短信验证码)**:
|
||||
1. 发送验证码:`POST /api/auth/send-code`,Body: `{"username": "商户名"}`
|
||||
2. 验证码校验登录:`POST /api/auth/phone-login`,Body: `{"username": "商户名", "code": "123456"}`
|
||||
3. 成功后返回 `{"token": "05c55d8b8c...", "user": {...}}`,前端存入 `localStorage.yd_token`。
|
||||
- **方式二(Token 直接配置)**:
|
||||
直接携带有效的 `yd_token` 发起全部 API 调用。因上游商户账号无固定密码,**实施阶段确认采用后台直接录入 Token 的模式进行对接**,后续再按需考虑是否引入验证码登录交互。
|
||||
|
||||
---
|
||||
|
||||
## 五、 已知、未知与对接目标清单
|
||||
|
||||
### 5.1 已知事项 (Knowns)
|
||||
1. **网络通信协议无加密防护**:请求为明文 JSON,无需逆向复杂的 Webpack 虚拟机加解密或 WAF 签名算法,通信门槛低。
|
||||
2. **商户账号鉴权特征明确**:上游**无独立密码登录**,仅支持 Token 登录与“用户名+手机短信验证码”登录。登录态通过 `Authorization: Bearer <yd_token>` 全局透传,有效期长且支持通过 `GET /api/me` 实时探测状态与积分余额。
|
||||
3. **角色绑定走和平精英官方 H5 授权**:由腾讯官方活动页面(`gp.qq.com`)承接鉴权,安全合规,无风控封号风险。
|
||||
4. **提取统一下单通用 Token,绑定后发货前动态选择皮肤**:
|
||||
- 提取采购阶段统一下单为“黑色通用 Token”(`1 = 黑色`),生成通用绑定链接;
|
||||
- 买家扫码并通过 UID 强一致门禁后,在最终发货调用 `POST /api/redeem/{id}` 时,根据订单商品动态传入 `skin`(黑色ROCK或蓝色运动服)。
|
||||
5. **具备官方发货凭证与对账接口**:
|
||||
- 上游返回 `fulfillId`(腾讯官方发货单号),可直接作为我们系统的 `ProviderOrderNo`;
|
||||
- 提供 `GET /api/user/exchange-records`,支持异步核验与网络超时防重对账。
|
||||
6. **公开免登录能力完整**:买家端可直接使用 `redeem_code` 独立完成绑定与兑换,避免在买家端暴露平台主账号的 Bearer Token。
|
||||
|
||||
### 5.2 核心业务决策与防错机制 (Decisions & Guards)
|
||||
1. **后台全反代无感方案**:系统统一反代,买家和打手使用本系统原生提货页 `/delivery/:orderNo`,绝不暴露上游平台。
|
||||
2. **UID 强一致防御门禁**:前置强制输入 UID,捕获角色不符时硬阻断发货;记录初始快照防止上游旧绑定信息混淆。
|
||||
3. **系统用户采购凭据先落 Token 模式**:后台提供极简 Bearer Token 录入与一键连通性测试(调 `/api/me`),自动读取用户名和积分;暂不接入验证码流程,避免多余交互。
|
||||
4. **本地通用库存池与自动补货**:本地维护统一的通用 Token 池,支持采购 50 个、低水位告警与自动补货。
|
||||
5. **绑定错误统计与全局总开关**:mismatch 独立看板,全局发货总开关(Kill Switch)一键止血熔断转人工。
|
||||
|
||||
### 5.3 下一步对接目标 (Next Steps / Goals)
|
||||
1. 建立本地 `rock_tokens` 通用库存表与系统配置存储(存储 `rock_bearer_token` 等)。
|
||||
2. 开发上游 0666 纯 HTTP 交互模块(Claim 采购、Refresh 刷新、Redeem 兑换、ExchangeRecords 对账、Me 心跳与积分探测)。
|
||||
3. 接入后台批量采购 50 个、库存列表、mismatch 统计看板、水位预警(飞书/钉钉)与自动补货任务。
|
||||
4. 提货前端接入 UID 前置输入与扫码一致性校验硬阻断。
|
||||
5. 完成标准 `RockProvider` 接入既有路由与发货工作台。
|
||||
Reference in New Issue
Block a user