220 lines
6.8 KiB
Markdown
220 lines
6.8 KiB
Markdown
# 架构设计
|
|
|
|
> 本文讲系统结构、职责划分、数据模型、技术难点和开发顺序。具体技术选型见 [技术栈](03-tech-stack.md)。
|
|
|
|
## 一、系统结构
|
|
|
|
```text
|
|
第三方系统
|
|
|
|
|
| HTTPS JSON
|
|
v
|
|
Flask API / middleware
|
|
|
|
|
| 参数校验、鉴权、幂等
|
|
v
|
|
Application service
|
|
|
|
|
| 查询编排 / 上报编排 / 标准业务模型
|
|
v
|
|
Mapper / transformer
|
|
|
|
|
| CHIS 保存请求模型
|
|
v
|
|
CHIS client + auth manager
|
|
|
|
|
| cookies / session cache
|
|
v
|
|
Redis
|
|
|
|
|
v
|
|
基卫 CHIS *.jsonRequest / 登录接口
|
|
```
|
|
|
|
## 二、职责划分
|
|
|
|
**API / view**
|
|
|
|
- 接收第三方请求。
|
|
- 完成第三方鉴权、trace_id、基础参数校验。
|
|
- 调用 application service。
|
|
- 返回统一响应。
|
|
- 不写 CHIS 字段映射和登录细节。
|
|
|
|
**middleware**
|
|
|
|
- 可以负责第三方鉴权、trace_id、请求体大小限制、日志上下文。
|
|
- 不建议每个请求无脑登录 CHIS。
|
|
- 如果做 CHIS 会话准备,也应调用 `ChisSessionManager.ensure_session()`,由 session manager 决定复用或重登。
|
|
|
|
**application service**
|
|
|
|
- 编排单条体检上报流程。
|
|
- 编排 CHIS 只读查询验证流程。
|
|
- 处理幂等查询、业务校验、调用 mapper、调用 CHIS client。
|
|
- 将 CHIS 错误翻译为本项目统一错误。
|
|
|
|
**mapper / transformer**
|
|
|
|
- 将第三方输入转换为内部标准模型。
|
|
- 将内部标准模型转换为 CHIS 请求体。
|
|
- 管理字段默认值、字典映射、日期格式、空值策略。
|
|
- 重点参考 `HealthCheckHtmlForm.js` 中 `getSaveRequest` 和 `saveToServer` 的行为。
|
|
|
|
**CHIS auth manager**
|
|
|
|
- 负责登录 CHIS、获取角色 / 应用 / 会话上下文。
|
|
- 负责查询当前账号信息或等价接口,判断会话是否有效。
|
|
- 负责 Redis 会话缓存、清理和重登。
|
|
- 登录链路参考 `D:\hans\chupd\chis\login_client_v2.py`,但不能原样依赖 Django model/cache。
|
|
- CHIS public key 从 Flask 配置或环境变量读取,不从代码硬编码。
|
|
|
|
**CHIS client**
|
|
|
|
- 封装 `*.jsonRequest` 和其他 CHIS HTTP 请求。
|
|
- 自动携带会话 cookie 和必要 header。
|
|
- 处理超时、重试、登录失效、错误码、日志脱敏。
|
|
- 先用 `getLanderInfo`、`getEncryType`、`getHMNIListOfHTML` 等只读接口验证通道,再接入保存接口。
|
|
|
|
**Redis repository**
|
|
|
|
- 保存 CHIS 会话对象。
|
|
- 保存幂等键和处理结果摘要。
|
|
- 可保存短期锁,避免同一账号并发重登。
|
|
|
|
## 三、建议项目结构
|
|
|
|
```text
|
|
chisup/
|
|
├── app/
|
|
│ ├── __init__.py
|
|
│ ├── api/
|
|
│ │ └── health_check.py
|
|
│ ├── middleware/
|
|
│ ├── services/
|
|
│ │ ├── health_check_query.py
|
|
│ │ └── health_check_submit.py
|
|
│ ├── mappers/
|
|
│ │ └── health_check.py
|
|
│ ├── chis/
|
|
│ │ ├── auth.py
|
|
│ │ ├── client.py
|
|
│ │ ├── crypto.py
|
|
│ │ ├── session_store.py
|
|
│ │ └── errors.py
|
|
│ ├── repositories/
|
|
│ ├── validators/
|
|
│ └── config.py
|
|
├── tests/
|
|
├── docs/
|
|
├── reverse_file/
|
|
├── requirements.txt
|
|
└── README.md
|
|
```
|
|
|
|
## 四、核心数据对象
|
|
|
|
### 4.1 第三方上报请求
|
|
|
|
具体字段待定,建议至少包含:
|
|
|
|
| 字段 | 说明 |
|
|
| --- | --- |
|
|
| `request_id` | 第三方业务流水号,用于幂等 |
|
|
| `account_ref` | CHIS 账号或机构配置引用;不推荐直接传明文密码 |
|
|
| `person.id_card` | 居民身份证号,日志必须脱敏 |
|
|
| `check_date` | 体检日期 |
|
|
| `health_check` | 体检主体数据 |
|
|
| `source` | 第三方来源系统 |
|
|
|
|
### 4.2 Redis CHIS 会话对象
|
|
|
|
建议结构:
|
|
|
|
```json
|
|
{
|
|
"base_url": "CHIS_BASE_URL_ALIAS",
|
|
"uid": "CHIS_USER_ID",
|
|
"role_id": "CHIS_ROLE_ID",
|
|
"manage_unit": "CHIS_MANAGE_UNIT",
|
|
"cookies": {},
|
|
"login_at": "2026-07-04T00:00:00+08:00",
|
|
"expires_at": "2026-07-04T02:00:00+08:00",
|
|
"last_validated_at": "2026-07-04T00:10:00+08:00"
|
|
}
|
|
```
|
|
|
|
不要保存明文密码。确需保存账号凭证时,应使用安全配置或密钥管理,并在文档中明确加密和权限边界。
|
|
|
|
### 4.3 CHIS 体检保存请求
|
|
|
|
从逆向脚本可确认体检保存不是单表直传,至少涉及:
|
|
|
|
- `hcData`
|
|
- 生活方式数据
|
|
- 查体数据
|
|
- 辅助检查数据
|
|
- 健康评价 / 指导数据
|
|
- 用药、住院、非免疫规划接种等列表数据
|
|
|
|
最终字段以真实 CHIS 请求和 schema 验证为准。
|
|
|
|
### 4.4 CHIS 体检详情查询请求
|
|
|
|
已确认 `reverse_file/20260704_query_health_check.har` 中的体检详情查询需要:
|
|
|
|
```json
|
|
{
|
|
"serviceId": "chis.healthCheckService",
|
|
"method": "execute",
|
|
"serviceAction": "getHMNIListOfHTML",
|
|
"schema": "chis.application.hc.schemas.HC_HealthCheck",
|
|
"body": {
|
|
"healthCheck": "体检主键",
|
|
"phrId": "健康档案号",
|
|
"idCard": "身份证号"
|
|
}
|
|
}
|
|
```
|
|
|
|
检查报告信息查询需要:
|
|
|
|
```json
|
|
{
|
|
"serviceId": "chis.healthCheckService",
|
|
"serviceAction": "getCheckInfoDetail",
|
|
"method": "execute",
|
|
"body": {
|
|
"idCard": "身份证号",
|
|
"checkDate": "体检日期"
|
|
}
|
|
}
|
|
```
|
|
|
|
注意:当前资料不能证明“只传 `healthCheck` 就能查详情”。若外部 API 要支持只传体检 id,需要先验证如何由 `healthCheck` 反查 `phrId`、`idCard`、`checkDate`、`empiId`、`createUser`。
|
|
|
|
## 五、关键技术难点
|
|
|
|
| 难点 | 说明 | 应对 |
|
|
| --- | --- | --- |
|
|
| CHIS 登录链路 | 可能涉及公钥、加密、角色、应用、机构上下文 | 等用户提供现有代码后接入,先写 auth 边界 |
|
|
| 会话有效性 | cookie 存在不代表 CHIS 会话仍有效 | 用账号信息查询接口确认,失败则清理缓存并重登 |
|
|
| 只传体检 id 查询详情 | `getHMNIListOfHTML` 还需要 `phrId` 和 `idCard` | 先要求调用方传全参数,后续验证反查链路 |
|
|
| 体检字段转换 | CHIS 前端保存逻辑复杂,数据块多 | 先做最小样例 mapper,逐步补字段测试 |
|
|
| 幂等 | 第三方重试可能导致重复体检记录 | 使用 `source + request_id` 或业务唯一键保存结果 |
|
|
| 隐私与日志 | 涉及身份证号、体检数据、账号凭证 | 统一脱敏,敏感字段禁止落日志 |
|
|
| CHIS 接口变化 | 逆向接口可能因版本变化失效 | client 层集中封装,转换层有测试样例 |
|
|
|
|
## 六、推荐开发顺序
|
|
|
|
1. 初始化 Flask 项目骨架和测试命令。
|
|
2. 接入 CHIS 登录代码,验证能获取有效会话。
|
|
3. 实现账号信息查询 / 会话有效性确认。
|
|
4. 实现 Redis 会话缓存、锁和失效重登。
|
|
5. 实现通用 CHIS `*.jsonRequest` client。
|
|
6. 先跑通体检详情只读查询,验证登录、会话、角色/机构、SM2 加密和错误处理。
|
|
7. 定义第三方体检上报 API 和统一响应。
|
|
8. 实现最小体检 mapper。
|
|
9. 通过通用 CHIS request 提交最小样例。
|
|
10. 补幂等、日志脱敏、错误码和测试。
|