|
|
@@ -2,6 +2,8 @@ package com.jzg.quotation.hengbang.crawler.component;
|
|
|
|
|
|
import cn.hutool.core.convert.Convert;
|
|
|
import cn.hutool.core.util.StrUtil;
|
|
|
+import cn.hutool.http.HttpRequest;
|
|
|
+import cn.hutool.http.HttpResponse;
|
|
|
import com.alibaba.fastjson.JSON;
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
|
@@ -10,6 +12,7 @@ import com.jzg.commons.exception.SystemException;
|
|
|
import com.jzg.quotation.commons.component.RequestComponent;
|
|
|
import com.jzg.quotation.commons.constant.CacheConstant;
|
|
|
import com.jzg.quotation.commons.service.ExteriorUtilsRequest;
|
|
|
+import com.jzg.quotation.commons.utils.DateUtil;
|
|
|
import com.jzg.quotation.commons.utils.RequestObjectConversion;
|
|
|
import com.jzg.quotation.hengbang.crawler.constant.RequestConstant;
|
|
|
import com.jzg.quotation.hengbang.crawler.constant.enums.RequestUrl;
|
|
|
@@ -39,6 +42,8 @@ import javax.crypto.spec.SecretKeySpec;
|
|
|
import java.nio.charset.StandardCharsets;
|
|
|
import java.time.Duration;
|
|
|
import java.util.*;
|
|
|
+import java.util.regex.Matcher;
|
|
|
+import java.util.regex.Pattern;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
/**
|
|
|
@@ -302,24 +307,78 @@ public class HengBangCrawlerRequestComponent {
|
|
|
String json = mapper.writeValueAsString(calculationRequest);
|
|
|
log.info("提交报价数据请求参数: {}", json);
|
|
|
req.setHbEncD(HengBangAESUtil.encryptStr(json));
|
|
|
- HbCrawlerSaleInfoResponse response = requestComponent.toStringPost(RequestUrl.CALCULATION.getRequestUrl(hbCrawlerProperties.getBaseUrl()), req, RequestUrl.CALCULATION.getRequestDescription(), HbCrawlerSaleInfoResponse.class, headers);
|
|
|
- System.out.println(HengBangAESUtil.decryptStr(response.getHbEncD()));
|
|
|
+
|
|
|
+ String requestJson = mapper.writeValueAsString(req);
|
|
|
+ String url = RequestUrl.CALCULATION.getRequestUrl(hbCrawlerProperties.getBaseUrl());
|
|
|
+ log.info("恒邦calculation请求URL: {}, 请求体: {}", url, requestJson);
|
|
|
+
|
|
|
+ // 使用Hutool发送HTTP POST请求
|
|
|
+ HttpResponse httpResponse = HttpRequest.post(url)
|
|
|
+ .header(headers)
|
|
|
+ .body(requestJson)
|
|
|
+ .timeout(60000)
|
|
|
+ .execute();
|
|
|
+
|
|
|
+ String responseBody = httpResponse.body();
|
|
|
+ int status = httpResponse.getStatus();
|
|
|
+ log.info("恒邦calculation响应状态码: {}, 响应体(前500字符): {}", status,
|
|
|
+ responseBody != null && responseBody.length() > 500 ? responseBody.substring(0, 500) : responseBody);
|
|
|
+
|
|
|
+ // 处理非2xx响应
|
|
|
+ if (!httpResponse.isOk()) {
|
|
|
+ if (status == 500) {
|
|
|
+ JSONObject resObj = JSONObject.parseObject(responseBody);
|
|
|
+ String detail = resObj.getString("detail");
|
|
|
+ if (detail.contains("重复投保")) {
|
|
|
+ String time = extractDuplicateEndTime(detail);
|
|
|
+ if (time != null) {
|
|
|
+ calculationRequest.setBegintimeCi(DateUtil.toUtcDateTime(time));
|
|
|
+ calculationRequest.setBegintimeBi(DateUtil.toUtcDateTime(time));
|
|
|
+ }
|
|
|
+ return getCalculationResult(calculationRequest, headers);
|
|
|
+ }
|
|
|
+ return StrUtil.isNotBlank(detail) ? detail : responseBody;
|
|
|
+ } else if (status == 400) {
|
|
|
+ JSONObject resObj = JSONObject.parseObject(responseBody);
|
|
|
+ String title = resObj.getString("title");
|
|
|
+ return StrUtil.isNotBlank(title) ? title : responseBody;
|
|
|
+ }
|
|
|
+ log.error("恒邦calculation接口返回非2xx: {}, 响应: {}", status, responseBody);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Jackson解析响应
|
|
|
+ HbCrawlerSaleInfoResponse response = mapper.readValue(responseBody, HbCrawlerSaleInfoResponse.class);
|
|
|
+ if (response.getHbEncD() == null) {
|
|
|
+ throw new SystemException("恒邦calculation接口返回数据缺少hbEncD字段,原始响应: " + responseBody);
|
|
|
+ }
|
|
|
String resJson = HengBangAESUtil.decryptStr(response.getHbEncD());
|
|
|
+ log.info("恒邦calculation解密后响应: {}", resJson);
|
|
|
return resJson;
|
|
|
- } catch (WebClientResponseException e) {
|
|
|
- log.error("恒邦calculation接口调用失败[{}]: {}", e.getStatusCode(), e.getResponseBodyAsString());
|
|
|
- final JSONObject jsonObject = JSONObject.parseObject(e.getResponseBodyAsString());
|
|
|
- if (jsonObject.getInteger("status") == 500) {
|
|
|
- String detail = jsonObject.getString("detail");
|
|
|
- return StrUtil.isNotBlank(detail) ? detail : e.getResponseBodyAsString();
|
|
|
- } else if (jsonObject.getInteger("status") == 400) {
|
|
|
- return jsonObject.getString("title");
|
|
|
- } else {
|
|
|
- throw new SystemException(e.getMessage());
|
|
|
- }
|
|
|
+ } catch (SystemException e) {
|
|
|
+ throw e;
|
|
|
} catch (Exception e) {
|
|
|
- throw new SystemException(e.getMessage());
|
|
|
+ log.error("恒邦calculation接口调用异常", e);
|
|
|
+ throw new SystemException("恒邦报价第二步异常: " + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ // 重复投保提取时间
|
|
|
+ private static final Pattern DUPLICATE_END_TIME_PATTERN = Pattern.compile("终保日期 (\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2})");
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 提取系统自动分配的起保时间
|
|
|
+ *
|
|
|
+ * @param calculationResult 核心提示
|
|
|
+ * @return 提取到的时间字符串,未提取到返回 null
|
|
|
+ */
|
|
|
+ public String extractDuplicateEndTime(String calculationResult) {
|
|
|
+ Matcher matcher = DUPLICATE_END_TIME_PATTERN.matcher(calculationResult);
|
|
|
+ if (matcher.find()) {
|
|
|
+ String shortEndTime = matcher.group(1); // 提取到 2025-12-14 16:00
|
|
|
+ return shortEndTime + ":00"; // 补全秒数为 2025-12-14 16:00:00
|
|
|
}
|
|
|
+ return null;
|
|
|
}
|
|
|
|
|
|
/**
|