# 征信解析 Mock Server 设计方案

## 1. 背景

当前仓库已经有一个基于 FastAPI 的 [lsfx-mock-server](/Users/wkc/Desktop/ccdi/ccdi/lsfx-mock-server)，用于模拟流水分析平台接口。本次新增需求来自以下两份输入材料：

- `assets/征信解析/征信解析接口payload.xlsx`
- `assets/征信解析/HTML引擎服务_ 接口设计说明书_1.docx`

根据说明书，本次目标接口为 `POST /xfeature-mngs/conversation/htmlEval`，请求格式为 `form-data`，核心入参为 `model`、`file`、`hType`，返回结构为 `message`、`status_code`、`payload`。根据 Excel，本次 `payload` 至少覆盖 30 个征信指标字段，分布在 `lx_header`、`lx_debt`、`lx_publictype` 三个主题域对象下。

本次工作目标不是实现真实 HTML 解析能力，而是在现有 Mock 服务中补齐一个“结构正确、返回稳定、便于联调”的征信解析接口。

## 2. 目标

- 在现有 [lsfx-mock-server](/Users/wkc/Desktop/ccdi/ccdi/lsfx-mock-server) 中新增征信解析 Mock 能力。
- 实现说明书中的单一核心接口 `POST /xfeature-mngs/conversation/htmlEval`。
- 支持 `model`、`file`、`hType` 的 `form-data` 请求。
- 成功返回时输出与 Excel 字段定义一致的 `payload` 结构。
- 按 `model + hType + 文件名` 生成稳定随机结果，保证同一请求重复调用结果一致。
- 提供最小调试能力，包括健康检查接口和按参数触发失败码。

## 3. 非目标

- 不解析真实 HTML 内容，不从文件正文抽取字段。
- 不新增说明书之外的业务接口。
- 不为每个字段单独编写硬编码生成逻辑。
- 不引入独立新项目或第二套运行框架。
- 不设计复杂的动态配置平台或可视化管理后台。

## 4. 方案对比

### 4.1 方案 A：最短硬编码

直接在现有路由文件中追加征信接口，并把随机生成逻辑写在单个函数或单个 service 内。

优点：

- 实现最快。

缺点：

- 路由层会掺杂业务规则。
- 后续补错误码、字段规则、样例模板时可维护性差。

### 4.2 方案 B：模块化扩展

在现有 [lsfx-mock-server](/Users/wkc/Desktop/ccdi/ccdi/lsfx-mock-server) 中新增独立的征信解析路由、service 和配置文件，复用当前 FastAPI 应用和启动方式。

优点：

- 保持实现路径最短。
- 复用现有工程基础设施和依赖。
- 征信解析逻辑与现有 LSFX Mock 逻辑隔离，后续扩展清晰。

缺点：

- 需要增加少量模块文件和配置文件。

### 4.3 方案 C：全配置驱动

把 Excel 字段直接转换为运行时元数据，服务根据配置动态生成字段、校验和示例响应。

优点：

- 后续字段调整灵活。

缺点：

- 引入额外抽象，超出本次“最短路径实现”的边界。

## 5. 推荐方案

采用方案 B。

原因如下：

- 与用户确认的边界一致：直接扩展现有工程，不新建独立服务。
- 可以在不影响已有 LSFX Mock 链路的前提下补齐征信解析能力。
- 代码结构清晰，后续如果字段扩充或错误码增加，仍可局部修改。

## 6. 模块边界与目录设计

征信解析能力直接并入现有 [lsfx-mock-server](/Users/wkc/Desktop/ccdi/ccdi/lsfx-mock-server)，但采用独立模块组织，避免与现有银行流水 Mock 逻辑混杂。

建议落点如下：

- `lsfx-mock-server/routers/credit_api.py`
- `lsfx-mock-server/services/credit_payload_service.py`
- `lsfx-mock-server/services/credit_debug_service.py`
- `lsfx-mock-server/config/credit_feature_schema.json`
- `lsfx-mock-server/config/credit_response_examples.json`

职责划分如下：

- `credit_api.py`：负责 HTTP 路由、`form-data` 入参接收、响应结构封装。
- `credit_payload_service.py`：负责稳定随机种子生成、字段分组、payload 生成。
- `credit_debug_service.py`：负责调试标记识别、错误码映射、健康检查响应。
- `credit_feature_schema.json`：记录字段归属、类型、枚举范围等元数据。
- `credit_response_examples.json`：保存成功和失败响应模板，保证结构统一。

## 7. 接口设计

### 7.1 接口定义

- 方法：`POST`
- 路径：`/xfeature-mngs/conversation/htmlEval`
- Content-Type：`multipart/form-data`

### 7.2 请求参数

| 参数名 | 类型 | 必填 | 说明 |
| ------ | ---- | ---- | ---- |
| `model` | `String` | 是 | 查询主题域，当前只接受 `LXCUSTALL` |
| `file` | `File` | 是 | HTML 文件，仅校验上传存在 |
| `hType` | `String` | 是 | 报文类型，只接受 `PERSON` 或 `ENTERPRISE` |

说明：接口说明书的参数表明确 `hType` 当前支持 `PERSON/ENTERPRISE`，但错误码表中 `ERR_10003` 的文案写为“报文类型无效，仅支持JSON/XML”。本设计将该差异视为原始文档歧义，校验逻辑以参数表为准，失败时的返回码与返回信息沿用错误码表定义。

### 7.3 成功响应

成功时统一返回：

```json
{
  "message": "成功",
  "payload": {
    "lx_header": {},
    "lx_debt": {},
    "lx_publictype": {}
  },
  "status_code": "0"
}
```

### 7.4 失败响应

失败时统一返回：

```json
{
  "message": "关键参数缺失，参数名: model",
  "payload": null,
  "status_code": "ERR_99999"
}
```

## 8. Payload 生成设计

### 8.1 生成原则

- 不解析真实 HTML 文件内容。
- 仅基于 `model + hType + 文件名` 计算稳定随机种子。
- 同一组输入每次调用返回相同结果。
- 不同 `model`、`hType` 或文件名组合返回不同结果。

### 8.2 字段分组

根据 Excel，本次最小字段集合如下：

- `lx_header`
  - `query_cert_no`
  - `query_cust_name`
  - `report_time`
- `lx_debt`
  - 房贷、车贷、经营贷、消费贷、其他贷款、非银行、信用卡等余额/金额/状态字段
- `lx_publictype`
  - 民事判决、强制执行、行政处罚的记录数和金额字段

### 8.3 类型规则

为避免 30 个字段写成 30 段硬编码分支，schema 只保留最小类型抽象：

- `string`
- `amount`
- `count`
- `status`

生成规则如下：

- `string`：生成符合业务格式的字符串。
- `amount`：生成非负金额字符串，保留两位小数。
- `count`：生成非负整数。
- `status`：严格从 schema 枚举中选值，当前为 `正常`、`逾期`、`不良`。

### 8.4 头信息字段规则

虽然不解析真实 HTML，头信息字段仍需保证格式可用：

- `query_cert_no`：生成合法格式的证件号码样式字符串。
- `query_cust_name`：生成脱敏风格或常见中文姓名样式字符串。
- `report_time`：生成合法日期字符串，例如 `YYYY-MM-DD`。

## 9. 错误处理设计

错误处理只覆盖说明书已明确的最小集合，不新增自定义协议。

| 场景 | 返回码 | 返回信息 |
| ---- | ------ | -------- |
| 缺少 `model`、`file`、`hType` | `ERR_99999` | `关键参数缺失，参数名: XX` |
| `model` 不为 `LXCUSTALL` | `ERR_10002` | `无效的主题域` |
| `hType` 不为 `PERSON` 或 `ENTERPRISE` | `ERR_10003` | `报文类型无效，仅支持JSON/XML` |
| 调试标记触发无效证件号类错误 | `ERR_10001` | `无效的证件号码` |
| 调试标记触发机构号错误 | `ERR_10004` | `无效机构号或行社号` |
| 调试标记触发权限错误 | `ERR_10005` | `无权限访问` |
| 调试标记触发服务异常 | `ERR_10006` | `尽调报告生成异常：异步事件发送失败` |

调试标记建议复用现有 Mock 服务习惯，通过 `model` 中包含类似 `error_ERR_10001` 的值触发对应错误响应。

## 10. 调试能力设计

本次只提供最小调试能力：

- 提供健康检查接口，例如 `GET /credit/health`。
- 支持通过特定 `model` 值触发失败码。
- 不额外增加复杂调试参数。
- 不支持运行时在线修改字段配置。

这样既能满足联调和测试，又不会偏离主业务接口行为。

## 11. 配置组织设计

Excel 文件只作为需求输入，不作为运行时依赖。服务运行时改为读取项目内的 JSON schema。

`credit_feature_schema.json` 建议字段结构如下：

```json
[
  {
    "domain": "lx_header",
    "field": "query_cert_no",
    "type": "string"
  },
  {
    "domain": "lx_debt",
    "field": "uncle_bank_house_state",
    "type": "status",
    "options": ["正常", "逾期", "不良"]
  }
]
```

这样可以保证：

- 扩充字段时只需要补 schema。
- 生成逻辑聚焦类型，不直接绑定具体字段数量。
- 响应结构仍保持说明书和 Excel 要求。

## 12. 测试与验收设计

测试边界保持最短闭环：

- 单元测试
  - 成功响应结构正确。
  - 同一输入返回稳定随机一致结果。
  - 不同输入返回不同随机结果。
  - 调试标记能返回预期错误码。
- 接口测试
  - `multipart/form-data` 上传可被正确接收。
  - 缺参时返回说明书约定格式。
  - 健康检查接口返回可用状态。

验收重点如下：

- 调用方按说明书格式发起请求时，能拿到合法 JSON 响应。
- `payload` 字段结构与 Excel 保持一致。
- 同一组请求参数重复调用时结果一致。
- 参数异常时返回约定错误码与错误信息。

## 13. 文档与实施计划要求

按仓库约定，设计确认后需要继续产出两份实施计划：

- 后端实施计划：`docs/plans/backend/`
- 前端实施计划：`docs/plans/frontend/`

由于本次主体是 Mock 服务开发，前端计划可聚焦联调接入、调试入口或调用说明，不扩展无关页面开发。

后续进入实现阶段后，还需补充本次改动的实施记录到 `docs/reports/implementation/`。

## 14. 实现落点

预计涉及如下文件范围：

- 新增 `lsfx-mock-server/routers/credit_api.py`
- 新增 `lsfx-mock-server/services/credit_payload_service.py`
- 新增 `lsfx-mock-server/services/credit_debug_service.py`
- 新增 `lsfx-mock-server/config/credit_feature_schema.json`
- 新增 `lsfx-mock-server/config/credit_response_examples.json`
- 按需修改 `lsfx-mock-server/main.py` 或路由注册入口
- 新增对应测试文件

## 15. 结论

本方案采用“在现有 Mock 服务中模块化扩展征信解析能力”的方式，以单接口、稳定随机、最小调试能力为边界完成征信解析 Mock Server 建设。该方案满足当前联调目标，同时避免引入真实 HTML 解析和过度设计，符合最短路径实现要求。
