Artifact 08d5912512f5d271242b6e2e9b3fdedca9629fdd0327d8ef915f3b63784b0dde:
- File
docs/api/ql361_reverse_spec.md
— part of check-in
[5bb18ed4d4]
at
2026-10-23 03:34:10
on branch trunk
— 把来肯对接和本地库落到可切换的后端。
账号从环境读取,商品由人工增量同步,订单按五分钟轮询并缓存登录会话。开发期用 SQLite,同一套结构可切到 PostgreSQL。 (user: pluto size: 7794)
QL361 (来肯企汇) 逆向接口协议分析与对接技术规范
| 文档版本 | 编写日期 | 目标站点 | 分析工具 / 方式 |
|---|---|---|---|
| v1.0.0 | 2026-10-23 | https://22beta.ql361.com/ |
Web 静态分析、JS 运行时代码逆向 |
1. 核心网络与网关拓扑
1.1 站点入口
- 业务工作台页面:
https://22beta.ql361.com/desktop.html?v=196647593#/ - 静态资源基础路径:
https://22beta.ql361.com/v_22beta/ - 统一 API 网关地址:
https://22beta.ql361.com/v_22beta/api.cc(或分布式直连网关https://20-apiserver-prod.ql361.com/api.cc) - 统一认证登录页面:
https://www.ql361.com/account/logon - 认证接口:
POST https://www.ql361.com/account/Auth
1.2 安全与防御层 (WAF)
- CDN 提供商:腾讯云 EdgeOne (
Server: TencentEdgeOne) - 防御机制:EdgeOne 具备 Bot 防护与防抓取策略。所有 HTTP 请求必须附带合法的现代浏览器
User-Agent与合规的Accept、Referer头,否则将返回HTTP 567 Unknown Status阻断。 - 登录验证码:集成了网易易盾(NetEase Dun)滑动验证码,同时系统也支持手机 App 扫码登录(
GET /account/QRCode轮询)。
2. API 通信协议规范 (api.cc)
QL361 采用基于 RPC 风格的统一网关协议,所有业务调用均路由至 api.cc。
2.1 请求格式
- HTTP Method:
POST - URL 查询参数: $$text{URL} = text{base_url} + text{?___method=} + text{MethodName} + text{&pagetype=erp&from=allinoneclient&platform=pc} + text{TokenQuery}$$
| 参数名 | 必填 | 说明 | 示例 |
|---|---|---|---|
___method |
是 | 后端业务逻辑层 (BLL) 方法名,大小写敏感 | CC.ERP.BLL.API.MessageServer.GetLoginStatusForDesktop |
pagetype |
是 | 页面类型 | 默认 erp,报表或消息传 crmoa |
from |
是 | 客户端来源代号 | 固定 allinoneclient |
platform |
是 | 客户端平台 | 固定 pc |
s |
是 | 会话标识 (Session Id) | 从登录态 Cookie 中获取的 s 值 |
tok |
是 | 鉴权令牌 (Token) | 从登录态 Cookie 中获取的 tok 值 |
HTTP 请求头 (Headers):
Host: 22beta.ql361.com User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 Content-Type: application/json Referer: https://22beta.ql361.com/desktop.html?v=196647593 Cookie: s=<SESSION_ID>; tok=<TOKEN>; acw_tc=<WAF_COOKIE>请求体 (Body): 标准的 JSON 字符串。
{ "billid": 100234, "begindate": "2026-10-01", "enddate": "2026-10-23" }
3. 响应结构与异常状态码
QL361 网关返回的 JSON 响应具有统一的包裹结构:
3.1 正常响应 (Normal)
{
"type": "normal",
"data": { ... },
"msg": "",
"productVersion": "v_22beta"
}
3.2 会话过期 / 未登录 (Logoff)
{
"type": "logoff",
"msg": "当前账号已在其他地方登录或已退出登录",
"data": null
}
处理策略:SwiftFlow 逆向引擎捕获到
type == "logoff"或msg包含“已退出登录”时,立即触发告警或重新发起认证流程。
3.3 业务异常 (Error)
{
"type": "error",
"msg": "未找到指定单据信息",
"data": null
}
4. 核心 BLL 业务方法清单 (只读抽取)
| 业务领域 | 核心方法名 (___method) |
业务用途 | 实测状态 |
|---|---|---|---|
| 会话状态 | CC.ERP.BLL.API.MessageServer.GetLoginStatusForDesktop |
检查当前 Session 是否有效 | 已验证通过 |
| 基础仓库 | cc.erp.bll.bas.baseinfomanager.getforautocomplete |
获取全部仓库列表 (bastype: "store") |
已验证通过 |
| 销售订单列表 | cc.erp.bll.bill.billbllmanager.getdatalist |
分页拉取销售订单 (billtype: 604) |
已验证通过 |
| 订单商品行明细 | cc.erp.bll.bill.billbllmanager.getfulldata |
查询指定订单全量明细与商品条码/规格/库位 | 已验证通过 |
| 待拣货销售清单 | cc.erp.bll.report.reportmanager.getdatalist |
待拣货专用报表视图 (billtype: 2352) |
已验证通过 |
| 待发货出库清单 | CC.ERP.BLL.Bill.Core.Delivery.DeliveryHandOverService.QueryCanHandOverBillList |
交接发货出库单据 | 已验证通过 |
5. 销售订单与商品明细数据协议 (实测样本)
5.1 订单列表拉取 (cc.erp.bll.bill.billbllmanager.getdatalist)
- 请求负载:
{ "reportparam": { "orders": "", "parid": 0, "pagetype": "erp", "displaytype": "tree", "pagerow": 100, "pagenumber": 0 }, "conditionparam": { "begindate": "2024-01-01", "enddate": "2026-12-31", "billtype": 604, "status": 20 } } - 核心字段映射:
billid: 订单数字 ID (如1898938789)billcode: 业务单据号 (如XSDD-20260922-001)dfullname: 客户名称 (如山西省忻州市巷往烘焙)contactor: 联系人phone: 电话soutfullname: 发货仓库名称 (如门店)soutid: 仓库 ID (如793208)qty: 订单总件数 (如22.0)totalmoney: 订单总金额status: 订单状态 (20= 待发货/待拣货,22= 发货完成,30= 交易完成,19= 已取消)
5.2 订单全量商品明细 (cc.erp.bll.bill.billbllmanager.getfulldata)
- 请求负载:
{ "billid": 1898938789, "billtype": 604 } - 响应结构:
data.header(单头汇总) +data.body0.datasource(商品行明细列表) - 商品行字段提取:
gcode: 商品编码/SKU (如c001057)gfullname: 商品名称 (如乙夫-蔬香紫薯味吐司400g)barcode: 69码/EAN13商品条码 (如6971979070155)spec: 规格 (如400g*20袋)mqty/mufullname: 大单位件数 (如2.0 件)qty/bufullname: 基本单位散件数 (如40.0 盒)gpcode: 原系统货位 (如默认货位(门店))sacode: 原系统库区 (如默认库区)
6. 拣货单生成转换逻辑 (SwiftFlow WMS 核心)
从 QL361 销售订单向 SwiftFlow 拣货任务的转换流程如下:
[QL361 销售订单: billtype 604]
│
▼ (只读抽取: getfulldata)
{ 订单商品行明细: SKU, 条码, 件数, 散数 }
│
├───────────────────────────────────────────┐
▼ ▼
【按单拣货 Single Order】 【波次汇总拣货 Wave Picking】
- 单任务 1:1 对应源单 - 多单合并、相同 SKU 累加数量
- SwiftFlow 推荐最优 S 型库位动线 - 匹配四级库位 (区-排-架-位) 推荐最短动线
- PDA 扫条码逐行核销 - 拣货完成后推入播种墙 (Seed Wall) 进行二次分播
│ │
▼ ▼
【拣货完成待复核】 【播种复核分箱完成】
5. SwiftFlow 在 Gleam 中的实现架构
- 模块位置:
shared/ql361api - 底层驱动:
gleam_httpc+gleam_json - 设计模式:只读数据适配器模式(Read-Only Adapter Pattern)。所有抓取到的数据经过清洗与类型转换后,投递给
backend/业务核心。