Refactor credit parse to use remote HTML paths
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
package com.ruoyi.lsfx.client;
|
||||
|
||||
import com.ruoyi.lsfx.domain.response.CreditParseResponse;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.uuid.IdUtils;
|
||||
import com.ruoyi.lsfx.domain.response.CreditParseInvokeResponse;
|
||||
import com.ruoyi.lsfx.exception.LsfxApiException;
|
||||
import com.ruoyi.lsfx.util.HttpUtil;
|
||||
import jakarta.annotation.Resource;
|
||||
@@ -8,7 +10,6 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -22,26 +23,51 @@ public class CreditParseClient {
|
||||
@Value("${credit-parse.api.url}")
|
||||
private String creditParseUrl;
|
||||
|
||||
public CreditParseResponse parse(String model, String hType, File file) {
|
||||
@Value("${credit-parse.api.org-code:902000}")
|
||||
private String orgCode;
|
||||
|
||||
@Value("${credit-parse.api.run-type:1}")
|
||||
private String runType;
|
||||
|
||||
@Value("${credit-parse.api.model:LXCUSTALL}")
|
||||
private String defaultModel;
|
||||
|
||||
public CreditParseInvokeResponse parse(String remotePath) {
|
||||
return parse(defaultModel, remotePath);
|
||||
}
|
||||
|
||||
public CreditParseInvokeResponse parse(String model, String remotePath) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
log.info("【征信解析】开始调用: fileName={}, model={}, hType={}", file.getName(), model, hType);
|
||||
String actualModel = StringUtils.isBlank(model) ? defaultModel : model;
|
||||
log.info("【征信解析】开始调用: model={}, remotePath={}", actualModel, remotePath);
|
||||
|
||||
try {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("model", model);
|
||||
params.put("hType", hType);
|
||||
params.put("file", file);
|
||||
params.put("serialNum", buildSerialNum());
|
||||
params.put("orgCode", orgCode);
|
||||
params.put("runType", runType);
|
||||
params.put("remotePath", remotePath);
|
||||
params.put("model", actualModel);
|
||||
|
||||
CreditParseResponse response = httpUtil.uploadFile(creditParseUrl, params, null, CreditParseResponse.class);
|
||||
CreditParseInvokeResponse response = httpUtil.postUrlEncodedForm(
|
||||
creditParseUrl, params, null, CreditParseInvokeResponse.class);
|
||||
|
||||
long elapsed = System.currentTimeMillis() - startTime;
|
||||
log.info("【征信解析】调用完成: statusCode={}, cost={}ms",
|
||||
response != null ? response.getStatusCode() : null, elapsed);
|
||||
log.info("【征信解析】调用完成: success={}, code={}, businessStatusCode={}, cost={}ms",
|
||||
response != null ? response.getSuccess() : null,
|
||||
response != null ? response.getCode() : null,
|
||||
response != null && response.getData() != null && response.getData().getMappingOutputFields() != null
|
||||
? response.getData().getMappingOutputFields().getStatusCode() : null,
|
||||
elapsed);
|
||||
return response;
|
||||
} catch (Exception e) {
|
||||
log.error("【征信解析】调用失败: fileName={}, model={}, hType={}, error={}",
|
||||
file.getName(), model, hType, e.getMessage(), e);
|
||||
log.error("【征信解析】调用失败: model={}, remotePath={}, error={}",
|
||||
actualModel, remotePath, e.getMessage(), e);
|
||||
throw new LsfxApiException("征信解析调用失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private String buildSerialNum() {
|
||||
return "CCDI_CREDIT_" + System.currentTimeMillis() + "_" + IdUtils.fastSimpleUUID();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import com.ruoyi.common.annotation.Anonymous;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.lsfx.client.CreditParseClient;
|
||||
import com.ruoyi.lsfx.domain.response.CreditParseResponse;
|
||||
import com.ruoyi.lsfx.domain.response.CreditParseInvokeResponse;
|
||||
import com.ruoyi.lsfx.exception.LsfxApiException;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
@@ -14,13 +14,6 @@ import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
|
||||
@Tag(name = "征信解析接口测试", description = "用于测试征信解析接口")
|
||||
@Anonymous
|
||||
@@ -29,56 +22,27 @@ import java.nio.file.StandardCopyOption;
|
||||
public class CreditParseController {
|
||||
|
||||
private static final String DEFAULT_MODEL = "LXCUSTALL";
|
||||
private static final String DEFAULT_HTYPE = "PERSON";
|
||||
|
||||
@Resource
|
||||
private CreditParseClient creditParseClient;
|
||||
|
||||
@Operation(summary = "解析征信HTML", description = "上传征信HTML文件并调用外部解析服务")
|
||||
@Operation(summary = "解析征信HTML", description = "传入征信HTML远程地址并调用外部解析服务")
|
||||
@PostMapping("/parse")
|
||||
public AjaxResult parse(@Parameter(description = "征信HTML文件") @RequestParam("file") MultipartFile file,
|
||||
@Parameter(description = "解析模型,默认LXCUSTALL") @RequestParam(required = false) String model,
|
||||
@Parameter(description = "主体类型,默认PERSON") @RequestParam(required = false) String hType) {
|
||||
if (file == null || file.isEmpty()) {
|
||||
return AjaxResult.error("征信HTML文件不能为空");
|
||||
}
|
||||
|
||||
String originalFilename = file.getOriginalFilename();
|
||||
if (StringUtils.isBlank(originalFilename)) {
|
||||
return AjaxResult.error("文件名不能为空");
|
||||
}
|
||||
|
||||
String lowerCaseName = originalFilename.toLowerCase();
|
||||
if (!lowerCaseName.endsWith(".html") && !lowerCaseName.endsWith(".htm")) {
|
||||
return AjaxResult.error("仅支持 HTML 格式文件");
|
||||
public AjaxResult parse(@Parameter(description = "征信HTML远程访问地址") @RequestParam("remotePath") String remotePath,
|
||||
@Parameter(description = "模型编码,默认LXCUSTALL") @RequestParam(required = false) String model) {
|
||||
if (StringUtils.isBlank(remotePath)) {
|
||||
return AjaxResult.error("征信HTML远程地址不能为空");
|
||||
}
|
||||
|
||||
String actualModel = StringUtils.isBlank(model) ? DEFAULT_MODEL : model;
|
||||
String actualHType = StringUtils.isBlank(hType) ? DEFAULT_HTYPE : hType;
|
||||
|
||||
Path tempFile = null;
|
||||
try {
|
||||
String suffix = lowerCaseName.endsWith(".htm") ? ".htm" : ".html";
|
||||
tempFile = Files.createTempFile("credit_parse_", suffix);
|
||||
Files.copy(file.getInputStream(), tempFile, StandardCopyOption.REPLACE_EXISTING);
|
||||
|
||||
File convertedFile = tempFile.toFile();
|
||||
CreditParseResponse response = creditParseClient.parse(actualModel, actualHType, convertedFile);
|
||||
CreditParseInvokeResponse response = creditParseClient.parse(actualModel, remotePath);
|
||||
return AjaxResult.success(response);
|
||||
} catch (LsfxApiException e) {
|
||||
return AjaxResult.error(e.getMessage());
|
||||
} catch (IOException e) {
|
||||
return AjaxResult.error("文件转换失败:" + e.getMessage());
|
||||
} catch (Exception e) {
|
||||
return AjaxResult.error("征信解析失败:" + e.getMessage());
|
||||
} finally {
|
||||
if (tempFile != null) {
|
||||
try {
|
||||
Files.deleteIfExists(tempFile);
|
||||
} catch (IOException ignored) {
|
||||
// 忽略临时文件删除失败,避免影响主流程返回
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.ruoyi.lsfx.domain.response;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class CreditParseInvokeData {
|
||||
|
||||
private CreditParseResponse mappingOutputFields;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.ruoyi.lsfx.domain.response;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class CreditParseInvokeResponse {
|
||||
|
||||
private Boolean success;
|
||||
|
||||
private Integer code;
|
||||
|
||||
private CreditParseInvokeData data;
|
||||
}
|
||||
@@ -206,6 +206,47 @@ public class HttpUtil {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送POST请求(application/x-www-form-urlencoded格式,带请求头)
|
||||
* @param url 请求URL
|
||||
* @param params 表单参数
|
||||
* @param headers 请求头
|
||||
* @param responseType 响应类型
|
||||
* @return 响应对象
|
||||
*/
|
||||
public <T> T postUrlEncodedForm(String url, Map<String, Object> params, Map<String, String> headers, Class<T> responseType) {
|
||||
try {
|
||||
HttpHeaders httpHeaders = createHeaders(headers);
|
||||
httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
|
||||
|
||||
MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
|
||||
if (params != null) {
|
||||
params.forEach((key, value) -> {
|
||||
if (value != null) {
|
||||
body.add(key, value.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(body, httpHeaders);
|
||||
|
||||
ResponseEntity<T> response = restTemplate.postForEntity(url, requestEntity, responseType);
|
||||
|
||||
if (!response.getStatusCode().is2xxSuccessful()) {
|
||||
throw new LsfxApiException("API调用失败,HTTP状态码: " + response.getStatusCode());
|
||||
}
|
||||
|
||||
T responseBody = response.getBody();
|
||||
if (responseBody == null) {
|
||||
throw new LsfxApiException("API返回数据为空");
|
||||
}
|
||||
|
||||
return responseBody;
|
||||
} catch (RestClientException e) {
|
||||
throw new LsfxApiException("网络请求失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件(Multipart格式)
|
||||
* @param url 请求URL
|
||||
|
||||
Reference in New Issue
Block a user