Files
junhong_cmp_fiber/docs/7月迭代/七月迭代联调交付说明.md
break 73f5125d3d
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 8m26s
七月迭代短暂完结,还有很多后端的关键东西没有弄,这是一版赶时间做的东西
2026-07-25 17:06:58 +08:00

127 lines
9.0 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.
# 七月迭代联调交付说明
## 交付状态
本说明覆盖 `deliver-july-iteration-confirmed-scope` 的企业微信、Gateway、Redis/Asynq、对象存储和前端联调输入。生产代码、增量迁移和 OpenAPI 已生成至可联调状态;测试库已执行至 `000194` 并完成结构核对尚未执行自动化测试、完整构建、LSP 或真实外部环境闭环。
接口统一使用 `{code,msg,data,timestamp}` 响应。完整请求和响应结构以 `docs/admin-openapi.yaml` 为准。
## 企业微信联调
### 环境和管理配置
| 配置 | 来源 | 说明 |
| --- | --- | --- |
| `JUNHONG_WECOM_BASE_URL` | 环境变量 | 默认 `https://qyapi.weixin.qq.com` |
| `JUNHONG_WECOM_TIMEOUT` | 环境变量 | 默认 `10s` |
| `JUNHONG_WECOM_CREDENTIAL_ENCRYPTION_KEY` | 环境变量 | 32 字节随机密钥的 Base64 文本;更换前必须先完成历史凭据重加密 |
| `corp_id``agent_id`、Secret | `POST /api/admin/wecom/applications` | 管理端按明文提交,服务端加密保存;超级管理员读取时返回明文,业务日志不记录 |
| 回调 Token、EncodingAESKey | 同上 | Token 按明文提交EncodingAESKey 固定 43 位 |
| 默认发起人 | `PUT /api/admin/wecom/applications/:id/default-creator` | 必须先同步可见成员,再从当前可见成员中选择 |
| `template_id` 和控件映射 | `PUT /api/admin/wecom/scenes/:business_type` | 模板必须先在企微后台创建,本系统只校验和绑定 |
部署侧还必须在企微管理后台配置:自建应用审批权限、应用可见通讯录范围、调用接口的可信 IP以及公开可访问的回调地址
```text
GET/POST {API_PUBLIC_BASE_URL}/api/callback/wecom/approval/{application_id}
```
### 配置和联调顺序
1. 配置加密 Key部署 API 和 Worker。
2. 创建应用配置并调用 `POST /api/admin/wecom/applications/:id/test` 验证取 token。
3. 调用 `POST /api/admin/wecom/applications/:id/members/sync`,再分页查询成员。
4. 为内部系统账号调用 `PUT /api/admin/accounts/:id/wecom-binding` 绑定 `(corp_id,userid)`
5. 选择一个当前可见成员作为默认发起人。代理退款、代理相关业务以及未绑定内部员工均使用该成员发起,但本地业务单仍保存真实提交人。
6. 分别配置 `refund_approval``offline_recharge_approval``template_id` 和控件映射。选择控件必须填写企微模板真实 option key。
7. 在企微后台配置回调 URL、Token、EncodingAESKey完成 GET 校验。
8. 分别提交一笔退款和员工线下代充值,验证 `applyevent``sp_no`、回调、详情同步、标准终态和业务终态。
Integration Log 不记录 Secret、access_token、media_id、附件正文或完整企微响应普通业务字段和业务快照按明文保存便于业务处理。
### 结果未知和旧入口
- `applyevent` 超时或断连后标记为结果未知不自动创建第二张审批单Worker 通过时间窗单号和详情查询恢复。
- `wecom:approval:recovery` 每 2 分钟触发,详情同步使用 `wecom:approval:sync`
- 在真实退款和线下代充值闭环、存量 provider 清单均验证前,保持 `JUNHONG_APPROVAL_LEGACY_REFUND_MANUAL_ENABLED=true``JUNHONG_APPROVAL_LEGACY_OFFLINE_RECHARGE_PAY_ENABLED=true`
- 切换后前端只读展示 `approval_provider``approval_status``approval_status_name`,不得再提供企微记录的本地人工通过、驳回或线下确认按钮。
## Gateway 卡限速联调
| 环境变量 | 说明 |
| --- | --- |
| `JUNHONG_GATEWAY_BASE_URL` | Gateway API 基础地址 |
| `JUNHONG_GATEWAY_APP_ID` | Gateway 应用 ID |
| `JUNHONG_GATEWAY_APP_SECRET` | Gateway 应用密钥 |
| `JUNHONG_GATEWAY_TIMEOUT` | 超时秒数,允许 5300默认配置为 60 |
接口固定为:
```text
PUT /api/admin/iot-cards/:iccid/speed-tier
```
请求只允许 `code=-1..8`Gateway 业务参数只有卡 ICCID 对应的 `cardNo` 和档位 `code`。设备没有限速接口,也不得通过设备绑定关系间接限速。
联调需覆盖全部档位、越权卡、明确失败和超时。超时返回结果未知时,按 Integration Log 中的 ICCID 到 Gateway 运维侧核对当前档位,再决定是否人工重试;系统不会盲目自动重发。
## Redis、Asynq 和 Worker
API 与 Worker 必须连接同一 Redis/Asynq。新增或复用的任务如下
| 任务类型 | 队列 | 用途 |
| --- | --- | --- |
| `wecom:approval:sync` | `wecom:approval` | 拉取企微详情并同步标准决策 |
| `wecom:approval:recovery` | `wecom:approval` | 结果未知恢复和未终态轮询 |
| `asset:package:batch_order` | 同名独立队列 | 单列 CSV 批量订购 |
| `device:import` | 同名独立队列 | 原设备导入和设备 CSV 批量分配共用任务外壳,通过 `operation_type` 分支 |
| `package:expiry:reminder` | `data:cleanup` | 每日 15/7/3 天套餐临期提醒 |
| `export:dispatch/shard/finalize` | 各自既有队列 | 六类新增 datasource 继续复用导出流水线 |
联调时确认 Worker 启动日志已注册上述 Handler`JUNHONG_WORKER_ROLE` 的部署拓扑为单实例 `all`,或严格一个 `leader` 加多个 `consumer`
## 对象存储和 CSV
先调用 `POST /api/admin/storage/upload-url` 获取预签名地址,再把文件直传对象存储,业务接口只接收返回的 `file_key`
| purpose | 业务 | 文件要求 |
| --- | --- | --- |
| `batch_purchase` | 资产套餐批量订购 | UTF-8 单列 CSV最多 1000 行、10MB |
| `device_batch_allocation` | 设备分配代理或设置套餐系列 | UTF-8 单列 CSV支持 VirtualNo、IMEI、SN最多 1000 行、10MB |
对象存储需配置 `JUNHONG_STORAGE_PROVIDER`、S3 endpoint/region/bucket/access key/secret key、SSL/path style 和预签名有效期。Worker 必须具备下载相同私有对象的权限。
## 前端接口和字段
| 场景 | 前端接入要点 |
| --- | --- |
| 店铺登录限制 | `PUT /api/admin/shops/:id``client_login_disabled`;列表和详情同字段回显,只阻止新登录,不踢出已有 Token |
| 实名策略 | 卡、设备分别调用 `POST /api/admin/iot-cards/batch-update-realname-policy``POST /api/admin/devices/batch-update-realname-policy`;最多 500 条、全成全败 |
| C 端资产初始化 | 使用 `effective_realname_policy``realname_required``realname_status``allowed_payment_methods`,不要在前端重新推断策略 |
| 支付方式配置 | `GET/PUT /api/admin/system-configs` 管理 `c2b.payment.card_allowed_methods``c2b.payment.device_allowed_methods`;至少保留一种 |
| 临期资产 | `GET /api/admin/expiring-assets`,使用数量、高亮和优先标识 |
| 企微配置 | 使用应用、成员同步/选择、默认发起人、账号绑定和场景接口;模板节点和审批人规则仍在企微后台维护 |
| 退款/充值/换货 | 展示 `submitter_id/submitter_name`;退款和充值只读展示企微审批渠道及状态 |
| 订单/退款资产 | 卡展示 ICCID设备优先 VirtualNo、缺失时展示 IMEI订单同时展示 `purchase_role` |
| 批量订购 | 上传 `purpose=batch_purchase`,再调用 `POST /api/admin/asset-package-batch-orders`;任务列表和详情使用统一状态名称 |
| 设备批量分配 | 上传 `purpose=device_batch_allocation`,再调用 `POST /api/admin/devices/import/allocations`;任务查询复用设备导入任务接口并展示 `operation_type/operation_name/target_id/status_name` |
| 业务导出 | `POST /api/admin/export-tasks`;新增场景为 `iot_card``package``agent_wallet_transaction``agent_recharge``refund``exchange` |
| 卡固定限速 | 只在卡页面展示固定档位选择;设备页面不得出现限速入口 |
## 已知限制
- 本系统不创建企微模板、不配置审批节点或审批人规则,也不提供扫码绑定。
- 企微应用只能看到其可见范围内的成员;可见范围或可信 IP 错误会导致连接、绑定或提交失败。
- 卡限速不保存本地当前档位,结果未知必须人工向 Gateway 核对。
- CSV 任务逐行部分成功,不保证整批业务原子性;任务详情是失败和跳过原因的权威展示。
- 店铺登录限制不主动吊销既有 C 端 Token。
- 测试库已完成 `000182``000194` 结构落库和注释核对;其他环境尚未执行迁移,外部系统闭环和前端浏览器验收也未完成。
## 发布和回滚
1. 测试库已执行至 `000194`;其他环境发布时仍须按迁移顺序执行并核对最终版本和表结构。
2. 先部署数据库兼容代码、API 和 Worker保持旧审批入口开启再配置企微应用、模板、回调和默认发起人。
3. 真实审批闭环通过后,先隐藏前端旧按钮,再关闭旧入口配置并重启 API。
4. 回滚时先停止新批量任务和新审批提交,等待已领取任务结束,再回退应用版本。新增表和列暂不删除。
5. 已产生的审批、退款、钱包流水、订单、通知、Outbox、Integration Log、设备分配和限速审计均为业务事实不得清表回滚使用前向修复。