|
|
@@ -64,6 +64,7 @@ import java.nio.charset.StandardCharsets;
|
|
|
import java.time.LocalDateTime;
|
|
|
import java.time.format.DateTimeFormatter;
|
|
|
import java.util.*;
|
|
|
+import java.util.concurrent.atomic.AtomicInteger;
|
|
|
import java.util.function.Consumer;
|
|
|
import java.util.regex.Matcher;
|
|
|
import java.util.regex.Pattern;
|
|
|
@@ -224,7 +225,7 @@ public class HuaTaiCrawlerRequestImpl implements HuaTaiCrawlerRequest {
|
|
|
String quotationNo = str(xbResult, "quotationNo");
|
|
|
String modelcodexh = StringUtils.isBlank(str(xbResult, "modelcodexh")) ? car.getCarModelNo() : str(xbResult, "modelcodexh");
|
|
|
log.info("XBResult_modelCodeXH: {}", str(xbResult, "modelcodexh"));
|
|
|
- log.info("modelCode_XH: {}", modelcodexh);
|
|
|
+ log.info("car.getCarModelNo()_modelCode_XH: {}", car.getCarModelNo());
|
|
|
|
|
|
// 报价前预处理-保存车辆信息、过滤车型等处理
|
|
|
PreResult pre = null;
|
|
|
@@ -449,15 +450,58 @@ public class HuaTaiCrawlerRequestImpl implements HuaTaiCrawlerRequest {
|
|
|
|
|
|
private StepResult executeQuoteSteps(QuoteVo q, String quotationNo, LoginDTO dto,
|
|
|
String cookie, PreResult pre, Map<String, Object> gsInfo) {
|
|
|
+ // 线程安全计数器,限制最多2次循环(初始0,最多执行2次)
|
|
|
+ AtomicInteger retryCount = new AtomicInteger(0);
|
|
|
PreResult currentPre = pre;
|
|
|
+ StepResult stepResult = null;
|
|
|
+ final int MAX_RETRY_TIMES = 2;
|
|
|
+
|
|
|
+ while (retryCount.get() < MAX_RETRY_TIMES) {
|
|
|
+ try {
|
|
|
+ stepResult = executeQuoteStepInternal(q, quotationNo, dto, cookie, currentPre, gsInfo);
|
|
|
+ // 正常获取到数据则跳出循环
|
|
|
+ if (stepResult != null && stepResult.data() != null && stepResult.data().getApplicationdto() != null) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ } catch (SystemException e) {
|
|
|
+ log.error("第{}次报价步骤执行异常: {}", retryCount.get() + 1, e.getMessage());
|
|
|
+ // 检测是否是车型不匹配需要重新查询的异常
|
|
|
+ if (e.getMessage().contains("errrorFlag") && e.getMessage().contains("carChange")) {
|
|
|
+ // 累加计数,超过次数则抛出异常
|
|
|
+ if (retryCount.incrementAndGet() >= MAX_RETRY_TIMES) {
|
|
|
+ if(e.getMessage().contains("上传的行业车型编码不在平台车型范围内,请核实。")) {
|
|
|
+ throw new SystemException("报价重试次数已达上限(" + MAX_RETRY_TIMES + "次),车型匹配失败。上传的行业车型编码不在平台车型范围内,请核实。", e.getMessage());
|
|
|
+ }else {
|
|
|
+ throw new SystemException("报价重试次数已达上限(" + MAX_RETRY_TIMES + "次),车型匹配失败。" + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 提取新的modelcodexh并重新执行预处理
|
|
|
+ currentPre = rebuildPreResult(q, cookie, quotationNo, e.getMessage(), gsInfo);
|
|
|
+ continue; // 继续下一次循环
|
|
|
+ }
|
|
|
+ // 非车型匹配异常,直接抛出
|
|
|
+ throw e;
|
|
|
+ }
|
|
|
+ // 无有效数据且未触发异常时,累加计数
|
|
|
+ retryCount.incrementAndGet();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 最终仍无结果则返回空StepResult(或抛出异常,根据业务要求调整)
|
|
|
+ return stepResult != null ? stepResult : new StepResult(null, "");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 重构:抽离单次报价步骤执行的核心逻辑
|
|
|
+ */
|
|
|
+ private StepResult executeQuoteStepInternal(QuoteVo q, String quotationNo, LoginDTO dto,
|
|
|
+ String cookie, PreResult pre, Map<String, Object> gsInfo) {
|
|
|
String decryptData = "";
|
|
|
HttpHeaders h = buildQuoteStep1Headers(cookie);
|
|
|
- HtCrawlerSaveOneStepRequest r = new HtCrawlerSaveOneStepRequest(q, currentPre.carDTO(),
|
|
|
- currentPre.params(), quotationNo, currentPre.dataDTO(), dto, gsInfo);
|
|
|
+ HtCrawlerSaveOneStepRequest r = new HtCrawlerSaveOneStepRequest(q, pre.carDTO(),
|
|
|
+ pre.params(), quotationNo, pre.dataDTO(), dto, gsInfo);
|
|
|
log.info("saveOneStept: {}", JSONObject.toJSONString(r));
|
|
|
String body = req.saveOneStept(r, h).getBody().toString();
|
|
|
String mealid = extractMealId(body);
|
|
|
- //机动车损失保险
|
|
|
String limitAmount = extractLimitAmount(body);
|
|
|
log.info("mealid: {}", mealid);
|
|
|
log.info("limitAmount: {}", limitAmount);
|
|
|
@@ -477,41 +521,30 @@ public class HuaTaiCrawlerRequestImpl implements HuaTaiCrawlerRequest {
|
|
|
}
|
|
|
|
|
|
// 处理报价响应各种结果
|
|
|
- HtCrawlerQuoteResponse.DataDTO data = null;
|
|
|
+ HtCrawlerQuoteResponse.DataDTO data = resolveQuoteResponse(duplQuoteResult, decryptData, mealid,
|
|
|
+ limitAmount, h, personalInsuredJSON);
|
|
|
+ return new StepResult(data, personalInsuredJSON);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 重构:抽离重新构建PreResult的逻辑(原递归中重新执行prepareQuote的部分)
|
|
|
+ */
|
|
|
+ private PreResult rebuildPreResult(QuoteVo q, String cookie, String quotationNo, String errorMsg, Map<String, Object> gsInfo) {
|
|
|
try {
|
|
|
- data = resolveQuoteResponse(duplQuoteResult, decryptData, mealid,
|
|
|
- limitAmount, h, personalInsuredJSON);
|
|
|
+ // 提取新的modelcodexh
|
|
|
+ Map<String, Object> map = MAPPER.readValue(errorMsg, Map.class);
|
|
|
+ List<Map<String, String>> list = (List) map.get("carModelList");
|
|
|
+ String newModelCodexh = list.get(0).get("vehiclecode");
|
|
|
+
|
|
|
+ // 重新执行报价预处理流程
|
|
|
+ AttributionInformationVo attr = q.getOrder().getAttributionInformationVo();
|
|
|
+ log.info(map.get("unMatchVehicleFrameMessage") + "已重新执行prepareQuote,新modelcodexh:{}", newModelCodexh);
|
|
|
+ return prepareQuote(attr, gsInfo, q.getCarInfoVo(),
|
|
|
+ newModelCodexh, cookie, quotationNo, map);
|
|
|
} catch (Exception e) {
|
|
|
- log.info("车型异常或其他错误的报价结果: {}", decryptData);
|
|
|
- decryptData = e.getMessage();
|
|
|
- // 检测modelcodexh不在平台车型范围内的异常在这里处理,需要重走新查车型流程再报价
|
|
|
- if (decryptData.contains("errrorFlag") && decryptData.contains("carChange")) {
|
|
|
-
|
|
|
- // 提取新的modelcodexh
|
|
|
- Map<String, Object> map = null;
|
|
|
- try {
|
|
|
- map = MAPPER.readValue(decryptData, Map.class);
|
|
|
- } catch (JsonProcessingException ex) {
|
|
|
- throw new RuntimeException(ex);
|
|
|
- }
|
|
|
- List<Map<String, String>> list = (List)map.get("carModelList");
|
|
|
- String newModelCodexh = list.get(0).get("vehiclecode");
|
|
|
-
|
|
|
- // 重新执行报价预处理流程
|
|
|
- AttributionInformationVo attr = q.getOrder().getAttributionInformationVo();
|
|
|
- log.info(map.get("unMatchVehicleFrameMessage")+"已重新执行prepareQuote,新modelcodexh:{}", newModelCodexh);
|
|
|
- try {
|
|
|
- currentPre = prepareQuote(attr, gsInfo, q.getCarInfoVo(),
|
|
|
- newModelCodexh, cookie, quotationNo, map);
|
|
|
- } catch (Exception ex) {
|
|
|
- throw new RuntimeException(ex);
|
|
|
- }
|
|
|
- executeQuoteSteps(q, quotationNo, dto, cookie, currentPre, gsInfo);
|
|
|
- } else {
|
|
|
- throw new SystemException(decryptData);
|
|
|
- }
|
|
|
+ log.error("重新构建PreResult失败", e);
|
|
|
+ throw new SystemException("重新获取车型信息失败", e.getMessage());
|
|
|
}
|
|
|
- return new StepResult(data, personalInsuredJSON);
|
|
|
}
|
|
|
|
|
|
private String extractMealId(String body) {
|