Files
ccdi/docs/design/2026-03-23-credit-parse-client-design.md

365 lines
12 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.
# 征信解析客户端与接口设计方案
## 1. 背景
本次需求来自以下两份输入材料:
- `assets/征信解析/HTML引擎服务_ 接口设计说明书_1.docx`
- `assets/征信解析/征信解析接口payload.xlsx`
根据说明书,本次目标外部接口为 `POST /xfeature-mngs/conversation/htmlEval`,请求格式为 `multipart/form-data`,核心入参为:
- `model`
- `file`
- `hType`
返回体结构为:
- `message`
- `status_code`
- `payload`
根据 Excel`payload` 当前至少包含以下三个主题域对象:
- `lx_header`
- `lx_debt`
- `lx_publictype`
当前仓库中已有银行流水分析平台的集成代码,集中在 `ccdi-lsfx` 模块;但征信解析服务与流水分析平台不是同一套接口语义和配置边界。本次目标是在不破坏现有 `lsfx` 链路的前提下,新增一套独立的征信解析调用能力,并在 `ccdi-lsfx` 中暴露一个可供联调使用的后端接口。
## 2. 目标
-`ccdi-lsfx` 模块中新增独立的征信解析 `Client`
-`ccdi-lsfx` 模块中新增对外联调接口,用于接收 HTML 文件并调用征信解析服务。
- 征信解析配置与现有 `lsfx` 配置完全隔离,不共用同一配置前缀。
- 配置项使用单一完整 URL不拆分 `base-url``endpoints`
- 外部服务成功响应时,保留 `message``status_code``payload` 的原始语义。
- 控制器仅做最小参数校验,不额外引入项目上传记录、异步任务、状态轮询或结果落库。
## 3. 非目标
- 不接入 `ccdi-project` 现有项目文件上传主链路。
- 不新增征信解析结果落库逻辑。
- 不补充前端页面接入。
- 不把征信解析 `Client` 并入现有 `LsfxAnalysisClient`
- 不将征信解析配置挂到 `lsfx.api.*` 下。
- 不额外设计说明书之外的兜底流程、降级流程或兼容协议。
## 4. 方案对比
### 4.1 方案 A直接扩展现有 `LsfxAnalysisClient`
把征信解析方法直接加到现有 `LsfxAnalysisClient`,并继续使用 `lsfx.api.*` 配置。
优点:
- 改动文件数最少。
缺点:
- 语义上把两套不同外部服务混在同一个 Client 中。
- 配置边界不清晰,后续切换环境容易误改现有流水分析配置。
- 不符合本次“新增 Client并在配置文件里与 lsfx 分开”的要求。
### 4.2 方案 B在 `ccdi-lsfx` 中新增独立 `CreditParseClient`
`ccdi-lsfx` 中新增独立控制器和独立 `Client`,并使用新的配置前缀承载完整 URL。
优点:
- 满足“接口加在 `ccdi-lsfx` 中”的要求。
- 满足“新增 Client在配置文件里与 lsfx 分开”的要求。
- 与现有银行流水分析集成边界清晰,不会污染主链路。
- 仍然复用现有 `HttpUtil`,实现路径最短。
缺点:
- 需要新增少量类和配置项。
### 4.3 方案 C在 `ccdi-project` 中直接暴露业务接口并自行发起调用
`ccdi-project` 新增控制器和 service直接使用 `RestTemplate` 调征信解析平台。
优点:
- 对业务模块看起来更直接。
缺点:
- 与用户已确认的“接口加在 `ccdi-lsfx` 中”不一致。
- 会把外部平台调用能力分散到多个模块。
- 后续复用和维护成本更高。
## 5. 推荐方案
采用方案 B`ccdi-lsfx` 中新增独立 `CreditParseClient`、独立配置和独立联调接口。
推荐原因:
- 与已确认需求完全一致。
- 保持最短路径实现,不引入无关业务改造。
- 外部服务边界清晰,后续如果还要补企业征信或更多解析接口,可以继续沿用这一结构。
## 6. 模块边界与目录设计
本次改动集中在 `ccdi-lsfx` 模块。
建议落点如下:
- `ccdi-lsfx/src/main/java/com/ruoyi/lsfx/controller/CreditParseController.java`
- `ccdi-lsfx/src/main/java/com/ruoyi/lsfx/client/CreditParseClient.java`
- `ccdi-lsfx/src/main/java/com/ruoyi/lsfx/domain/response/CreditParseResponse.java`
- `ccdi-lsfx/src/main/java/com/ruoyi/lsfx/domain/response/CreditParsePayload.java`
- `ruoyi-admin/src/main/resources/application-dev.yml`
- `ruoyi-admin/src/main/resources/application-nas.yml`
职责划分如下:
- `CreditParseController`
- 接收联调方上传的 HTML 文件和可选参数。
- 做最小参数校验。
-`MultipartFile` 转换为临时文件。
- 调用 `CreditParseClient`
- 返回 `AjaxResult`
- `CreditParseClient`
- 读取独立配置中的完整 URL。
- 组装 `multipart/form-data` 参数。
- 调用现有 `HttpUtil.uploadFile(...)`
- 统一记录调用日志和抛出平台调用异常。
- `CreditParseResponse`
- 映射外部接口返回的 `message``status_code``payload`
- `CreditParsePayload`
- 承载 `lx_header``lx_debt``lx_publictype` 三个主题域对象。
## 7. 配置设计
征信解析配置独立于 `lsfx`,使用新的配置前缀。
建议配置结构如下:
```yml
credit-parse:
api:
url: http://64.202.94.120:8081/xfeature-mngs/conversation/htmlEval
```
说明:
- `url` 保存单一完整地址,不拆分为 `base-url``endpoints`
- 不复用 `lsfx.api.connection-timeout``lsfx.api.read-timeout` 等配置项。
- 本次实现优先沿用现有 `RestTemplate` Bean若后续确需独立超时配置再单独扩展专用 HTTP 配置,不在本次设计中预埋。
## 8. 对外接口设计
### 8.1 接口定义
- 方法:`POST`
- 路径:`/lsfx/credit/parse`
- Content-Type`multipart/form-data`
接口放在 `ccdi-lsfx` 模块中,作为征信解析联调入口。
### 8.2 请求参数
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
| ------ | ---- | ---- | ------ | ---- |
| `file` | `MultipartFile` | 是 | 无 | 征信 HTML 文件 |
| `model` | `String` | 否 | `LXCUSTALL` | 主题域编码 |
| `hType` | `String` | 否 | `PERSON` | 报文类型 |
### 8.3 本地校验规则
控制器层只做最小必要校验:
- `file` 不能为空。
- 文件名不能为空。
- 文件后缀必须为 `.html``.htm`
- `model` 为空时补默认值 `LXCUSTALL`
- `hType` 为空时补默认值 `PERSON`
不在控制器层重复实现外部平台业务码校验,不提前限制:
- `model` 是否只能取 `LXCUSTALL`
- `hType` 是否只能取 `PERSON``ENTERPRISE`
上述业务校验结果以外部服务返回的 `status_code` 为准。
### 8.4 返回规则
返回采用若依标准 `AjaxResult` 包装,规则如下:
- 本地参数校验失败:返回 `AjaxResult.error(...)`
- 外部调用成功拿到响应:返回 `AjaxResult.success(responseBody)`
- 网络异常、超时、反序列化异常或其他调用异常:返回 `AjaxResult.error("征信解析调用失败:" + e.getMessage())`
其中 `AjaxResult.data` 中保留外部原始业务语义,例如:
```json
{
"code": 200,
"msg": "操作成功",
"data": {
"message": "成功",
"status_code": "0",
"payload": {
"lx_header": {},
"lx_debt": {},
"lx_publictype": {}
}
}
}
```
这意味着:
- 外部业务失败码如 `ERR_99999``ERR_10002` 仍然作为正常 HTTP 调用结果返回。
- 调用方根据 `data.status_code` 判断业务成功与否。
- 本地接口不对外部业务码做二次翻译,避免语义偏移。
## 9. Client 设计
### 9.1 调用链
调用链固定为:
`CreditParseController` -> `CreditParseClient` -> `HttpUtil.uploadFile(...)` -> 征信解析服务
### 9.2 请求组装
`CreditParseClient` 发送 `multipart/form-data`,参数仅包含:
- `model`
- `file`
- `hType`
不新增说明书之外的扩展字段。
### 9.3 URL 读取
`CreditParseClient` 直接读取:
- `credit-parse.api.url`
不做 URL 拼接。
### 9.4 日志
日志风格保持与 `ccdi-lsfx` 现有习惯一致,至少包含:
- 请求开始:文件名、`model``hType`
- 请求结束:耗时、返回 `status_code`
- 请求失败:错误信息和异常堆栈
### 9.5 异常
`CreditParseClient` 统一抛出 `LsfxApiException` 风格异常,保持 `ccdi-lsfx` 模块内部异常语义一致。
## 10. 响应对象设计
### 10.1 请求 DTO
本次不新增请求 DTO。
原因:
- 控制器直接接收 `MultipartFile file, String model, String hType` 即可。
- `Client` 内部直接构造 `Map<String, Object>` 最短路径实现。
- 纯透传场景下,引入请求 DTO 只会增加样板代码。
### 10.2 响应 DTO
建议新增以下响应对象:
#### `CreditParseResponse`
- `String message`
- `String statusCode`
- `CreditParsePayload payload`
其中 `statusCode` 使用注解映射 JSON 字段 `status_code`
#### `CreditParsePayload`
- `Map<String, Object> lxHeader`
- `Map<String, Object> lxDebt`
- `Map<String, Object> lxPublictype`
其中字段名使用注解映射:
- `lx_header`
- `lx_debt`
- `lx_publictype`
### 10.3 为何不展开成 30+ 强类型字段
本次目标是“添加调用征信解析接口的方法”,不是“建立完整征信指标领域模型”。因此本次不把 Excel 中的 30 余个字段全部定义为强类型 Java 属性,原因如下:
- 当前需求核心是打通调用,不是做复杂业务计算。
- 外部字段后续仍可能调整,强类型化会增加维护成本。
- 三段 `Map<String, Object>` 已足够支撑联调与响应透传。
后续如果业务明确需要对单个字段做服务内计算或落库,再单独收敛更细的领域对象。
## 11. 文件处理设计
由于现有 `HttpUtil.uploadFile(...)` 接收的是 `File` 对象,控制器层需要把上传的 `MultipartFile` 转为临时文件。
处理规则如下:
- 使用系统临时目录创建临时文件。
- 临时文件名保留原始后缀,方便外部服务识别文件类型。
- `Client` 调用结束后,在 `finally` 中删除临时文件。
- 临时文件删除失败只记录日志,不覆盖主流程结果。
该处理仅用于本次同步调用,不沉淀到项目上传目录,不复用 `ccdi-project` 的文件上传记录表。
## 12. 测试设计
本次测试只覆盖后端最小闭环,不扩展到前端。
建议至少覆盖以下场景:
1. 合法 HTML 文件上传,外部服务返回 `status_code = 0`
2. 文件为空,本地接口直接返回参数错误
3. 文件后缀非法,本地接口直接返回参数错误
4. 外部服务不可达或超时,接口返回调用失败信息
5. 外部服务返回业务失败码,例如 `ERR_99999`,本地接口仍然按成功调用返回 `AjaxResult.success(...)`
如果测试过程中需要临时启动后端进程,测试完成后必须主动关闭,避免残留进程占用端口。
## 13. 实施边界确认
本次实施只包含以下内容:
- 新增 `CreditParseClient`
- 新增 `CreditParseController`
- 新增征信解析响应对象
- 新增独立配置项 `credit-parse.api.url`
- 补充后端测试
本次明确不包含:
- `ccdi-project` 主上传链路改造
- 项目上传记录表扩展
- 征信结果落库
- 前端接入
- 额外的兼容性补丁或兜底方案
## 14. 风险与约束
- 外部服务返回结构以说明书和联调实际为准;若实际返回字段名与说明书不一致,需要在实现阶段按真实返回修正映射。
- 本次沿用现有 `RestTemplate` Bean若后续征信解析服务需要独立连接池或独立超时再单独设计不在本次范围内扩展。
- 由于本次不做落库,调用结果仅用于联调和即时查看。
## 15. 预期交付物
- 一份后端设计实现代码,落在 `ccdi-lsfx` 模块
- 一份后端实施计划文档,落在 `docs/plans/backend/`
- 一份前端实施计划文档,落在 `docs/plans/frontend/`,明确本次无前端实施项
- 一份本次改动实施记录文档,落在 `docs/reports/implementation/`
本方案采用“`ccdi-lsfx` 内新增独立征信解析 Client 与联调接口、配置与 `lsfx` 完全隔离”的方式,以最短路径补齐征信解析调用能力,同时保证与现有银行流水分析链路边界清晰,符合当前需求边界。