# cloudtentacles 外部履约平台接入设计 ## 1. 背景 当前项目里现有链路大致分两层: - **订单来源层** - `agiso`:Webhook 推送型; - `khhao`:账号密码登录 + 验证码识别 + Cookie 会话拉取型。 - **履约执行层** - 当前以内置人工发货、腾讯领取兑换等执行器为主。 现在新增一个发货相关的平台,当前已知入口为: - `https://123.207.217.176` - 前端资源来自 `gp.playinjoy.com` - 前端代码里根实例名显示为 `cloudtentacles` 这个平台**不是订单数据源**,而是**订单创建后用于执行发货/兑换的外部履约平台**。 它和 `khhao` 的相同点只是“都需要后台登录”,但系统角色完全不同: - `khhao`:订单来源 / 上游平台; - `cloudtentacles`:履约执行 / 下游发货平台。 它的登录链路与 `khhao` 明显不同: - 不是图片验证码识别; - 是“账号 + 密码 + 手机号 + 短信验证码”登录; - 登录参数不是明文提交,而是前端先做 `MD5 + RSA-OAEP(SHA-256)` 加密; - 登录成功后不是 Cookie 会话,而是返回 `token`,后续通过 `Authorization` 请求头访问接口。 因此它应当作为**履约执行器能力**接入,复用 `khhao` 的“HTTP 登录平台”经验,但不要按“来源平台”建模。 --- ## 2. 当前已确认事实 ### 2.1 证据来源 - HAR:`/Users/yml/Desktop/抓包/123.207.217.176.har` - 前端代码:`tems/test1.js` - 打包代码:`tems/index.93fe093c.js` ### 2.2 已确认接口链路 1. 发送短信验证码 `POST https://123.207.217.176/public/verif_code` 2. 提交登录 `POST https://123.207.217.176/public/login` 3. 登录后探活接口 - `POST /user/info` - `GET /user/get_asset` - `GET /user/get_permission` 4. 当前 HAR 里还看到的业务接口 - `GET /categories/get` - `GET /sku/list` ### 2.3 登录态机制 不是依赖 Cookie。 前端在登录成功后会把 `/public/login` 返回的 `data` 当成 token 保存,并在后续请求里自动带上: ```http Authorization: deviceid: - devicetype: 0 ``` ### 2.4 登录参数的真实结构 根据 `tems/test1.js`,发验证码与登录都不是直接提交原始字段,而是先调用 `encryptWithPublicKey(...)`。 #### 发验证码原始参数 ```js { account: username, phone: phone } ``` #### 登录原始参数 ```js { account: username, password: MD5(password), phone: phone, code: smsCode } ``` #### 加密前最终明文 ```js { t: Date.now(), r: Math.random().toString(16), s: 'ct-client', ...payload } ``` 然后: 1. `JSON.stringify` 2. 使用 RSA-OAEP + SHA-256 公钥加密 3. Base64 编码,作为 `covert` 最终请求体: ```json { "covert": "", "t": 1777726021956, "r": "0.8601863c152d6" } ``` ### 2.5 密码处理 密码不是明文传输。 前端代码中: ```js password: cu(password) ``` 而 `cu` 实际是: ```js MD5(password).toString(Hex) ``` 即: - 先 `MD5` - 再参与 RSA 加密 --- ## 3. 设计目标 ## 3.1 第一阶段目标 这一版只做“基础登录能力”,不直接做完整发货自动化: 1. 能发送短信验证码; 2. 能使用账号、密码、手机号、短信验证码自动登录; 3. 能持久化保存该平台的履约配置; 4. 能在后台手动测试登录; 5. 能在登录后调用一个轻量探活接口确认登录成功; 6. 输出统一的会话对象,给后续“SKU 查询 / 背包读取 / 发货执行”复用。 ## 3.2 第二阶段目标 后续逐步补: 1. token 缓存与自动续登; 2. SKU/分类/背包读取; 3. 发货动作封装; 4. 发货结果记录与截图/证据保存; 5. 接成新的 `executor_key`,纳入现有履约任务执行链路; 6. 由“订单支付成功 / 任务就绪”触发自动发货。 --- ## 4. 关键设计决策 ## 4.1 领域定位 这里不应该新增 `provider = 'cloudtentacles'` 作为订单来源标识。 更合理的定位是: - 订单来源 `provider/platform/shopId` 仍然来自 `agiso` / `khhao` - `cloudtentacles` 属于**履约执行器 / 外部发货平台** 因此它更适合进入这条链路: - `fulfillment_profiles.profile_key` - `fulfillment_profiles.executor_key` - 任务执行服务 建议后续新增类似: - `profileKey = 'cloudtentacles_dispatch'` - `executorKey = 'cloudtentacles_dispatch'` 而不是把它混进订单来源层。 ## 4.2 接入模式 这个平台本质上是 **外部履约平台 + token 会话** 模式。 因此结构上可以先放在 `platforms/` 下管理其登录与 API 封装,但业务接入点要落到**履约执行层**: - 配置服务 - 加密服务 - HTTP 客户端 - 登录/会话服务 - 发货业务服务 - 履约执行适配层 ## 4.3 不建议直接照抄 khhao 的原因 `khhao` 当前链路核心是: - 打开登录页 - 拉验证码图片 - OCR - 表单提交 - Cookie 维持会话 而当前平台核心是: - 组装明文 - MD5 密码 - RSA 公钥加密 - 请求登录接口 - token 维持会话 所以如果把所有逻辑都塞进一个 `session-service.js`,后面会越来越乱。 更合理的方式是把“加密”、“请求头”、“token 管理”单独拆开。 ## 4.4 第一版不引入浏览器自动化 当前证据显示不需要浏览器: - HAR 中登录接口是纯 XHR; - 参数生成逻辑已经从 JS 中还原; - token 机制清晰; - 没看到依赖浏览器页面上下文的动态签名。 因此第一版应坚持 **纯 HTTP 实现**。 只有后续遇到这些问题时,才考虑浏览器方案: - 服务端增加不可还原的前端签名; - 短信验证码流程强依赖页面态; - 登录成功但服务端对业务接口做浏览器环境校验。 --- ## 5. 推荐目录结构 建议新增目录: `apps/backend/src/services/platforms/cloudtentacles/` 同时第二阶段补一个执行适配入口,例如: `apps/backend/src/services/fulfillment/cloudtentacles-dispatch-service.js` ### 5.1 第一阶段实际落地文件 #### `shared.js` 职责: - 读取运行时配置; - 规范化 baseUrl / 路径 / timeout; - 构建 URL; - 构建公共请求头; - 统一设备头默认值。 建议内容: - `resolveCloudtentaclesConfig(overrides)` - `buildCloudtentaclesUrl(baseUrl, pathname, searchParams?)` - `buildCloudtentaclesHeaders({ token?, contentType? })` #### `crypto-service.js` 职责: - 密码 MD5; - 公钥 PEM 转 ArrayBuffer / Buffer; - 组装 `t/r/s` 明文; - 执行 RSA-OAEP(SHA-256) 加密; - 返回 `{ covert, t, r }` 建议暴露: - `md5CloudtentaclesPassword(password)` - `encryptCloudtentaclesPayload(payload, options?)` 这样后续不仅登录能用,发验证码、改密等其它加密接口也都能复用。 #### `http-client.js` 职责: - 对 `fetch` 做一层轻封装; - 统一 timeout; - 自动带 `Authorization / deviceid / devicetype`; - 统一解析平台响应格式; - 统一抛出带平台上下文的错误。 建议暴露: - `cloudtentaclesRequest(path, options)` 注意:第一版不用做成全局通用 HTTP 框架,只服务这个平台即可。 #### `session-service.js` 职责: - 发送短信验证码; - 使用短信验证码登录; - 登录后调用 `/user/info` 验证会话; - 返回标准会话对象。 建议暴露: - `sendCloudtentaclesSmsCode(payload)` - `loginCloudtentaclesSession(payload)` - `validateCloudtentaclesSession(payload)` 建议会话对象: ```js { baseUrl, token, loggedInAt, username, phone, userInfo, permissions } ``` #### `source-config-service.js` 职责: - 读写履约平台配置文件; - 管理默认账号、密码、手机号; - 管理后续自动化开关预留字段。 建议文件: `apps/backend/data/cloudtentacles-sources.json` 建议结构: ```json { "enabled": true, "baseUrl": "https://123.207.217.176", "username": "", "password": "", "phone": "", "deviceId": "-", "deviceType": 0 } ``` ### 5.2 第二阶段预留文件 这些先不一定创建实现,但目录命名先按这个方向约束: #### `catalog-service.js` - 分类 - SKU - 背包 - 库存类读取 #### `delivery-service.js` - 发货动作 - CDK / 虚拟物品使用 - 回滚 / 失败重试 #### `record-service.js` - 交易记录 - 发货记录 - 订单对账 #### `auto-sync-service.js` - 定时探活 - 自动续登 - 预热会话 #### `apps/backend/src/services/fulfillment/cloudtentacles-dispatch-service.js` 职责: - 接收履约任务; - 读取任务绑定的库存 / 凭据; - 调用 `platforms/cloudtentacles/*` 完成实际发货; - 回写任务状态、发货结果、证据。 --- ## 6. 配置设计 ## 6.1 运行时配置 建议在: - `apps/backend/config/default.cjs` - `apps/backend/src/types/runtime-config.js` - `apps/backend/src/config/runtime.js` 增加: ```js platforms: { cloudtentacles: { baseUrl: 'https://123.207.217.176', timeoutMs: 5000, sendSmsPath: '/public/verif_code', loginPath: '/public/login', userInfoPath: '/user/info', assetPath: '/user/get_asset', permissionPath: '/user/get_permission', publicKeyPem: '-----BEGIN PUBLIC KEY----- ... -----END PUBLIC KEY-----', clientSource: 'ct-client', deviceId: '-', deviceType: 0, }, } ``` ### 设计说明 - `publicKeyPem` 放运行时配置,而不是硬编码到 service; - `clientSource` 默认是 `ct-client`; - `deviceId / deviceType` 先允许配置,避免后面服务端开始校验时需要改代码。 ## 6.2 持久化来源配置 建议和 `khhao` 一样,先用数据文件落地,不急着进数据库。 建议文件: `apps/backend/data/cloudtentacles-sources.json` 建议第一版结构: ```json { "enabled": true, "baseUrl": "https://123.207.217.176", "username": "", "password": "", "phone": "", "deviceId": "-", "deviceType": 0 } ``` 后续如果要支持多套账号,再演进为: ```json { "sources": [ { "sourceKey": "cloudtentacles-main", "enabled": true, "baseUrl": "https://123.207.217.176", "username": "", "password": "", "phone": "", "deviceId": "-", "deviceType": 0 } ] } ``` 第一版先单来源,能明显降低 UI 和逻辑复杂度。 --- ## 7. API 设计建议 建议先在管理后台补一组最小接口: ### 7.1 配置读取 ```http GET /api/v1/admin/platform-config/cloudtentacles-source ``` 返回: - 配置文件路径 - 当前履约平台配置 ### 7.2 配置保存 ```http POST /api/v1/admin/platform-config/cloudtentacles-source ``` 用于保存: - 账号 - 密码 - 手机号 - baseUrl - 设备头默认值 ### 7.3 发送短信验证码 ```http POST /api/v1/admin/platforms/cloudtentacles/send-sms-code ``` 入参支持: - 使用已保存配置; - 或临时覆盖账号/手机号/baseUrl。 ### 7.4 手动登录测试 ```http POST /api/v1/admin/platforms/cloudtentacles/login ``` 入参: - `username` - `password` - `phone` - `code` 返回: - `token` - `userInfo` - `permissions` - `loggedInAt` ### 7.5 会话探活测试 ```http POST /api/v1/admin/platforms/cloudtentacles/validate-session ``` 入参: - `token` 返回: - 是否有效 - 用户信息 --- ## 8. 后台 UI 设计建议 第一版 UI 不需要太复杂,但应与 `khhao` 分开,避免把“订单来源配置”和“履约平台配置”混在一起。 建议在“平台配置”页新增独立区块,归类到“履约平台”分组: ### 8.1 履约平台配置区 字段: - 启用状态 - baseUrl - 账号 - 密码 - 手机号 - deviceId - deviceType 操作: - 保存配置 ### 8.2 登录测试区 字段: - 短信验证码输入框 操作: - 发送验证码 - 执行登录 - 验证当前 token ### 8.3 调试结果区 显示: - token 是否返回 - userInfo - permissions - 最近一次错误消息 注意: - 不要把这个平台和 `khhao` 放在同一张混合表单里; - 页面上要明确区分: - 订单来源平台 - 履约执行平台 - 后面平台越来越多时,这个结构才能撑住。 --- ## 9. 错误处理与日志建议 建议统一给这个平台加明确日志前缀: - `[cloudtentacles/crypto]` - `[cloudtentacles/session]` - `[cloudtentacles/http]` 第一版重点记录: 1. 发送验证码是否成功; 2. 登录是否成功; 3. `/user/info` 探活是否成功; 4. 平台返回的 `code/message`; 5. 不记录明文密码、短信验证码、完整 token。 建议在日志和接口返回里都做脱敏: - 手机号只显示部分; - token 只显示前后几位; - password 永不回显。 --- ## 10. 与现有履约架构的关系 当前项目里的履约主链路已经是: 1. 订单进入系统; 2. 根据 `provider/platform/shopId/sku` 命中 `order-fulfillment-bindings.json`; 3. 解析到 `fulfillment_profile`; 4. 创建 `delivery task`; 5. 根据 `executor_key` 决定后续执行方式。 所以 `cloudtentacles` 后续正确的接入位置是: - 第一阶段:只补平台登录能力; - 第二阶段:新增 `cloudtentacles_dispatch` 执行器; - 第三阶段:把某些 SKU 的履约绑定切到这个执行器。 也就是说: - `agiso/khhao` 决定“订单从哪里来” - `cloudtentacles` 决定“订单怎么发出去” --- ## 11. 实施顺序 建议按这个顺序落地: ### 第 1 步:后端基础模块 先实现: - `shared.js` - `crypto-service.js` - `http-client.js` - `session-service.js` - `source-config-service.js` 目标: - 本地可完成发送验证码; - 收到短信后可手动输入验证码登录; - 登录后可拉 `/user/info`。 ### 第 2 步:后台接口 增加: - 配置读取/保存 - 发送验证码 - 登录测试 - token 探活 ### 第 3 步:后台 UI 增加: - 单独的平台配置区 - 发送验证码与登录测试区 - 调试反馈区 ### 第 4 步:后续业务能力 登录能力稳定后,再补: - SKU/分类/背包读取 - 发货动作 - `cloudtentacles_dispatch` 执行器 - 自动发货链路 --- ## 12. 当前阶段结论 这个平台不是新的订单数据源,而是新的**外部履约能力**。 第一版接入重点不是立刻改主流程,而是先把 **可复用的登录能力** 做扎实。 最重要的不是把接口先堆进去,而是先把结构定对: - `khhao` 型平台:验证码图片 + Cookie - `cloudtentacles` 型平台:短信码 + RSA 加密 + token 二者都属于“后台登录型平台”,但在系统分层上不同: - `khhao`:来源层 - `cloudtentacles`:履约层 因此第一版推荐结论是: 1. 作为独立履约平台能力接入; 2. 先做“配置 + 发验证码 + 登录 + 探活”; 3. 目录结构按“配置 / 加密 / HTTP / 会话 / 业务”拆开; 4. 后续通过新的 `executor_key` 接入履约任务执行,而不是改订单来源模型。