Files
order_site/docs/khhao来源接入设计.md
T
2026-05-02 16:20:08 +08:00

404 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# khhao 新数据来源接入设计
## 1. 背景
当前系统的订单来源只有 `agiso`,核心模式是:
- 上游通过 webhook 推送订单事件;
- 后端按 `provider + platform + shopId + platformOrderId` 幂等落库;
- 命中履约绑定后生成任务、领取链接、自动发货等后续流程。
现在需要新增一个来源:`admin.khhao.com` 这一套已开发好的平台后台。
`agiso` 的差异是:
- **不是 webhook 推送**,而是**账号密码登录 + 验证码识别 + Cookie 会话查询**
- 订单数据来自平台接口查询;
- 初期目标是先完成**登录能力**与**订单查询能力**,再决定是否做定时拉取/增量同步。
## 2. 已确认事实(来自 `2026-05-02` 的 HAR
HAR 文件:`/Users/yml/Desktop/抓包/登陆.har`
已确认接口链路:
1. 打开登录页
`GET https://admin.khhao.com/c/login/index.php`
2. 获取验证码图片
`GET https://admin.khhao.com/verify_img.php`
3. 提交登录表单
`POST https://admin.khhao.com/c/login/index.php`
表单字段:
- `username`
- `password`
- `img_code`
4. 登录成功响应
```json
{"errcode":0,"msg":"登陆成功","url":"/c/payOrder/index.php"}
```
5. 查询订单列表
`GET https://admin.khhao.com/c/payOrder/get.php?page=1&limit=50`
6. 当前 HAR 中,登录依赖 `PHPSESSID` Cookie 维持会话。
订单列表响应里已看到这些关键字段:
- `ordersn`:外部订单号
- `pingtai` / `pingtaiName`:平台标识/平台名
- `shopid` / `shopName`:店铺
- `goodid` / `goodName`:商品
- `sku`SKU
- `fee`:成交金额
- `chengben` / `lirun`:成本/利润
- `num`:数量
- `status` / `statusName`:订单状态
- `addtime`:下单/录入时间
## 3. 设计目标
### 3.1 MVP 目标
先做最小可用能力:
1. 后端可通过账号密码自动登录 khhao;
2. 自动拉取验证码图片,并用现有 `ddddocr` 识别;
3. 登录成功后带 Cookie 调用订单查询接口;
4. 能按统一结构把 khhao 订单转换为内部订单模型;
5. 提供一个**手动查询 / 手动同步**入口,先不直接接入自动履约主流程。
### 3.2 第二阶段目标
1. 支持按时间窗口或页码批量拉取订单;
2. 增加定时轮询同步;
3. 将 khhao 订单正式纳入现有订单履约流程;
4. 视需要增加远端订单详情接口接入。
## 4. 关键设计决策
## 4.1 新来源标识
建议:
- `provider = 'khhao'`
- `platform = 由返回字段映射`
原因:
- 现有系统已经以 `provider/platform` 作为来源分层;
- khhao 本身更像“聚合后台/运营后台”,其下可能有多个平台;
- 后续如果 `pingtai=3` 代表快手、还有其它平台,也可以继续扩展。
建议先做一个映射表,例如:
- `3 -> kuaishou`
- 未识别值 -> `unknown`
同时把原始 `pingtai`、`pingtaiName` 放进 `raw_payload_json` 保留证据。
## 4.2 接入模式
`agiso` 是 **push**`khhao` 应设计成 **pull**。
因此不要强行塞进 `webhook-service`,而是单独建立:
- 登录会话服务
- 验证码识别服务
- 订单查询服务
- 订单转换/同步服务
## 4.3 会话管理
建议优先采用 **纯 HTTP + Cookie Jar**,不引入浏览器自动化。
原因:
- HAR 显示登录流程很简单,没有前端加密、签名或复杂跳转;
- 验证码是普通图片;
- 登录后查询接口是标准 XHR
- 用 HTTP 实现更稳定,也更适合服务端定时任务。
只有在后续发现以下情况时,再退回浏览器方案:
- 服务端校验动态前端字段;
- 有 JS 生成签名;
- Cookie/会话依赖浏览器行为;
- 验证码识别成功但仍反复登录失败。
## 4.4 OCR 复用
现有 OCR 子服务已经使用:
- `apps/backend/subservices/ocr-worker`
- `ddddocr>=1.6.1`
因此不需要新增 OCR 技术栈,只需要把 khhao 验证码图片作为图片字节传给现有 OCR 能力即可。
建议新增一个更通用的方法,而不是继续绑定在 “Tencent” 语义上:
- 现状:`recognizeTencentCaptcha`
- 建议新增:`recognizeImageCaptcha`
然后:
- 腾讯验证码继续走原接口或复用通用接口;
- khhao 登录验证码直接走通用接口。
## 5. 推荐模块拆分
建议新增目录:
`apps/backend/src/services/platforms/khhao/`
建议模块:
### 5.1 `captcha-service.js`
职责:
- 请求 `/verify_img.php`
- 读取图片字节
- 调 OCR
- 返回识别结果与调试信息
建议返回:
- `captchaText`
- `imageBase64`(仅调试阶段可选)
- `cookieHeaders`
### 5.2 `session-service.js`
职责:
- 初始化 Cookie 容器;
- 访问登录页,拿到初始 `PHPSESSID`
- 获取验证码并识别;
- 提交登录表单;
- 校验登录响应;
- 返回已登录会话对象。
建议会话对象:
- `baseUrl`
- `cookieHeader`
- `cookieMap`
- `loggedInAt`
### 5.3 `order-query-service.js`
职责:
- 调用 `/c/payOrder/get.php`
- 支持分页参数:`page`、`limit`
- 后续支持筛选参数(如果继续抓到更多接口)
- 返回原始平台订单列表
### 5.4 `order-mapper-service.js`
职责:
- 将 khhao 原始订单映射成内部统一订单结构;
- 归一化金额、数量、状态、平台、店铺、SKU;
- 产出可供 `order-service` 或新同步服务消费的对象。
建议映射:
- `platformOrderId <- ordersn`
- `shopId <- shopid`
- `shopName <- shopName`
- `totalAmount <- fee`(转分)
- `items[0].skuCode <- sku`
- `items[0].skuName <- goodName`
- `items[0].quantity <- num`
- `rawPayload <- 原始整条记录`
注意:
- 当前列表接口一条记录看起来像“一单一商品”,但不能假设永远如此;
- 第一版可以先按单商品映射;
- 如果后续发现有多商品订单,再调整内部映射。
### 5.5 `order-sync-service.js`
职责:
- 批量查询 khhao 订单;
- 调 `order-mapper-service` 转换;
- 调内部订单 upsert
- 记录同步结果、失败原因、游标信息。
这里建议不要直接复用 `upsertOrderFromWebhook(event)`,因为它的命名和语义绑定 webhook。
更合理的演进方向:
- 抽一个来源无关的方法,例如 `upsertOrderFromSource(event)`
- `webhook-service` 继续只负责 webhook 解析;
- `khhao` 同步服务直接调用来源无关的 upsert。
## 6. 配置设计
## 6.1 运行时配置
建议在:
- `apps/backend/config/default.cjs`
- `apps/backend/src/types/runtime-config.js`
- `apps/backend/src/config/runtime.js`
增加:
```js
platforms: {
khhao: {
baseUrl: 'https://admin.khhao.com',
timeoutMs: 5000,
loginPath: '/c/login/index.php',
captchaPath: '/verify_img.php',
orderListPath: '/c/payOrder/get.php',
},
}
```
## 6.2 凭据配置
不建议把账号密码直接写进仓库文档或默认配置。
建议通过以下方式之一管理:
1. 环境变量;
2. `apps/backend/data/khhao-sources.json`
3. 后台平台配置页维护。
建议结构:
```json
{
"sources": [
{
"sourceKey": "khhao-main",
"enabled": true,
"baseUrl": "https://admin.khhao.com",
"username": "******",
"password": "******",
"defaultPlatform": "kuaishou"
}
]
}
```
第一阶段最省成本的方案:**本地文件 + 环境变量覆盖**。
## 7. 与现有系统的衔接方式
## 7.1 第一阶段:只做手动查询/同步
建议新增后台接口,例如:
- `POST /api/v1/admin/platform-config/khhao/test-login`
- `POST /api/v1/admin/platform-config/khhao/query-orders`
- `POST /api/v1/admin/platform-config/khhao/sync-orders`
这样好处是:
- 不会影响现有 `agiso` 主链路;
- 可以先验证 OCR、登录、Cookie、字段映射;
- 便于比对真实订单数据。
## 7.2 第二阶段:纳入统一订单流程
当字段映射稳定后,再把 khhao 同步数据接到统一订单主链路:
- 来源查询 -> 订单映射 -> 通用 upsert -> 履约绑定 -> 任务生成
这一步需要补充:
- khhao 订单状态到内部 `orderStatus/payStatus` 的映射;
- 去重与增量同步策略;
- 同一来源重复登录的频率控制;
- 同步审计日志。
## 8. 状态映射建议
当前 HAR 仅看到:
- `status = 2` => `已发货`
- `status = 0` => `未打款`
第一阶段不要写死太多业务含义,建议:
### 内部订单状态
- `status=0` -> `created`
- `status=2` -> `delivered`
- 未知值 -> `unknown`
### 内部支付状态
- `status=0` -> `unpaid`
- `status=2` -> `paid`
- 未知值 -> `unknown`
但这只是 **初版推断**,最终要以更多样本验证。
## 9. 风险点
1. **验证码识别率**
- `ddddocr` 大概率可用,但识别失败需要自动重试;
- 建议单次登录允许 `2~3` 次验证码重试。
2. **登录态过期**
- 需要判断何时复用 Cookie,何时重新登录;
- 第一阶段可以每次查询都重新登录,先求稳定。
3. **订单列表不是详情接口**
- 当前拿到的是列表接口,不排除存在订单详情页/详情接口;
- 第一版先以列表字段落库;
- 如果后续履约需要更多字段,再补抓详情接口。
4. **平台字段含义未完全确认**
- `pingtai=3` 目前只从样本推断是快手;
- 需要再抓几个平台样本确认映射表。
5. **同步边界**
- khhao 是拉取式来源,必须明确增量条件;
- 第一版建议按 `page/limit` 手动同步,先不做自动游标。
## 10. 推荐实施顺序
### 阶段 A:打通基础能力
1. 增加 khhao 配置结构;
2. 增加通用图片 OCR 能力;
3. 实现登录 + Cookie 会话;
4. 实现订单列表查询;
5. 增加后台“测试登录 / 查询订单”接口。
### 阶段 B:打通内部模型
1. 实现 khhao -> 内部订单映射;
2. 提炼 webhook 无关的通用 order upsert
3. 增加手动同步接口;
4. 在后台展示同步结果。
### 阶段 C:进入自动履约
1. 增量同步;
2. 定时任务;
3. 状态回补;
4. 接入履约绑定、任务生成、消息通知。
## 11. 本次设计结论
结论很明确:
- khhao 不应该按 `agiso webhook` 思路接;
- 应该作为一个新的 **pull 型来源** 单独建接入层;
- OCR 直接复用现有 `ddddocr` 子服务;
- 第一阶段先做**手动查询/同步**最稳;
- 等字段、状态、平台映射稳定后,再接入统一履约主流程。