2026-03-02 10:05:38 +08:00
|
|
|
|
package com.ruoyi.lsfx.client;
|
|
|
|
|
|
|
|
|
|
|
|
import com.ruoyi.lsfx.constants.LsfxConstants;
|
2026-03-03 14:51:46 +08:00
|
|
|
|
import com.ruoyi.lsfx.domain.request.FetchInnerFlowRequest;
|
|
|
|
|
|
import com.ruoyi.lsfx.domain.request.GetBankStatementRequest;
|
|
|
|
|
|
import com.ruoyi.lsfx.domain.request.GetTokenRequest;
|
2026-03-02 10:05:38 +08:00
|
|
|
|
import com.ruoyi.lsfx.domain.response.*;
|
2026-03-03 09:35:27 +08:00
|
|
|
|
import com.ruoyi.lsfx.exception.LsfxApiException;
|
2026-03-02 10:05:38 +08:00
|
|
|
|
import com.ruoyi.lsfx.util.HttpUtil;
|
|
|
|
|
|
import com.ruoyi.lsfx.util.MD5Util;
|
2026-03-03 14:51:46 +08:00
|
|
|
|
import com.ruoyi.lsfx.util.ObjectUtil;
|
|
|
|
|
|
import jakarta.annotation.Resource;
|
2026-03-03 09:35:27 +08:00
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
2026-03-02 10:05:38 +08:00
|
|
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
|
|
|
|
import org.springframework.stereotype.Component;
|
|
|
|
|
|
|
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 流水分析平台客户端
|
|
|
|
|
|
*/
|
2026-03-03 09:35:27 +08:00
|
|
|
|
@Slf4j
|
2026-03-02 10:05:38 +08:00
|
|
|
|
@Component
|
|
|
|
|
|
public class LsfxAnalysisClient {
|
|
|
|
|
|
|
|
|
|
|
|
@Resource
|
|
|
|
|
|
private HttpUtil httpUtil;
|
|
|
|
|
|
|
|
|
|
|
|
@Value("${lsfx.api.base-url}")
|
|
|
|
|
|
private String baseUrl;
|
|
|
|
|
|
|
|
|
|
|
|
@Value("${lsfx.api.app-id}")
|
|
|
|
|
|
private String appId;
|
|
|
|
|
|
|
|
|
|
|
|
@Value("${lsfx.api.app-secret}")
|
|
|
|
|
|
private String appSecret;
|
|
|
|
|
|
|
|
|
|
|
|
@Value("${lsfx.api.client-id}")
|
|
|
|
|
|
private String clientId;
|
|
|
|
|
|
|
2026-03-02 10:48:01 +08:00
|
|
|
|
@Value("${lsfx.api.endpoints.get-token}")
|
|
|
|
|
|
private String getTokenEndpoint;
|
|
|
|
|
|
|
|
|
|
|
|
@Value("${lsfx.api.endpoints.upload-file}")
|
|
|
|
|
|
private String uploadFileEndpoint;
|
|
|
|
|
|
|
|
|
|
|
|
@Value("${lsfx.api.endpoints.fetch-inner-flow}")
|
|
|
|
|
|
private String fetchInnerFlowEndpoint;
|
|
|
|
|
|
|
|
|
|
|
|
@Value("${lsfx.api.endpoints.check-parse-status}")
|
|
|
|
|
|
private String checkParseStatusEndpoint;
|
|
|
|
|
|
|
|
|
|
|
|
@Value("${lsfx.api.endpoints.get-bank-statement}")
|
|
|
|
|
|
private String getBankStatementEndpoint;
|
|
|
|
|
|
|
2026-03-02 10:05:38 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 获取Token
|
|
|
|
|
|
*/
|
|
|
|
|
|
public GetTokenResponse getToken(GetTokenRequest request) {
|
2026-03-03 09:35:27 +08:00
|
|
|
|
log.info("【流水分析】获取Token请求: projectNo={}, entityName={}", request.getProjectNo(), request.getEntityName());
|
|
|
|
|
|
long startTime = System.currentTimeMillis();
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
String secretCode = MD5Util.generateSecretCode(
|
|
|
|
|
|
request.getProjectNo(),
|
|
|
|
|
|
request.getEntityName(),
|
|
|
|
|
|
appSecret
|
|
|
|
|
|
);
|
|
|
|
|
|
|
2026-03-03 14:51:46 +08:00
|
|
|
|
// 构建form-data参数(使用ObjectUtil简化代码)
|
|
|
|
|
|
Map<String, Object> params = ObjectUtil.toMapIgnoreNull(request);
|
|
|
|
|
|
// 添加特殊字段
|
|
|
|
|
|
params.put("appId", appId);
|
|
|
|
|
|
params.put("appSecretCode", secretCode);
|
|
|
|
|
|
params.put("role", request.getRole() != null ? request.getRole() : LsfxConstants.DEFAULT_ROLE);
|
|
|
|
|
|
params.put("analysisType", request.getAnalysisType() != null ? request.getAnalysisType() : LsfxConstants.ANALYSIS_TYPE);
|
2026-03-03 09:35:27 +08:00
|
|
|
|
|
|
|
|
|
|
String url = baseUrl + getTokenEndpoint;
|
2026-03-03 14:51:46 +08:00
|
|
|
|
GetTokenResponse response = httpUtil.postFormData(url, params, null, GetTokenResponse.class);
|
2026-03-03 09:35:27 +08:00
|
|
|
|
|
|
|
|
|
|
long elapsed = System.currentTimeMillis() - startTime;
|
|
|
|
|
|
if (response != null && response.getData() != null) {
|
|
|
|
|
|
log.info("【流水分析】获取Token成功: projectId={}, 耗时={}ms",
|
|
|
|
|
|
response.getData().getProjectId(), elapsed);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
log.warn("【流水分析】获取Token响应异常: 耗时={}ms", elapsed);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return response;
|
|
|
|
|
|
} catch (LsfxApiException e) {
|
|
|
|
|
|
log.error("【流水分析】获取Token失败: projectNo={}, error={}", request.getProjectNo(), e.getMessage(), e);
|
|
|
|
|
|
throw e;
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
log.error("【流水分析】获取Token未知异常: projectNo={}", request.getProjectNo(), e);
|
|
|
|
|
|
throw new LsfxApiException("获取Token失败: " + e.getMessage(), e);
|
2026-03-02 10:05:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 上传文件
|
|
|
|
|
|
*/
|
2026-03-02 10:16:30 +08:00
|
|
|
|
public UploadFileResponse uploadFile(Integer groupId, org.springframework.core.io.Resource file) {
|
2026-03-03 09:35:27 +08:00
|
|
|
|
log.info("【流水分析】上传文件请求: groupId={}, fileName={}", groupId, file.getFilename());
|
|
|
|
|
|
long startTime = System.currentTimeMillis();
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
String url = baseUrl + uploadFileEndpoint;
|
|
|
|
|
|
|
|
|
|
|
|
Map<String, Object> params = new HashMap<>();
|
|
|
|
|
|
params.put("groupId", groupId);
|
|
|
|
|
|
params.put("files", file);
|
|
|
|
|
|
|
|
|
|
|
|
Map<String, String> headers = new HashMap<>();
|
|
|
|
|
|
headers.put(LsfxConstants.HEADER_CLIENT_ID, clientId);
|
|
|
|
|
|
|
|
|
|
|
|
UploadFileResponse response = httpUtil.uploadFile(url, params, headers, UploadFileResponse.class);
|
|
|
|
|
|
|
|
|
|
|
|
long elapsed = System.currentTimeMillis() - startTime;
|
|
|
|
|
|
if (response != null && response.getData() != null) {
|
|
|
|
|
|
log.info("【流水分析】上传文件成功: uploadStatus={}, 耗时={}ms",
|
|
|
|
|
|
response.getData().getUploadStatus(), elapsed);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
log.warn("【流水分析】上传文件响应异常: 耗时={}ms", elapsed);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return response;
|
|
|
|
|
|
} catch (LsfxApiException e) {
|
|
|
|
|
|
log.error("【流水分析】上传文件失败: groupId={}, error={}", groupId, e.getMessage(), e);
|
|
|
|
|
|
throw e;
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
log.error("【流水分析】上传文件未知异常: groupId={}", groupId, e);
|
|
|
|
|
|
throw new LsfxApiException("上传文件失败: " + e.getMessage(), e);
|
|
|
|
|
|
}
|
2026-03-02 10:05:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 拉取行内流水
|
|
|
|
|
|
*/
|
|
|
|
|
|
public FetchInnerFlowResponse fetchInnerFlow(FetchInnerFlowRequest request) {
|
2026-03-03 09:35:27 +08:00
|
|
|
|
log.info("【流水分析】拉取行内流水请求: groupId={}, customerNo={}", request.getGroupId(), request.getCustomerNo());
|
|
|
|
|
|
long startTime = System.currentTimeMillis();
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
String url = baseUrl + fetchInnerFlowEndpoint;
|
|
|
|
|
|
|
2026-03-03 14:51:46 +08:00
|
|
|
|
// 构建form-data参数(使用ObjectUtil简化代码)
|
|
|
|
|
|
Map<String, Object> params = ObjectUtil.toMapIgnoreNull(request);
|
|
|
|
|
|
|
2026-03-03 09:35:27 +08:00
|
|
|
|
Map<String, String> headers = new HashMap<>();
|
|
|
|
|
|
headers.put(LsfxConstants.HEADER_CLIENT_ID, clientId);
|
|
|
|
|
|
|
2026-03-03 14:51:46 +08:00
|
|
|
|
FetchInnerFlowResponse response = httpUtil.postFormData(url, params, headers, FetchInnerFlowResponse.class);
|
2026-03-03 09:35:27 +08:00
|
|
|
|
|
|
|
|
|
|
long elapsed = System.currentTimeMillis() - startTime;
|
|
|
|
|
|
if (response != null && response.getData() != null) {
|
2026-03-03 16:11:03 +08:00
|
|
|
|
log.info("【流水分析】拉取行内流水完成: logId={},耗时={}ms", response.getData(), elapsed);
|
2026-03-03 09:35:27 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
log.warn("【流水分析】拉取行内流水响应异常: 耗时={}ms", elapsed);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return response;
|
|
|
|
|
|
} catch (LsfxApiException e) {
|
|
|
|
|
|
log.error("【流水分析】拉取行内流水失败: groupId={}, error={}", request.getGroupId(), e.getMessage(), e);
|
|
|
|
|
|
throw e;
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
log.error("【流水分析】拉取行内流水未知异常: groupId={}", request.getGroupId(), e);
|
|
|
|
|
|
throw new LsfxApiException("拉取行内流水失败: " + e.getMessage(), e);
|
|
|
|
|
|
}
|
2026-03-02 10:05:38 +08:00
|
|
|
|
}
|
2026-03-02 10:13:31 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 检查文件解析状态
|
|
|
|
|
|
*/
|
|
|
|
|
|
public CheckParseStatusResponse checkParseStatus(Integer groupId, String inprogressList) {
|
2026-03-03 09:35:27 +08:00
|
|
|
|
log.info("【流水分析】检查文件解析状态: groupId={}, inprogressList={}", groupId, inprogressList);
|
|
|
|
|
|
long startTime = System.currentTimeMillis();
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
String url = baseUrl + checkParseStatusEndpoint;
|
|
|
|
|
|
|
2026-03-03 14:51:46 +08:00
|
|
|
|
// 构建form-data参数
|
2026-03-03 09:35:27 +08:00
|
|
|
|
Map<String, Object> params = new HashMap<>();
|
|
|
|
|
|
params.put("groupId", groupId);
|
|
|
|
|
|
params.put("inprogressList", inprogressList);
|
|
|
|
|
|
|
|
|
|
|
|
Map<String, String> headers = new HashMap<>();
|
|
|
|
|
|
headers.put(LsfxConstants.HEADER_CLIENT_ID, clientId);
|
|
|
|
|
|
|
2026-03-03 14:51:46 +08:00
|
|
|
|
CheckParseStatusResponse response = httpUtil.postFormData(url, params, headers, CheckParseStatusResponse.class);
|
2026-03-03 09:35:27 +08:00
|
|
|
|
|
|
|
|
|
|
long elapsed = System.currentTimeMillis() - startTime;
|
|
|
|
|
|
if (response != null && response.getData() != null) {
|
|
|
|
|
|
log.info("【流水分析】检查解析状态完成: parsing={}, pendingList.size={}, 耗时={}ms",
|
|
|
|
|
|
response.getData().getParsing(),
|
|
|
|
|
|
response.getData().getPendingList() != null ? response.getData().getPendingList().size() : 0,
|
|
|
|
|
|
elapsed);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
log.warn("【流水分析】检查解析状态响应异常: 耗时={}ms", elapsed);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return response;
|
|
|
|
|
|
} catch (LsfxApiException e) {
|
|
|
|
|
|
log.error("【流水分析】检查解析状态失败: groupId={}, error={}", groupId, e.getMessage(), e);
|
|
|
|
|
|
throw e;
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
log.error("【流水分析】检查解析状态未知异常: groupId={}", groupId, e);
|
|
|
|
|
|
throw new LsfxApiException("检查解析状态失败: " + e.getMessage(), e);
|
|
|
|
|
|
}
|
2026-03-02 10:13:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2026-03-02 22:09:42 +08:00
|
|
|
|
* 获取银行流水(新版接口)
|
|
|
|
|
|
* 注意: 需要传入logId参数,参数名已从pageNum改为pageNow
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param request 请求参数(groupId, logId, pageNow, pageSize)
|
|
|
|
|
|
* @return 流水明细列表
|
2026-03-02 10:13:31 +08:00
|
|
|
|
*/
|
|
|
|
|
|
public GetBankStatementResponse getBankStatement(GetBankStatementRequest request) {
|
2026-03-03 09:35:27 +08:00
|
|
|
|
log.info("【流水分析】获取银行流水请求: groupId={}, logId={}, pageNow={}, pageSize={}",
|
|
|
|
|
|
request.getGroupId(), request.getLogId(), request.getPageNow(), request.getPageSize());
|
|
|
|
|
|
long startTime = System.currentTimeMillis();
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
String url = baseUrl + getBankStatementEndpoint;
|
|
|
|
|
|
|
2026-03-03 14:51:46 +08:00
|
|
|
|
// 构建form-data参数(使用ObjectUtil简化代码)
|
|
|
|
|
|
Map<String, Object> params = ObjectUtil.toMapIgnoreNull(request);
|
|
|
|
|
|
|
2026-03-03 09:35:27 +08:00
|
|
|
|
Map<String, String> headers = new HashMap<>();
|
|
|
|
|
|
headers.put(LsfxConstants.HEADER_CLIENT_ID, clientId);
|
|
|
|
|
|
|
2026-03-03 14:51:46 +08:00
|
|
|
|
GetBankStatementResponse response = httpUtil.postFormData(url, params, headers, GetBankStatementResponse.class);
|
2026-03-03 09:35:27 +08:00
|
|
|
|
|
|
|
|
|
|
long elapsed = System.currentTimeMillis() - startTime;
|
|
|
|
|
|
if (response != null && response.getData() != null) {
|
|
|
|
|
|
log.info("【流水分析】获取银行流水成功: totalCount={}, 耗时={}ms",
|
|
|
|
|
|
response.getData().getTotalCount(), elapsed);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
log.warn("【流水分析】获取银行流水响应异常: 耗时={}ms", elapsed);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return response;
|
|
|
|
|
|
} catch (LsfxApiException e) {
|
|
|
|
|
|
log.error("【流水分析】获取银行流水失败: groupId={}, logId={}, error={}",
|
|
|
|
|
|
request.getGroupId(), request.getLogId(), e.getMessage(), e);
|
|
|
|
|
|
throw e;
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
log.error("【流水分析】获取银行流水未知异常: groupId={}, logId={}",
|
|
|
|
|
|
request.getGroupId(), request.getLogId(), e);
|
|
|
|
|
|
throw new LsfxApiException("获取银行流水失败: " + e.getMessage(), e);
|
|
|
|
|
|
}
|
2026-03-02 10:13:31 +08:00
|
|
|
|
}
|
2026-03-02 10:05:38 +08:00
|
|
|
|
}
|