补齐三套环境配置、测试环境部署门禁与 system_config 初始化,并按当前无企微应用的约束将企微凭据改为明文存储。 Constraint: 当前测试环境尚无企微应用及历史企微密文数据 Rejected: 使用启动环境变量加密企微凭据 | 用户明确要求直接明文保存并移除加密密钥 Confidence: high Scope-risk: moderate Directive: 企微真实闭环完成前保持两个旧审批入口开关为 true Tested: gofmt;git diff --check;bash -n;docker compose config;Gitea workflow YAML 解析;OpenAPI 重新生成 Not-tested: go test;常规 go build;LSP;实际数据库迁移;真实测试环境部署;企微真实联调
9.8 KiB
七月迭代联调交付说明
交付状态
本说明覆盖 deliver-july-iteration-confirmed-scope 的企业微信、Gateway、Redis/Asynq、对象存储和前端联调输入。生产代码、增量迁移和 OpenAPI 已生成至可联调状态;仓库迁移已新增至 000196,测试环境下次部署时由 API 启动脚本自动执行,尚未执行自动化测试、完整构建、LSP 或真实外部环境闭环。
接口统一使用 {code,msg,data,timestamp} 响应。完整请求和响应结构以 docs/admin-openapi.yaml 为准。
企业微信联调
环境和管理配置
| 配置 | 来源 | 说明 |
|---|---|---|
JUNHONG_WECOM_BASE_URL |
环境变量 | 默认 https://qyapi.weixin.qq.com |
JUNHONG_WECOM_TIMEOUT |
环境变量 | 默认 10s |
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,以及公开可访问的回调地址:
GET/POST {API_PUBLIC_BASE_URL}/api/callback/wecom/approval/{application_id}
配置和联调顺序
- 部署 API 和 Worker,并确认数据库迁移已执行至最新版本。
- 创建应用配置并调用
POST /api/admin/wecom/applications/:id/test验证取 token。 - 调用
POST /api/admin/wecom/applications/:id/members/sync,再分页查询成员。 - 为内部系统账号调用
PUT /api/admin/accounts/:id/wecom-binding绑定(corp_id,userid)。 - 选择一个当前可见成员作为默认发起人。代理退款、代理相关业务以及未绑定内部员工均使用该成员发起,但本地业务单仍保存真实提交人。
- 分别配置
refund_approval、offline_recharge_approval的template_id和控件映射。选择控件必须填写企微模板真实 option key。 - 在企微后台配置回调 URL、Token、EncodingAESKey,完成 GET 校验。
- 分别提交一笔退款和员工线下代充值,验证
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 |
超时秒数,允许 5~300,默认配置为 60 |
接口固定为:
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。
System Config 初始化
迁移 000195_seed_july_system_config 初始化以下 6 个代码已注册配置;使用 ON CONFLICT DO NOTHING,不会覆盖环境管理员已经保存的值:
carrier_callback.ctcc_realname.enabled=falsecarrier_callback.cmcc_realname.enabled=falsecarrier_callback.cucc_realname.enabled=falsecarrier_callback.cucc_realname_removal.enabled=falsec2b.payment.card_allowed_methods=["wallet","wechat","alipay"]c2b.payment.device_allowed_methods=["wallet","wechat","alipay"]
部署后通过 GET /api/admin/system-configs 核对 6 项均为 registered=true。运营商回调默认关闭,完成对应运营商联调后再逐项开启;支付方式默认全选,可由超级管理员按卡和设备分别调整。
对象存储和 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结构落库和注释核对;000195~000196将在下一次测试环境部署时执行,外部系统闭环和前端浏览器验收尚未完成。
发布和回滚
- 发布目标数据库必须执行至
000196,并核对tb_system_config已出现 6 个七月迭代默认配置、tb_wecom_application已使用明文凭据字段;测试环境由 API 容器启动脚本自动迁移。 - 先部署数据库兼容代码、API 和 Worker,保持旧审批入口开启;再配置企微应用、模板、回调和默认发起人。
- 真实审批闭环通过后,先隐藏前端旧按钮,再关闭旧入口配置并重启 API。
- 回滚时先停止新批量任务和新审批提交,等待已领取任务结束,再回退应用版本。新增表和列暂不删除。
- 已产生的审批、退款、钱包流水、订单、通知、Outbox、Integration Log、设备分配和限速审计均为业务事实,不得清表回滚;使用前向修复。