Files
chis_osi/docs/02-旧项目架构评估.md
ilaandClaude Opus 4.8 3498542b07 docs: 初始化 chis_osi 设计文档与协作规范
- docs/: OSI 接口规范分析、旧项目架构评估、目标架构设计、字段与接口映射、实施路线图
- CLAUDE.md: 协作规则(项目认知、osi/mapping/pipeline 三层技术约束、安全/验证、提交规范)
- .gitignore: 补充项目特定忽略(config.yaml/logs/样本等)
- 随项目留存厂家 OSI 规范源材料(docx/xlsx,内部保密,仅限本私有仓库)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 13:10:17 +08:00

6.3 KiB
Raw Permalink Blame History

02 · 旧项目(chis_upload)架构评估

chis_upload 是通过逆向 Chrome F12 网页接口实现的 PHIS→CHIS 上传工具(Go 1.24)。 本文梳理它的分层与组件,区分「哪些复杂度是被网页逆向逼出来的、新项目应删除」与「哪些工程经验值得保留」。


1. 整体定位与数据流

旧项目本质是一个数据搬运管道:

PHIS(上游公卫系统) --拉取任务--> chis_upload --(模拟网页登录态)--> CHIS 网页后端

它对外暴露一组 HTTP API(/api/health-record/save 等),内部再以网页同款报文调用 CHIS。 另有 worker 模式:轮询 PHIS 拉任务、按 dataType 分流、调用自身 save API 完成投递。


2. 分层与目录职责(摘自其 AGENTS.md 与源码)

目录 职责
config/ viper 读取 config.yaml
util/ SM2 加密、Redis、报告日志(reportlog)、apitrace、日志
chis/ CHIS 调用核心:client/transport/auth/login + 各业务域 save/query + 归一化器/补齐器/身份链/完整度计算
model/ 请求/响应结构体
handler/ 对外 HTTP API 处理函数
middleware/ Cookie 中间件(登录态注入)
router/ 路由注册(每个 save/query 都套 authMW)
worker/ phis_poll_worker、mock_task_worker、幂等存储、批次报告

chis/ 目录尤其庞大(30+ 文件),是复杂度集中地。


3. 复杂度来源分析

3.1 由「网页逆向」逼出来的复杂度 —— 新项目应整体删除

旧项目机制 为什么存在 OSI 下的命运
SM2 加密(util/encrypt.go:EncryptSM2/GenerateLwD/GenerateQueryD/YearLlxKey) 网页登录与查询参数 lw_d/d 用 SM2 公钥加密,按年份还有动态字段名 2026llx ❌ 删除。OSI 用 MD5 头签名
登录流程(chis/login.go、LoginWithRoleHint、identity_chain.go) 网页要先登录拿 Cookie,且要处理多角色选择 ❌ 删除。OSI 无登录
Cookie/会话(middleware/cookie.go、chis/auth.go RedisCookieAuth、validate_cookie.go、util/redis.go cookie 缓存、cookie_ttl 配置) 维持网页登录态、跨请求复用、过期重登 ❌ 删除。OSI 每请求现签,无状态
身份链反查(chis/identity_chain.go:idCard → empiId/phrId/...) 网页保存需要先把身份证换成内部主键链路 ❌ 删除/大幅简化。OSI 直接用 idCard+checkId,phrId 由创建接口回传
Chrome 报文对齐(chrome_payload_compat_enable、各 *_payload_normalizer.go、health_check_enricher.go) 必须把字段补齐成 Chrome F12 抓到的同款形态,否则后端拒绝 ⚠ 转化。不再"对齐网页",而改为"映射到文档契约"——见下
完整度服务端重算(health_record_complete_level.go 37/33 项、health_check_perfection.go 70 项) 逆向得知网页会算 completeLevel/perfection,客户端不可信任传入值,需本地重算 ⚠ 待定。OSI 有显式 isFillShhj,完整度很可能由平台算;需联调确认后决定保留与否
网页拟态请求头(buildCHISCallHeaders:Origin/Referer/X-Requested-With/Host) 让请求看起来像浏览器发的 ❌ 删除。OSI 是正式服务接口,无需伪装
apitrace + 多套快照(util/apitrace.go、phis_snapshot_*,且注释标"兼容保留") 逆向期排障留下的多套追踪 🔁 收敛为一套 report log

量级判断:chis/ 目录约 70%~80% 的代码是为「骗过网页 + 复刻网页隐藏算法」服务的。 OSI 接口让这部分整体失去存在意义。

3.2 值得保留的工程经验 —— 新项目应继承

旧项目机制 价值 新项目去向
分层清晰 + 面向初级维护者(AGENTS.md:可读、不过度抽象、必要中文注释) 团队约定,降低接手成本 ✅ 继承这套协作规范
统一调用入口(chis/client.go Call(ctx, account, path, req, out):拼地址→注入头→传输→反序列化→记日志) 单点收敛传输与可观测 ✅ 演化为 OSI client.Call(ctx, serviceId, body, out)
传输层与代理(transport.go/http_client.go,SOCKS5 支持、超时控制、避免 typed-nil jar panic) 内网穿透/超时是真实运维需求 ✅ 几乎原样保留(去掉 cookiejar)
投递流水线(worker/:任务校验分流、重试分类、幂等去重、熔断、批次报告、跑完自动退出) 这是搬运管道的可靠性核心,与接口形态无关 ✅ 重点保留并升级
重试错误分类(网络/5xx/429/网络型 401 可重试;参数/权限不可重试;退避 2s*attempt) 来之不易的运维经验 ✅ 保留,适配 OSI 返回码(405 超时可重试)
report log + 降级(Redis 优先、不可用降级写本地 JSONL;带 trace_id) 可观测 + 不强依赖 Redis ✅ 保留,Redis 改为完全可选
统一错误体(APIError{error_code,error_message,trace_id}) 上游稳定解析 ✅ 保留
配置驱动 + Redis 启动失败不阻断 联调友好 ✅ 保留

3.3 旧项目的待改进点(新项目顺手修正)

  • 幂等键弱:旧键 account|idCard|dataType|sha1(saveBody),依赖报文哈希,报文微调即视为新任务。OSI 有天然的 checkId,应作为幂等主键。
  • 任务源是 mock 文件:mock_task_worker 读本地 JSON,真实 PHIS 拉取/状态回写一直 TODO(见其 phase9_todo_open_items.md)。新项目应直接把 PHIS 接入做实。
  • 多套追踪并存:apitrace / reportlog / snapshot 三套,注释里自承"兼容保留",应收敛为一套。
  • handler 里大量"从原始 JSON 多路径兜底提取字段"(fillEMPIAndPHRFromContext 等),是历史请求体不规范的补丁。新项目以明确契约杜绝。
  • server 与 worker 杂糅在 main.go(flag 极多)。新项目用子命令拆分。

4. 给新项目的迁移启示(一句话)

把 chis/ 里"对付网页"的 70% 删掉,保留并强化 worker/ 那套"可靠投递"的 30%, 再把删掉的部分替换成一个薄 OSI 客户端和一个厚字段映射层。