package com.ruoyi.lsfx.client; import com.fasterxml.jackson.databind.ObjectMapper; 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; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.util.HashMap; import java.util.Map; @Slf4j @Component public class CreditParseClient { private static final int PLATFORM_SUCCESS_CODE = 10000; private static final int INITIATE_SUCCESS_STATUS = 1; private static final int INITIATE_SUCCESS_REASON_CODE = 200; private static final int RESULT_QUERY_MAX_ATTEMPTS = 5; private static final long RESULT_QUERY_INTERVAL_MILLIS = 2000L; @Resource private HttpUtil httpUtil; @Resource private ObjectMapper objectMapper; @Value("${credit-parse.api.url}") private String creditParseUrl; @Value("${credit-parse.api.result-url}") private String creditParseResultUrl; @Value("${credit-parse.api.org-code:999000}") 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(); String actualModel = StringUtils.isBlank(model) ? defaultModel : model; String serialNum = buildSerialNum(); try { Map initiateParams = buildInitiateParams(serialNum, actualModel, remotePath); CreditParseInvokeResponse initiateResponse = request(creditParseUrl, initiateParams, "发起接口"); requireSuccessfulInitiateResponse(initiateResponse, "征信解析发起接口"); CreditParseInvokeResponse response = queryResult(serialNum); long elapsed = System.currentTimeMillis() - startTime; 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 (LsfxApiException e) { log.error("【征信解析】调用失败: serialNum={}, model={}, remotePath={}, error={}", serialNum, actualModel, remotePath, e.getMessage(), e); throw e; } catch (Exception e) { log.error("【征信解析】调用失败: serialNum={}, model={}, remotePath={}, error={}", serialNum, actualModel, remotePath, e.getMessage(), e); throw new LsfxApiException("征信解析调用失败: " + e.getMessage(), e); } } private Map buildInitiateParams(String serialNum, String model, String remotePath) { Map params = buildBaseParams(serialNum); params.put("remotePath", remotePath); params.put("model", model); return params; } private Map buildBaseParams(String serialNum) { Map params = new HashMap<>(); params.put("serialNum", serialNum); params.put("orgCode", orgCode); params.put("runType", runType); return params; } private CreditParseInvokeResponse queryResult(String serialNum) { Map params = buildBaseParams(serialNum); for (int attempt = 1; attempt <= RESULT_QUERY_MAX_ATTEMPTS; attempt++) { CreditParseInvokeResponse response = request(creditParseResultUrl, params, "结果接口第" + attempt + "次查询"); requireSuccessfulServiceResponse(response, "征信解析结果接口"); if (response.getData() == null || response.getData().getMappingOutputFields() == null) { waitForNextResult(serialNum, attempt); continue; } if (response.getData().getMappingOutputFields().getPayload() != null) { return response; } waitForNextResult(serialNum, attempt); } throw new LsfxApiException("征信解析结果未返回"); } private void waitForNextResult(String serialNum, int attempt) { if (attempt >= RESULT_QUERY_MAX_ATTEMPTS) { return; } log.info("【征信解析】结果未返回: serialNum={}, attempt={}/{}, {}ms后重试", serialNum, attempt, RESULT_QUERY_MAX_ATTEMPTS, RESULT_QUERY_INTERVAL_MILLIS); try { sleepBeforeNextResultQuery(RESULT_QUERY_INTERVAL_MILLIS); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new LsfxApiException("征信解析结果查询被中断", e); } } protected void sleepBeforeNextResultQuery(long intervalMillis) throws InterruptedException { Thread.sleep(intervalMillis); } private CreditParseInvokeResponse request(String url, Map params, String stage) { try { log.info("【征信解析】{}请求: url={}, params={}", stage, url, toJson(params)); String responseJson = httpUtil.postUrlEncodedFormForString(url, params, null); log.info("【征信解析】{}返回JSON: {}", stage, responseJson); return objectMapper.readValue(responseJson, CreditParseInvokeResponse.class); } catch (LsfxApiException e) { throw e; } catch (Exception e) { throw new LsfxApiException("征信解析" + stage + "调用失败: " + e.getMessage(), e); } } private void requireSuccessfulInitiateResponse(CreditParseInvokeResponse response, String stage) { requireSuccessfulServiceResponse(response, stage); } private void requireSuccessfulServiceResponse(CreditParseInvokeResponse response, String stage) { requireSuccessfulPlatformResponse(response, stage); if (response.getData() == null) { throw new LsfxApiException(stage + "返回结果为空"); } if (!Integer.valueOf(INITIATE_SUCCESS_STATUS).equals(response.getData().getStatus())) { throw new LsfxApiException(serviceErrorMessage(response, stage + "状态异常: " + response.getData().getStatus())); } if (!Integer.valueOf(INITIATE_SUCCESS_REASON_CODE).equals(response.getData().getReasonCode())) { throw new LsfxApiException(serviceErrorMessage(response, stage + "原因码异常: " + response.getData().getReasonCode())); } } private void requireSuccessfulPlatformResponse(CreditParseInvokeResponse response, String stage) { if (response == null) { throw new LsfxApiException(stage + "返回结果为空"); } if (!Boolean.TRUE.equals(response.getSuccess())) { throw new LsfxApiException(stage + "平台调用失败"); } if (!Integer.valueOf(PLATFORM_SUCCESS_CODE).equals(response.getCode())) { throw new LsfxApiException(stage + "平台状态码异常: " + response.getCode()); } } private String buildSerialNum() { return "CCDI_CREDIT_" + System.currentTimeMillis() + "_" + IdUtils.fastSimpleUUID(); } private String stringValue(Object value, String defaultValue) { if (value == null) { return defaultValue; } String text = value.toString().trim(); return text.isEmpty() ? defaultValue : text; } private String serviceErrorMessage(CreditParseInvokeResponse response, String defaultValue) { if (response == null || response.getData() == null) { return defaultValue; } String reasonMessage = stringValue(response.getData().getReasonMessage(), null); if (reasonMessage != null) { return reasonMessage; } if (response.getData().getMappingOutputFields() != null) { return stringValue(response.getData().getMappingOutputFields().getMessage(), defaultValue); } return defaultValue; } private String toJson(Object value) { try { return objectMapper.writeValueAsString(value); } catch (Exception e) { return String.valueOf(value); } } }