Files
ccdi/doc/对接流水分析/兰溪-流水分析对接-新版.md
wkc b022ec75b8 fix(lsfx): 修复流水分析对接模块的代码质量问题
1. 修复配置问题
   - 替换app-secret占位符为正确的密钥dXj6eHRmPv

2. 添加异常处理
   - HttpUtil所有方法添加完整的异常处理
   - 统一使用LsfxApiException包装异常
   - 检查HTTP状态码和响应体

3. 添加日志记录
   - Client所有方法添加详细的日志记录
   - 记录请求参数、响应结果、耗时
   - 异常情况记录错误日志

4. 完善参数校验
   - 接口1:添加6个必填字段校验
   - 接口2:添加groupId和文件校验,限制文件大小10MB
   - 接口3:添加7个参数校验和日期范围校验
   - 接口4:添加groupId和inprogressList校验

5. 性能优化
   - RestTemplate使用Apache HttpClient连接池
   - 最大连接数100,每个路由最大20个连接
   - 支持连接复用,提升性能

6. 代码审查文档
   - 添加详细的代码审查报告
   - 记录发现的问题和改进建议

修改的文件:
- ccdi-lsfx/pom.xml
- ccdi-lsfx/src/main/java/com/ruoyi/lsfx/client/LsfxAnalysisClient.java
- ccdi-lsfx/src/main/java/com/ruoyi/lsfx/config/RestTemplateConfig.java
- ccdi-lsfx/src/main/java/com/ruoyi/lsfx/controller/LsfxTestController.java
- ccdi-lsfx/src/main/java/com/ruoyi/lsfx/util/HttpUtil.java
- ruoyi-admin/src/main/resources/application-dev.yml
- doc/implementation/lsfx-code-review-20260302.md
2026-03-03 09:35:27 +08:00

549 lines
20 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.
# 兰溪-流水分析对接文档
## 接口说明
**生产环境IP**: `64.202.32.176`
### 接口调用流程
1. 初始化调用 `/account/common/getToken` 接口创建项目(必填参数按要求输入,选填参数可忽略)
2. 调用 `/watson/api/project/remoteUploadSplitFile` 接口上传文件,或者拉取行内流水 `/watson/api/project/getJZFileOrZjrcuFile`
3. 调用 `/watson/api/project/upload/getpendings` 获取文件解析的状态
- 文件上传后有个解析过程,需要观察该接口返回的 `parsing` 是否为 `false`
- 如果为 `true`可间隔1s轮询调用此接口直到 `parsing``false`
- 获取 `status` 的值,如果不为 `-5`,提示用户解析失败
4. 如果流水文件解析失败,可以调用 `/watson/api/project/batchDeleteUploadFile` 接口删除流水文件
5. 流水解析成功后,调用 `/watson/api/project/upload/getBankStatement` 接口将对应的流水明细存储到兰溪本地
---
## 1. 新建项目并获取token
### 1.1 接口请求地址
- **测试环境**: `http://158.234.196.5:82/c4c3/account/common/getToken`
- **请求方法**: `POST`
### 1.2 请求参数说明
**接口备注**: 第三方系统中点击需要查看的项目向见知现金流尽调系统请求访问token每个项目的token不同。现金流尽调系统根据 ProjectNo 为唯一标识查找项目如果对应的项目不存在则自动创建项目。注意token使用一次后即失效再次访问项目需要重新申请。支持拉取金综和行内流水
**请求体参数说明**:
| 参数名 | 示例值 | 参数类型 | 是否必填 | 参数描述 |
|--------|--------|----------|----------|----------|
| projectNo | 902000_当前时间戳 | String | 是 | 项目编号格式902000_当前时间戳 |
| entityName | 902000_202603021400 | String | 是 | 项目名称 |
| userId | 902001 | String | 是 | 操作人员编号,固定值 |
| userName | 902001 | String | 是 | 操作人员姓名,固定值 |
| appId | remote_app | String | 是 | 固定值 |
| appSecretCode | 6ee87a361f29234ad25d7893da9975a9 | String | 是 | 安全码 md5(projectNo + "_" + entityName + "_" + dXj6eHRmPv) |
| role | VIEWER | String | 是 | 固定值 |
| orgCode | 902000 | String | 是 | 行社机构号,固定值 |
| entityId | 123456 | String | 否 | 企业统信码或个人身份证号 |
| xdRelatedPersons | [{"relatedPerson":"上海上水纯净水有限公司","relation":"董事长"}, {"relatedPerson":"于小雪","relation":"股东"}, {"relatedPerson":"深圳市云顶信息技术有限公司","relation":"父子"}] | String | 否 | 信贷关联人信息 |
| jzDataDateId | 0 | String | 否 | 拉取指定日期推送过来的金综链流水为0时标识不需要拉取金综链流水 |
| innerBSStartDateId | 0 | String | 否 | 拉取行内流水开始日期0:不需要拉取行内流水。流水分析系统根据entityId到数仓中查询行内流水 |
| innerBSEndDateId | 0 | String | 否 | 拉取行内流水结束日期0:不需要拉取行内流水。流水分析系统根据entityId到数仓中查询行内流水 |
| analysisType | -1 | String | 是 | 固定值 |
| departmentCode | 902000 | String | 是 | 客户经理所属营业部/分理处的机构编码,固定值 |
### 1.3 返回参数说明
**成功响应 (200)**:
| 参数名 | 示例值 | 参数类型 | 参数描述 |
|--------|--------|----------|----------|
| code | 200 | String | 返回码: 200 请求成功; 请求失败: 40100 未知异常, 40101 appId错误, 40102 appSecretCode错误, 40104 可使用项目次数为0无法创建项目, 40105 只读模式下无法新建项目, 40106 错误的分析类型不在规定的取值范围内, 40107 当前系统不支持的分析类型, 40108 当前用户所属行社无权限 |
| data | - | Object | 返回数据 |
| data.token | eyJ0eXAi... | String | token |
| data.projectId | 77 | Integer | 见知项目Id |
| data.projectNo | test-zjnx-1204 | String | 项目编号 |
| data.entityName | 浙江农信test1204 | String | 项目名称 |
| data.analysisType | 0 | Integer | 分析类型 |
| message | create.token.success | String | 返回消息 |
| status | 200 | String | 状态 |
| successResponse | true | Boolean | 是否成功响应 |
### 1.4 返回示例
**成功响应 (200)**:
```json
{
"code": "200",
"data": {
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwcm9qZWN0Tm8iOiJ0ZXN0LXpqbngtMTIwNCIsInJvbGUiOiJWSUVXRVIiLCJlbnRpdHlOYW1lIjoi5rWZ5rGf5Yac5L-hdGVzdDEyMDQiLCJ1c2VyTmFtZSI6Iua1i-ivlTAwMSIsImV4cCI6MTcwMTY3ODEyMSwicHJvamVjdElkIjo3NywidXNlcklkIjoidGVzdDAwMSJ9.UMloP6vB1dayQglVdVcpC9w01kv8kyodKDYfPOC7Hac",
"projectId": 77,
"projectNo": "test-zjnx-1204",
"entityName": "浙江农信test1204",
"analysisType": 0
},
"message": "create.token.success",
"status": "200",
"successResponse": true
}
```
---
## 2. 上传文件接口
### 2.1 接口请求地址
- **测试环境**: `158.234.196.5:82/c4c3/watson/api/project/remoteUploadSplitFile`
- **请求头**: `X-Xencio-Client-Id: 26e5b9239853436b85c623f4b7a6d0e6`
- **请求方法**: `POST`
### 2.2 请求参数说明
| 参数 | 类型 | 参数名称 | 是否必填 | 说明 |
|------|------|----------|----------|------|
| groupId | Int | 项目id | 是 | - |
| files | File | 上传的文件 | 是 | - |
### 2.3 响应结果信息
**注意**: `status` 等于 `-5``uploadStatusDesc` 等于 `data.wait.confirm.newaccount` 表示当前流水文件上传后解析成功。反之则没有成功。
| 序号 | 字段 | 类型 | 备注 |
|------|------|------|------|
| - | code | String | 200成功 其他状态码失败 |
| - | data | Object | 列表 |
| - | accountName | - | 主体名称 |
| - | accountNo | - | 账号 |
| - | uploadFileName | - | 文件名称 |
| - | fileSize | - | 文件大小单位Byte |
| - | status | - | 状态值 |
| - | uploadStatusDesc | - | 文件状态描述 |
| - | bank | - | 所属银行 |
| - | currency | - | 币种 |
| - | accountId | - | 账号id |
| - | logId | - | 文件id |
### 2.4 参数请求样例
*暂未提供*
### 2.5 结果集合样例
**注意**: 结果集合样例不为测试案例结果,具体测试案例结果由具体的参数案例返回为具体值。
**成功响应**:
```json
{
"code": "200",
"data": {
"accountsOfLog": {
"13976": [
{
"bank": "BSX",
"accountName": "",
"accountNo": "虞海良绍兴银行流水",
"currency": "CNY"
}
]
},
"uploadLogList": [
{
"accountNoList": [],
"bankName": "BSX",
"dataTypeInfo": [
"CSV",
","
],
"downloadFileName": "虞海良绍兴银行流水.csv",
"enterpriseNameList": [],
"filePackageId": "14b13103010e4d32b5406c764cfe3644",
"fileSize": 46724,
"fileUploadBy": 448,
"fileUploadByUserName": "admin@support.com",
"fileUploadTime": "2025-03-12 18:53:29",
"leId": 10724,
"logId": 13976,
"logMeta": "{\"lostHeader\":[],\"balanceAmount\":true}",
"logType": "bankstatement",
"loginLeId": 10724,
"realBankName": "BSX",
"rows": 0,
"source": "http",
"status": -5,
"templateName": "BSX_T240925",
"totalRecords": 280,
"trxDateEndId": 20240905,
"trxDateStartId": 20230914,
"uploadFileName": "虞海良绍兴银行流水.csv",
"uploadStatusDesc": "data.wait.confirm.newaccount"
}
],
"uploadStatus": 1
},
"status": "200",
"successResponse": true
}
```
---
## 3. 拉取行内流水的接口
### 3.1 接口请求地址
- **测试环境**: `158.234.196.5:82/c4c3/watson/api/project/getJZFileOrZjrcuFile`
- **请求头**: `X-Xencio-Client-Id: 26e5b9239853436b85c623f4b7a6d0e6`
- **请求方法**: `POST`
### 3.2 请求参数说明
| 参数 | 类型 | 参数名称 | 是否必填 | 说明 |
|------|------|----------|----------|------|
| groupId | Int | 项目id | 是 | - |
| customerNo | String | 客户身份证号 | 是 | - |
| dataChannelCode | String | 校验码 | 是 | ZJRCU |
| requestDateId | Int | 发起请求的时间 | 是 | 当天请求时间 |
| dataStartDateId | Int | 拉取开始日期 | 是 | - |
| dataEndDateId | Int | 拉取结束日期 | 是 | - |
| uploadUserId | int | 柜员号 | 是 | - |
### 3.3 响应结果信息
| 序号 | 字段 | 类型 | 备注 |
|------|------|------|------|
| 1 | code | String | 200成功 其他状态码失败 |
| 2 | data | Object | 列表 |
### 3.4 参数请求样例
拉取行内流水
*暂未提供*
### 3.5 结果集合样例
**注意**: 结果集合样例不为测试案例结果,具体测试案例结果由具体的参数案例返回为具体值。
**行内流水失败**:
```json
{
"code": "200",
"data": {
"code": "501014",
"message": "无行内流水文件"
},
"status": "200",
"successResponse": true
}
```
---
## 4. 判断文件是否解析结束
### 4.1 接口请求地址
- **测试环境**: `http://158.234.196.5:82/c4c3/watson/api/project/upload/getpendings`
- **请求头**: `X-Xencio-Client-Id: c2017e8d105c435a96f86373635b6a09`
- **请求方法**: `POST`
### 4.2 请求参数说明
| 参数 | 类型 | 参数名称 | 是否必填 | 说明 |
|------|------|----------|----------|------|
| groupId | Int | 项目id | 是 | - |
| inprogressList | String | 文件id | 是 | - |
### 4.3 响应结果信息
**注意**: 文件解析有个处理过程,`parsing``false` 表示解析结束,可以轮询调用此接口。`status` 等于 `-5``uploadStatusDesc` 等于 `data.wait.confirm.newaccount` 表示文件解析成功。反之则没有成功。
| 序号 | 字段 | 类型 | 备注 |
|------|------|------|------|
| 1 | code | String | 200成功 其他状态码失败 |
| 2 | data | Object | 列表 |
| 3 | uploadFileName | - | 上传文件名称 |
| 4 | status | - | 文件解析后状态值 |
| 5 | uploadStatusDesc | - | 文件解析后状态描述 |
| 6 | parsing | - | 文件解析状态true表示解析中false表示解析结束 |
### 4.4 参数请求样例
*暂未提供*
### 4.5 结果集合样例
**注意**: 结果集合样例不为测试案例结果,具体测试案例结果由具体的参数案例返回为具体值。
**成功响应**:
```json
{
"code": "200",
"data": {
"parsing": false,
"pendingList": [
{
"accountNoList": [],
"bankName": "ZJRCU",
"dataTypeInfo": [
"CSV",
","
],
"downloadFileName": "230902199012261247_20260201_20260201_1772096608615.csv",
"enterpriseNameList": [],
"filePackageId": "cde6c7cf5cab48e8892f0c1c36b2aa7d",
"fileSize": 53101,
"fileUploadBy": 448,
"fileUploadByUserName": "admin@support.com",
"fileUploadTime": "2026-02-27 09:50:18",
"isSplit": 0,
"leId": 16210,
"logId": 19116,
"logMeta": "{\"lostHeader\":[],\"balanceAmount\":true}",
"logType": "bankstatement",
"loginLeId": 16210,
"lostHeader": [],
"realBankName": "ZJRCU",
"rows": 0,
"source": "http",
"status": -5,
"templateName": "ZJRCU_T251114",
"totalRecords": 131,
"trxDateEndId": 20240228,
"trxDateStartId": 20240201,
"uploadFileName": "230902199012261247_20260201_20260201_1772096608615.csv",
"uploadStatusDesc": "data.wait.confirm.newaccount"
}
]
},
"status": "200",
"successResponse": true
}
```
---
## 6. 获取流水列表并存储到兰溪本地
### 6.1 接口请求地址
- **测试环境**: `158.234.196.5:82/c4c3/watson/api/project/getBSByLogId`
- **请求头**: `X-Xencio-Client-Id: 26e5b9239853436b85c623f4b7a6d0e6`
- **请求方法**: `POST`
### 6.2 请求参数说明
| 参数 | 类型 | 参数名称 | 是否必填 | 说明 |
|------|------|----------|----------|------|
| groupId | Int | 项目id | 是 | - |
| logId | Int | 文件id | 是 | - |
| pageNow | Int | 当前页码 | 是 | - |
| pageSize | Int | 查询条数 | 是 | - |
### 6.3 响应结果信息
| 序号 | 字段 | 类型 | 备注 |
|------|------|------|------|
| 1 | code | String | 200成功 其他状态码失败 |
| 2 | data | Object | 列表 |
| 3 | bankStatementList | - | 流水列表 |
| 4 | totalCount | - | 总条数 |
### 6.4 参数请求样例
*暂未提供*
### 6.5 结果集合样例
**注意**: 结果集合样例不为测试案例结果,具体测试案例结果由具体的参数案例返回为具体值。
**成功响应**:
```json
{
"code": "200",
"data": {
"bankStatementList": [
{
"accountId": 0,
"accountMaskNo": "101015251071645",
"accountingDate": "2024-02-01",
"accountingDateId": 20240201,
"archivingFlag": 0,
"attachments": 0,
"balanceAmount": 4814.82,
"bank": "ZJRCU",
"bankComments": "",
"bankStatementId": 12847662,
"bankTrxNumber": "1a10458dd5c3366d7272285812d434fc",
"batchId": 19135,
"cashType": "1",
"commentsNum": 0,
"crAmount": 0,
"cretNo": "230902199012261247",
"currency": "CNY",
"customerAccountMaskNo": "597671502",
"customerBank": "",
"customerId": -1,
"customerName": "小店",
"customerReference": "",
"downPaymentFlag": 0,
"drAmount": 245.8,
"exceptionType": "",
"groupId": 16238,
"internalFlag": 0,
"leId": 16308,
"leName": "张传伟",
"overrideBsId": 0,
"paymentMethod": "",
"sourceCatalogId": 0,
"split": 0,
"subBankstatementId": 0,
"toDoFlag": 0,
"transAmount": 245.8,
"transFlag": "P",
"transTypeId": 0,
"transformAmount": 0,
"transformCrAmount": 0,
"transformDrAmount": 0,
"transfromBalanceAmount": 0,
"trxBalance": 0,
"trxDate": "2024-02-01 10:33:44",
"userMemo": "财付通消费_小店"
}
],
"totalCount": 131
},
"status": "200",
"successResponse": true
}
```
---
## 7. 兰溪存储的流水表表结构
### 7.1 表结构定义
```sql
CREATE TABLE `c4c_bank_statement_stg` (
`bank_statement_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
`LE_ID` int(10) unsigned DEFAULT '0' COMMENT '企业ID',
`ACCOUNT_ID` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '账号ID',
`LE_ACCOUNT_NAME` varchar(240) DEFAULT 'NONE' COMMENT '企业账号名称',
`LE_ACCOUNT_NO` varchar(240) DEFAULT NULL COMMENT '企业银行账号',
`ACCOUNTING_DATE_ID` int(11) DEFAULT NULL COMMENT '账号日期ID',
`ACCOUNTING_DATE` varchar(10) DEFAULT '0000-00-00' COMMENT '账号日期',
`TRX_DATE` varchar(20) NOT NULL COMMENT '交易日期',
`CURRENCY` varchar(10) DEFAULT NULL COMMENT '币种',
`AMOUNT_DR` decimal(19,2) NOT NULL DEFAULT '0.00' COMMENT '付款金额',
`AMOUNT_CR` decimal(19,2) NOT NULL DEFAULT '0.00' COMMENT '收款金额',
`AMOUNT_BALANCE` decimal(19,2) NOT NULL COMMENT '余额',
`CASH_TYPE` varchar(500) DEFAULT NULL COMMENT '交易类型',
`CUSTOMER_LE_ID` int(11) DEFAULT '-1' COMMENT '对手方企业ID',
`CUSTOMER_ACCOUNT_NAME` varchar(240) DEFAULT NULL COMMENT '对手方企业名称',
`CUSTOMER_ACCOUNT_NO` varchar(240) DEFAULT NULL COMMENT '对手方账号',
`customer_bank` varchar(300) DEFAULT NULL COMMENT '对手方银行',
`customer_reference` varchar(500) DEFAULT NULL COMMENT '对手方备注',
`USER_MEMO` varchar(1000) DEFAULT NULL COMMENT '用户交易摘要',
`BANK_COMMENTS` varchar(240) DEFAULT NULL COMMENT '银行交易摘要',
`BANK_TRX_NUMBER` varchar(240) DEFAULT NULL COMMENT '银行交易号',
`BANK` varchar(250) NOT NULL DEFAULT '' COMMENT '所属银行缩写',
`TRX_FLAG` varchar(2) DEFAULT '0' COMMENT '交易标志位',
`TRX_TYPE` int(11) NOT NULL DEFAULT '0' COMMENT '分类ID',
`EXCEPTION_TYPE` varchar(50) NOT NULL DEFAULT '' COMMENT '异常类型',
`internal_flag` tinyint(1) DEFAULT '0' COMMENT '是否为内部交易1 是 0 否',
`batch_id` int(11) NOT NULL DEFAULT '0' COMMENT '上传logId对应upload_log',
`batch_sequence` int(11) NOT NULL COMMENT '每次上传在文件中的line',
`CREATE_DATE` datetime DEFAULT NULL COMMENT '创建时间',
`created_by` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '创建者',
`meta_json` text COMMENT 'meta json',
`no_balance` tinyint(1) DEFAULT '0' COMMENT '是否包含余额',
`begin_balance` tinyint(1) DEFAULT '0' COMMENT '初始余额',
`end_balance` tinyint(1) DEFAULT '0' COMMENT '结束余额',
`group_id` int(11) DEFAULT '0' COMMENT '项目id',
`override_bs_id` bigint(20) DEFAULT '0' COMMENT '=0表示该数据未覆盖主表,>0表示覆盖主表,<0表示被主表覆盖',
`payment_method` varchar(500) DEFAULT NULL COMMENT '微信、支付宝流水字段,交易方式',
PRIMARY KEY (`bank_statement_id`),
KEY `idx_batch_id_account` (`batch_id`,`LE_ACCOUNT_NO`,`ACCOUNTING_DATE_ID`),
KEY `GROUP_ID` (`group_id`),
KEY `c4c_bank_statement_stg_batch_id_IDX` (`batch_id`,`LE_ACCOUNT_NO`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='银行流水的中间处理表';
```
### 7.2 字段映射关系
| 接口返回字段 | 数据库字段 | 说明 |
|-------------|-----------|------|
| bankStatementId | bank_statement_id | 流水ID |
| leId | LE_ID | 企业ID |
| accountId | ACCOUNT_ID | 账号ID |
| leName | LE_ACCOUNT_NAME | 企业账号名称 |
| accountMaskNo | LE_ACCOUNT_NO | 企业银行账号 |
| accountingDateId | ACCOUNTING_DATE_ID | 账号日期ID |
| accountingDate | ACCOUNTING_DATE | 账号日期 |
| trxDate | TRX_DATE | 交易日期 |
| currency | CURRENCY | 币种 |
| drAmount | AMOUNT_DR | 付款金额 |
| crAmount | AMOUNT_CR | 收款金额 |
| balanceAmount | AMOUNT_BALANCE | 余额 |
| cashType | CASH_TYPE | 交易类型 |
| customerId | CUSTOMER_LE_ID | 对手方企业ID |
| customerName | CUSTOMER_ACCOUNT_NAME | 对手方企业名称 |
| customerAccountMaskNo | CUSTOMER_ACCOUNT_NO | 对手方账号 |
| customerBank | customer_bank | 对手方银行 |
| customerReference | customer_reference | 对手方备注 |
| userMemo | USER_MEMO | 用户交易摘要 |
| bankComments | BANK_COMMENTS | 银行交易摘要 |
| bankTrxNumber | BANK_TRX_NUMBER | 银行交易号 |
| bank | BANK | 所属银行缩写 |
| transFlag | TRX_FLAG | 交易标志位 |
| transTypeId | TRX_TYPE | 分类ID |
| exceptionType | EXCEPTION_TYPE | 异常类型 |
| internalFlag | internal_flag | 是否为内部交易 |
| batchId | batch_id | 上传logId |
| - | batch_sequence | 每次上传在文件中的line |
| - | CREATE_DATE | 创建时间 |
| - | created_by | 创建者 |
| - | meta_json | meta json |
| - | no_balance | 是否包含余额 |
| - | begin_balance | 初始余额 |
| - | end_balance | 结束余额 |
| groupId | group_id | 项目id |
| overrideBsId | override_bs_id | 覆盖标识 |
| paymentMethod | payment_method | 交易方式 |
---
## 附录
### 常见错误码
| 错误码 | 说明 |
|--------|------|
| 200 | 请求成功 |
| 40100 | 未知异常 |
| 40101 | appId错误 |
| 40102 | appSecretCode错误 |
| 40104 | 可使用项目次数为0无法创建项目 |
| 40105 | 只读模式下无法新建项目 |
| 40106 | 错误的分析类型,不在规定的取值范围内 |
| 40107 | 当前系统不支持的分析类型 |
| 40108 | 当前用户所属行社无权限 |
| 501014 | 无行内流水文件 |
### 文件解析状态说明
| 字段 | 值 | 说明 |
|------|-----|------|
| status | -5 | 文件解析成功 |
| uploadStatusDesc | data.wait.confirm.newaccount | 等待确认新账户 |
| parsing | true | 文件解析中 |
| parsing | false | 文件解析结束 |
---
**文档生成时间**: 2026-03-02
**文档来源**: 兰溪-流水分析对接_new.docx