Ver código fonte

update
恒泰财险
1.报价相关

wks 1 ano atrás
pai
commit
9ac404997e
28 arquivos alterados com 1185 adições e 601 exclusões
  1. 1 0
      commons/src/main/java/com/jzg/commons/constants/quote/enums/base/ExpenseRequestUrl.java
  2. 2 1
      tenant/insurance/quotation-ansheng/src/main/java/com/jzg/quotation/ansheng/crawler/service/impl/AnShengCrawlerLoginServiceImpl.java
  3. 5 3
      tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/crawler/client/ChengTaiAPI.java
  4. 84 0
      tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/crawler/component/ChengTaiRequestCrawlerComponent.java
  5. 39 0
      tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/crawler/model/ChengTaiCrawlerConfigureParameters.java
  6. 53 0
      tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/crawler/model/request/ChengTaiCheckCaptchaRequest.java
  7. 23 0
      tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/crawler/model/request/ChengTaiGetCaptchaRequest.java
  8. 36 0
      tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/crawler/model/request/ChengTaiLoginRequest.java
  9. 68 0
      tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/crawler/model/response/ChengTaiCheckCaptchaResponse.java
  10. 59 0
      tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/crawler/model/response/ChengTaiGetCaptchaResponse.java
  11. 20 0
      tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/crawler/model/response/ChengTaiLoginResponse.java
  12. 14 0
      tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/crawler/properties/ChengTaiCrawlerProperties.java
  13. 39 157
      tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/crawler/service/ChengTaiAPIService.java
  14. 30 0
      tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/crawler/service/ChengTaiCrawlerQuoteProcessService.java
  15. 54 70
      tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/crawler/service/ChengTaiCrawlerRequestService.java
  16. 77 0
      tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/crawler/service/impl/ChengTaiCrawlerQuoteProcessServiceImpl.java
  17. 78 0
      tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/utils/CryptoUtils.java
  18. 44 0
      tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/utils/RSACipher.java
  19. 32 0
      tenant/insurance/quotation-chengtai/src/main/resources/certs/CFCA EV ROOT.crt
  20. 0 112
      tenant/insurance/quotation-chengtai/src/test/java/com/jzg/quotation/chengtai/crawler/service/ChengTaiAPIServiceTest.java
  21. 43 1
      tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/component/RequestComponent.java
  22. 54 0
      tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/config/SslConfig.java
  23. 85 37
      tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/config/WebClientConfig.java
  24. 2 1
      tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/service/ExteriorUtilsRequest.java
  25. 5 4
      tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/service/impl/ExteriorUtilsRequestImpl.java
  26. 56 0
      tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/utils/Base64ImageUtils.java
  27. 182 182
      tenant/insurance/quotation-summary/src/test/java/com/jzg/quotation/taikang/crawler/service/ChengTaiCrawlerRequestServiceTest.java
  28. 0 33
      tenant/insurance/quotation-taikang/src/test/java/com/jzg/quotation/taikang/crawler/TaiKangHttpClientTest.java

+ 1 - 0
commons/src/main/java/com/jzg/commons/constants/quote/enums/base/ExpenseRequestUrl.java

@@ -16,6 +16,7 @@ public enum ExpenseRequestUrl {
     CAPTCHA_IDENTIFY("/identify/captcha", "验证码识别"),
     REINSURANCE_CAPTCHA_IDENTIFY("/reinsurance/captcha", "转保验证码识别"),
     SLIDER_IDENTIFY("/identify/slider", "滑块验证"),
+    SLIDER_MATCH("/identify/slide-match", "滑块验证"),
     ;
 
     private final String uri;

+ 2 - 1
tenant/insurance/quotation-ansheng/src/main/java/com/jzg/quotation/ansheng/crawler/service/impl/AnShengCrawlerLoginServiceImpl.java

@@ -1,5 +1,6 @@
 package com.jzg.quotation.ansheng.crawler.service.impl;
 
+import com.jzg.commons.constants.quote.enums.base.ExpenseRequestUrl;
 import com.jzg.commons.entity.quote.vo.identify.SliderCaptchaVo;
 import com.jzg.commons.exception.SystemException;
 import com.jzg.quotation.ansheng.crawler.component.AnShengCrawlerCacheComponent;
@@ -44,7 +45,7 @@ public class AnShengCrawlerLoginServiceImpl implements AnShengCrawlerLoginServic
             AnShengCrawlerVerifyResponse.DataDTO dataDTO = anShengCrawlerRequestComponent.crawlerVerify(anShengCrawlerVerifyRequest, httpHeaders);
             // 滑块验证码识别
             AnShengCrawlerVerifyResponse.DataDTO.ImageVerificationDTO imageVerification = dataDTO.getImageVerification();
-            List<Integer> integers = exteriorUtilsRequest.sliderCaptchaIdentify(new SliderCaptchaVo(imageVerification.getOriginImage(), imageVerification.getShadeImage()));
+            List<Integer> integers = exteriorUtilsRequest.sliderCaptchaIdentify(ExpenseRequestUrl.SLIDER_IDENTIFY, new SliderCaptchaVo(imageVerification.getOriginImage(), imageVerification.getShadeImage()));
             // 验证验证码
             AnShengCrawlerCheckVerificationRequest anShengCrawlerCheckVerificationRequest = new AnShengCrawlerCheckVerificationRequest(integers.get(0)
                     .toString(), integers.get(1).toString(), imageVerification.getUserFlag(), username);

+ 5 - 3
tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/crawler/client/ChengTaiAPI.java

@@ -4,7 +4,10 @@ import com.jzg.quotation.commons.standard.CrawlerRequestUrlStandard;
 
 public enum ChengTaiAPI implements CrawlerRequestUrlStandard {
 
-    Login("/api/upms/login", "登录"),
+    GET_CAPTCHA("/api/upms/captcha/get", "获取验证码"),
+    CHECK_CAPTCHA("/api/upms/captcha/check", "验证验证码"),
+
+    LOGIN("/api/upms/login", "登录"),
     System("/api/upms/system", "系统信息"),
     FindAreaConfig("/api/vehicle/base/findAreaConfig", ""),
     FindDictionaryOfRisk("/api/vehicle/base/findDictionary?type=RISK_TYPE", "查询险种"),
@@ -24,9 +27,8 @@ public enum ChengTaiAPI implements CrawlerRequestUrlStandard {
     GetPolicyModel("/api/vehicle/query/getPolicyModel", "获取详情"),
     Insure("/api/vehicle/query/payPageQuery/{uuid}/insure", "获取支付链接"),
     DownloadAddress("/api/vehicle/core/downloadAddress", "获取保单链接"),
-    HygeiaGet("/api/vehicle/core/hygeia/get", "获取意外险"),
+    HygeiaGet("/api/vehicle/core/hygeia/get", "获取意外险");
 
-    ;
 
     private final String uri;
 

+ 84 - 0
tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/crawler/component/ChengTaiRequestCrawlerComponent.java

@@ -0,0 +1,84 @@
+package com.jzg.quotation.chengtai.crawler.component;
+
+import com.jzg.commons.exception.SystemException;
+import com.jzg.quotation.chengtai.crawler.client.ChengTaiAPI;
+import com.jzg.quotation.chengtai.crawler.model.request.ChengTaiCheckCaptchaRequest;
+import com.jzg.quotation.chengtai.crawler.model.request.ChengTaiGetCaptchaRequest;
+import com.jzg.quotation.chengtai.crawler.model.request.ChengTaiLoginRequest;
+import com.jzg.quotation.chengtai.crawler.model.response.ChengTaiCheckCaptchaResponse;
+import com.jzg.quotation.chengtai.crawler.model.response.ChengTaiGetCaptchaResponse;
+import com.jzg.quotation.chengtai.crawler.model.response.ChengTaiLoginResponse;
+import com.jzg.quotation.chengtai.crawler.properties.ChengTaiCrawlerProperties;
+import com.jzg.quotation.commons.component.RequestComponent;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+
+import java.util.Optional;
+
+@Component
+@RequiredArgsConstructor
+public class ChengTaiRequestCrawlerComponent {
+
+    private final RequestComponent requestComponent;
+
+    private final ChengTaiCrawlerProperties chengTaiCrawlerProperties;
+
+    public <Response> ResponseEntity<Response> requestBasePost(ChengTaiAPI requestUrl, Object body, Class<Response> responseClass, HttpHeaders headers) {
+        String url = chengTaiCrawlerProperties.getBaseUrl() + requestUrl.uri();
+        return requestComponent.objectPost(url, body, responseClass, headers);
+    }
+
+    public <Response> Response requestPost(ChengTaiAPI requestUrl, Object body, Class<Response> responseClass, HttpHeaders headers) {
+        return requestBasePost(requestUrl, body, responseClass, headers).getBody();
+    }
+
+    /**
+     * 获取公钥
+     *
+     * @param responseEntity 响应内容
+     * @return 公钥
+     */
+    public static <T> String getPublicKey(ResponseEntity<T> responseEntity) {
+        return Optional.ofNullable(responseEntity)
+                .map(ResponseEntity::getHeaders)
+                .map(x -> x.get("Publickey"))
+                .map(x -> x.get(0))
+                .orElseThrow(() -> new SystemException("获取公钥失败"));
+    }
+
+
+    /**
+     * 获取验证码
+     *
+     * @param request 请求内容
+     * @return 验证码
+     */
+    public ResponseEntity<ChengTaiGetCaptchaResponse> getCaptcha(ChengTaiGetCaptchaRequest request) {
+        return requestBasePost(ChengTaiAPI.GET_CAPTCHA, request, ChengTaiGetCaptchaResponse.class, new HttpHeaders());
+    }
+
+    /**
+     * 验证验证码
+     *
+     * @param request 验证码
+     * @return 验证结果
+     */
+    public ResponseEntity<ChengTaiCheckCaptchaResponse> checkCaptcha(ChengTaiCheckCaptchaRequest request) {
+        return requestBasePost(ChengTaiAPI.CHECK_CAPTCHA, request, ChengTaiCheckCaptchaResponse.class, new HttpHeaders());
+    }
+
+    /**
+     * 登录
+     *
+     * @param request 登录信息
+     * @return 登录结果
+     */
+    public ChengTaiLoginResponse login(ChengTaiLoginRequest request){
+        ResponseEntity<ChengTaiLoginResponse> response = requestComponent.formData(ChengTaiAPI.LOGIN.getRequestUrl(chengTaiCrawlerProperties.getBaseUrl()), request, ChengTaiLoginResponse.class, new HttpHeaders());
+        return response.getBody();
+    }
+
+
+}

+ 39 - 0
tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/crawler/model/ChengTaiCrawlerConfigureParameters.java

@@ -0,0 +1,39 @@
+package com.jzg.quotation.chengtai.crawler.model;
+
+import com.jzg.quotation.commons.standard.ConfigureParameters;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serial;
+
+/**
+ * @ClassName ChengTaiCrawlerConfigureParameters
+ * @Description 诚泰财险【爬虫】配置参数
+ * @Author wenks
+ * @Date 2025/9/10 18:07
+ * @Version 1.0
+ */
+@AllArgsConstructor
+@NoArgsConstructor
+@Data
+public class ChengTaiCrawlerConfigureParameters implements ConfigureParameters {
+
+    @Serial
+    private static final long serialVersionUID = 5287255169924097167L;
+
+    /**
+     * 业务归属机构
+     */
+    private String deptCode;
+    /**
+     * 业务员
+     */
+    private String handlerCode;
+    /**
+     * 中介机构
+     */
+    private String agreementCode;
+
+}
+

+ 53 - 0
tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/crawler/model/request/ChengTaiCheckCaptchaRequest.java

@@ -0,0 +1,53 @@
+package com.jzg.quotation.chengtai.crawler.model.request;
+
+import com.alibaba.fastjson.JSON;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+
+/**
+ * @ClassName ChengTaiCheckCaptchaRequest
+ * @Description 诚泰财险校验验证码请求参数
+ * @Author wenks
+ * @Date 2025/9/9 16:43
+ * @Version 1.0
+ */
+@NoArgsConstructor
+@Data
+public class ChengTaiCheckCaptchaRequest implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 3187109115725104676L;
+
+    @JsonProperty("captchaType")
+    private String captchaType;
+
+    @JsonProperty("pointJson")
+    private String pointJson;
+
+    @JsonProperty("token")
+    private String token;
+
+    public ChengTaiCheckCaptchaRequest(String pointJson, String token) {
+        this.captchaType = "blockPuzzle";
+        this.pointJson = pointJson;
+        this.token = token;
+    }
+
+    @Data
+    @NoArgsConstructor
+    @AllArgsConstructor
+    public static class NotchLocation{
+
+        private double x;
+
+        private int y;
+
+    }
+
+}

+ 23 - 0
tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/crawler/model/request/ChengTaiGetCaptchaRequest.java

@@ -0,0 +1,23 @@
+package com.jzg.quotation.chengtai.crawler.model.request;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @ClassName ChengTaiGetCaptchaRequest
+ * @Description 诚泰财险获取验证码请求参数
+ * @Author wenks
+ * @Date 2025/9/9 15:40
+ * @Version 1.0
+ */
+@Data
+public class ChengTaiGetCaptchaRequest {
+
+    @JsonProperty("captchaType")
+    private String captchaType;
+
+    public ChengTaiGetCaptchaRequest() {
+        this.captchaType = "blockPuzzle";
+    }
+}

+ 36 - 0
tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/crawler/model/request/ChengTaiLoginRequest.java

@@ -0,0 +1,36 @@
+package com.jzg.quotation.chengtai.crawler.model.request;
+
+import com.alibaba.fastjson.JSON;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.jzg.quotation.chengtai.crawler.client.EncryptRSA;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * @ClassName ChengTaiLoginRequest
+ * @Description 诚泰财险登录请求
+ * @Author wenks
+ * @Date 2025/9/9 16:56
+ * @Version 1.0
+ */
+@Data
+@AllArgsConstructor
+public class ChengTaiLoginRequest implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 2912851835581891383L;
+
+    @JsonProperty("username")
+    private String username;
+
+    @JsonProperty("password")
+    private String password;
+
+    @JsonProperty("captchaVerification")
+    private String captchaVerification;
+
+
+}

+ 68 - 0
tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/crawler/model/response/ChengTaiCheckCaptchaResponse.java

@@ -0,0 +1,68 @@
+package com.jzg.quotation.chengtai.crawler.model.response;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+
+/**
+ * @ClassName ChengTaiCheckCaptchaResponse
+ * @Description 诚泰财险校验参数返回参数
+ * @Author wenks
+ * @Date 2025/9/9 16:43
+ * @Version 1.0
+ */
+@NoArgsConstructor
+@Data
+public class ChengTaiCheckCaptchaResponse implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 7356576829460089305L;
+
+    @JsonProperty("code")
+    private Integer code;
+
+    @JsonProperty("message")
+    private String message;
+
+    @JsonProperty("body")
+    private BodyDTO body;
+
+    @NoArgsConstructor
+    @Data
+    public static class BodyDTO {
+
+        @JsonProperty("repCode")
+        private String repCode;
+
+        @JsonProperty("repData")
+        private RepDataDTO repData;
+
+        @JsonProperty("repMsg")
+        private String repMsg;
+
+        @JsonProperty("success")
+        private Boolean success;
+
+        @NoArgsConstructor
+        @Data
+        public static class RepDataDTO {
+
+            @JsonProperty("captchaType")
+            private String captchaType;
+
+            @JsonProperty("pointJson")
+            private String pointJson;
+
+            @JsonProperty("token")
+            private String token;
+
+            @JsonProperty("result")
+            private Boolean result;
+
+        }
+    }
+}

+ 59 - 0
tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/crawler/model/response/ChengTaiGetCaptchaResponse.java

@@ -0,0 +1,59 @@
+package com.jzg.quotation.chengtai.crawler.model.response;
+
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @ClassName ChengTaiGetCaptchaResponse
+ * @Description 诚泰财险获取验证码返回结果
+ * @Author wenks
+ * @Date 2025/9/9 15:42
+ * @Version 1.0
+ */
+@NoArgsConstructor
+@Data
+public class ChengTaiGetCaptchaResponse {
+
+    @JsonProperty("code")
+    private Integer code;
+
+    @JsonProperty("message")
+    private String message;
+
+    @JsonProperty("body")
+    private BodyDTO body;
+
+    @NoArgsConstructor
+    @Data
+    public static class BodyDTO {
+
+        @JsonProperty("repCode")
+        private String repCode;
+
+        @JsonProperty("repData")
+        private RepDataDTO repData;
+
+        @JsonProperty("success")
+        private Boolean success;
+
+        @NoArgsConstructor
+        @Data
+        public static class RepDataDTO {
+
+            @JsonProperty("secretKey")
+            private String secretKey;
+
+            @JsonProperty("originalImageBase64")
+            private String originalImageBase64;
+
+            @JsonProperty("jigsawImageBase64")
+            private String jigsawImageBase64;
+
+            @JsonProperty("token")
+            private String token;
+
+        }
+    }
+}

+ 20 - 0
tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/crawler/model/response/ChengTaiLoginResponse.java

@@ -0,0 +1,20 @@
+package com.jzg.quotation.chengtai.crawler.model.response;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@NoArgsConstructor
+@Data
+public class ChengTaiLoginResponse {
+
+    @JsonProperty("code")
+    private Integer code;
+
+    @JsonProperty("message")
+    private String message;
+
+    @JsonProperty("body")
+    private String body;
+
+}

+ 14 - 0
tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/crawler/properties/ChengTaiCrawlerProperties.java

@@ -0,0 +1,14 @@
+package com.jzg.quotation.chengtai.crawler.properties;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+@Data
+@Component
+@ConfigurationProperties(prefix = "chengtai.crawler")
+public class ChengTaiCrawlerProperties {
+
+    private String baseUrl;
+
+}

+ 39 - 157
tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/crawler/service/ChengTaiAPIService.java

@@ -9,6 +9,7 @@ import com.jzg.quotation.chengtai.crawler.model.param.*;
 import com.jzg.quotation.chengtai.crawler.model.result.*;
 import com.jzg.quotation.commons.component.RequestComponent;
 import jakarta.annotation.Resource;
+import lombok.RequiredArgsConstructor;
 import org.apache.commons.collections4.CollectionUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -25,152 +26,98 @@ import java.util.Map;
 import java.util.UUID;
 
 @Service
+@RequiredArgsConstructor
 public class ChengTaiAPIService {
-    private static final Logger logger = LoggerFactory.getLogger(ChengTaiAPIService.class);
 
-    @Resource
-    private RequestComponent requestComponent;
-
-    @Resource
-    private ChengTaiInsuranceItemService chengTaiInsuranceItemService;
-
-    public void setRequestComponent(RequestComponent requestComponent) {
-        this.requestComponent = requestComponent;
-    }
+    private final RequestComponent requestComponent;
 
     private <T> T post(ChengTaiAPI api, Object body, Class<T> resultClass, HttpHeaders headers) {
-//        headers.add(":authority", "b2b.champion-ic.com");
-//        headers.add(":method", "POST");
-//        headers.add(":path", api.uri());
-//        headers.add(":scheme", "https");
         if (headers != null) {
             headers.add("traceid", UUID.randomUUID().toString());
         }
-
         String paramString = JsonUtil.toJsonString(body);
-
         ResponseEntity<String> responseEntity = requestComponent.post(api.url(), paramString, String.class, headers);
-
         String responseEntityBody = responseEntity.getBody();
-
         T objcet = JsonUtil.readObjcet(responseEntityBody, resultClass);
-
         return objcet;
     }
 
     /**
      * 查询险种
      *
-     * @param token
-     * @return
+     * @param headers 请求头
+     * @return 险种
      */
-    public List<ChengTaiDictionary> findDictionaryOfRisk(String token) {
-        HttpHeaders headers = new HttpHeaders();
-        headers.add("token", token);
-
+    public List<ChengTaiDictionary> findDictionaryOfRisk(HttpHeaders headers) {
         ChengTaiFindDictionaryResult.Response result = post(ChengTaiAPI.FindDictionaryOfRisk, null, ChengTaiFindDictionaryResult.Response.class, headers);
-
         return result.getBody();
     }
 
     /**
      * 查询登录用户信息
      *
-     * @param token
-     * @return
+     * @param headers 请求头
+     * @return 登录用户信息
      */
-    public ChengTaiQueryLoginUserInfoResult queryLoginUserInfo(String token) {
-        HttpHeaders headers = new HttpHeaders();
-        headers.add("token", token);
-
+    public ChengTaiQueryLoginUserInfoResult queryLoginUserInfo(HttpHeaders headers) {
         ChengTaiQueryLoginUserInfoResult.Response result = post(ChengTaiAPI.QueryLoginUserInfo, null, ChengTaiQueryLoginUserInfoResult.Response.class, headers);
-
         return result.getBody();
     }
 
     /**
      * 查询登录用户可用的业务归属机构
      *
-     * @param token
-     * @return
+     * @param headers 请求头
+     * @return 业务归属机构
      */
-    public List<ChengTaiFindAttributionOrgByUserResult> findAttributionOrgByUser(String token) {
-        HttpHeaders headers = new HttpHeaders();
-        headers.add("token", token);
-
+    public List<ChengTaiFindAttributionOrgByUserResult> findAttributionOrgByUser(HttpHeaders headers) {
         ChengTaiFindAttributionOrgByUserResult.Response result = post(ChengTaiAPI.FindAttributionOrgByUser, null, ChengTaiFindAttributionOrgByUserResult.Response.class, headers);
-
         return result.getBody();
     }
 
-    public List<ChengTaiFindSaleManVoByDeptCodeResult> findSaleManVoByDeptCode(String token, String deptCode, String isOuter, List<String> riskCodes) {
+    public List<ChengTaiFindSaleManVoByDeptCodeResult> findSaleManVoByDeptCode(HttpHeaders headers, String deptCode, String isOuter, List<String> riskCodes) {
         ChengTaiFindSaleManVoByDeptCodeParam param = new ChengTaiFindSaleManVoByDeptCodeParam();
         param.setDeptCode(deptCode);
         param.setIsOuter(isOuter);
         param.setRiskCodes(riskCodes);
-
-        HttpHeaders headers = new HttpHeaders();
-        headers.add("token", token);
-
         ChengTaiFindSaleManVoByDeptCodeResult.Response result = post(ChengTaiAPI.FindSaleManVoByDeptCode, param, ChengTaiFindSaleManVoByDeptCodeResult.Response.class, headers);
-
         return result.getBody();
     }
 
-    public ChengTaiQueryRiskAuthorityResult queryRiskAuthority(String token, String saleCode, String subAgreementCode) {
+    public ChengTaiQueryRiskAuthorityResult queryRiskAuthority(HttpHeaders headers, String saleCode, String subAgreementCode) {
         Map<String, String> param = Maps.newHashMapWithExpectedSize(2);
-
         param.put("saleCode", saleCode);
         param.put("subAgreementCode", subAgreementCode);
-
-        HttpHeaders headers = new HttpHeaders();
-        headers.add("token", token);
-
         ChengTaiQueryRiskAuthorityResult.Response result = post(ChengTaiAPI.QueryRiskAuthority, param, ChengTaiQueryRiskAuthorityResult.Response.class, headers);
-
         return result.getBody();
     }
 
     /**
      * 查询务人员可用的中介协议和代理机构
      *
-     * @param token
+     * @param headers
      * @param saleCode
      * @param riskCodes
      * @return
      */
-    public ChengTaiFindCoreConferInfoByHandleCodeResult findCoreConferInfoByHandleCode(String token, String saleCode, List<String> riskCodes) {
+    public ChengTaiFindCoreConferInfoByHandleCodeResult findCoreConferInfoByHandleCode(HttpHeaders headers, String saleCode, List<String> riskCodes) {
         Map<String, Object> param = Maps.newHashMapWithExpectedSize(2);
-
         param.put("saleCode", saleCode);
         param.put("riskCodes", riskCodes);
-
-        HttpHeaders headers = new HttpHeaders();
-        headers.add("token", token);
-
         ChengTaiFindCoreConferInfoByHandleCodeResult.Response result = post(ChengTaiAPI.FindCoreConferInfoByHandleCode, null, ChengTaiFindCoreConferInfoByHandleCodeResult.Response.class, headers);
-
         return result.getBody();
     }
 
-    public ChengTaiQueryVehicleListResult queryVehicleList(String token) {
-        HttpHeaders headers = new HttpHeaders();
-        headers.add("token", token);
-
+    public ChengTaiQueryVehicleListResult queryVehicleList(HttpHeaders headers) {
         ChengTaiQueryVehicleListResult.Response result = post(ChengTaiAPI.QueryVehicleList, null, ChengTaiQueryVehicleListResult.Response.class, headers);
-
         if (result == null) {
             return null;
         }
-
         ChengTaiQueryVehicleListResult body = result.getBody();
-
         if (body == null) {
             return null;
         }
-
         List<ChengTaiJqxclassidDic> jqxclassidDic = body.getJqxclassidDic();
-
         if (CollectionUtils.isNotEmpty(jqxclassidDic)) {
             jqxclassidDic.forEach(jqxclassid -> {
                 String extdata = jqxclassid.getExtdata();
@@ -193,7 +140,7 @@ public class ChengTaiAPIService {
      * @param vinCode 车架号
      * @return
      */
-    public ChengTaiQueryCarInfoResult queryCarInfo(String token, String comCode, String plateNo, String vinCode) {
+    public ChengTaiQueryCarInfoResult queryCarInfo(HttpHeaders headers, String comCode, String plateNo, String vinCode) {
         if (plateNo == null || plateNo.isBlank()) {
             plateNo = "新车上牌";
         }
@@ -203,12 +150,7 @@ public class ChengTaiAPIService {
         param.put("comCode", comCode);
         param.put("plateNo", plateNo);
         param.put("vinCode", vinCode);
-
-        HttpHeaders headers = new HttpHeaders();
-        headers.add("token", token);
-
         ChengTaiQueryCarInfoResult.Response result = post(ChengTaiAPI.QueryCarInfo, param, ChengTaiQueryCarInfoResult.Response.class, headers);
-
         return result.getBody();
 
     }
@@ -216,22 +158,16 @@ public class ChengTaiAPIService {
     /**
      * 根据车牌号、车架号查询车型
      *
-     * @param token
+     * @param headers
      * @param modelCode 车型编号
      * @return
      */
-    public ChengTaiFindCarModelResult findCarModel(String token, String modelCode) {
+    public ChengTaiFindCarModelResult findCarModel(HttpHeaders headers, String modelCode) {
         Map<String, String> param = Maps.newHashMapWithExpectedSize(3);
-
         param.put("modelcode: ", modelCode);
         param.put("pageNo", "1");
         param.put("pageSize", "100");
-
-        HttpHeaders headers = new HttpHeaders();
-        headers.add("token", token);
-
         ChengTaiFindCarModelResult.Response result = post(ChengTaiAPI.FindCarModel, param, ChengTaiFindCarModelResult.Response.class, headers);
-
         return result.getBody();
 
     }
@@ -239,75 +175,51 @@ public class ChengTaiAPIService {
     /**
      * 身份识别
      *
-     * @param token
      * @param applicant
      * @return
      */
-    public ChengTaiApplicant clientIdentify(String token, ChengTaiApplicant applicant) {
-        HttpHeaders headers = new HttpHeaders();
-
-        headers.add("token", token);
-
+    public ChengTaiApplicant clientIdentify(HttpHeaders headers, ChengTaiApplicant applicant) {
         ChengTaiClientIdentifyResult.Response response = post(ChengTaiAPI.ClientIdentify, applicant, ChengTaiClientIdentifyResult.Response.class, headers);
-
         return response.getBody();
     }
 
     /**
      * 保存
      *
-     * @param token
+     * @param headers
      * @param param
      * @return
      */
-    public ChengTaiSaveResult save(String token, ChengTaiPremiumcalParam param) {
-        HttpHeaders headers = new HttpHeaders();
-
-        headers.add("token", token);
-
+    public ChengTaiSaveResult save(HttpHeaders headers, ChengTaiPremiumcalParam param) {
         ChengTaiSaveResult.Response response = post(ChengTaiAPI.Save, param, ChengTaiSaveResult.Response.class, headers);
-
         return response.getBody();
     }
 
     /**
      * 保费计算
      *
-     * @param token
+     * @param headers
      * @param param
      * @return
      */
-    public ChengTaiPremiumcalResult premiumcal(String token, ChengTaiPremiumcalParam param) {
-        HttpHeaders headers = new HttpHeaders();
-
-        headers.add("token", token);
-
+    public ChengTaiPremiumcalResult premiumcal(HttpHeaders headers, ChengTaiPremiumcalParam param) {
         ChengTaiPremiumcalResult.Response result = post(ChengTaiAPI.Premiumcal, param, ChengTaiPremiumcalResult.Response.class, headers);
-
         return result.getBody();
     }
 
-    public ChengTaiSubmitResult submit(String token, ChengTaiPremiumcalParam param) {
-        HttpHeaders headers = new HttpHeaders();
-
-        headers.add("token", token);
-
+    public ChengTaiSubmitResult submit(HttpHeaders headers, ChengTaiPremiumcalParam param) {
         ChengTaiSubmitResult.Response result = post(ChengTaiAPI.Submit, param, ChengTaiSubmitResult.Response.class, headers);
-
         return result.getBody();
     }
 
     /**
      * 上传影像
      *
-     * @param token
+     * @param headers
      * @param param
      * @return
      */
-    public ChengTaiImageUploadResult imageUpload(String token, byte[] file, ChengTaiImageUploadParam param) {
-        HttpHeaders headers = new HttpHeaders();
-
-        headers.add("token", token);
+    public ChengTaiImageUploadResult imageUpload(HttpHeaders headers, byte[] file, ChengTaiImageUploadParam param) {
 
         MultiValueMap<String, Object> formData = new LinkedMultiValueMap<>();
         formData.add("uploadVo", param);
@@ -319,11 +231,8 @@ public class ChengTaiAPIService {
         });
 
         ResponseEntity<String> responseEntity = requestComponent.formData(ChengTaiAPI.ImageUpload.url(), formData, String.class, headers);
-
         String responseEntityBody = responseEntity.getBody();
-
         ChengTaiImageUploadResult.Response result = JsonUtil.readObjcet(responseEntityBody, ChengTaiImageUploadResult.Response.class);
-
         return result.getBody();
     }
 
@@ -342,7 +251,7 @@ public class ChengTaiAPIService {
 
         param.add("captchaVerification", captcha);
 
-        ResponseEntity<String> responseEntity = requestComponent.form(ChengTaiAPI.Login.url(), param, String.class, null);
+        ResponseEntity<String> responseEntity = requestComponent.form(ChengTaiAPI.LOGIN.url(), param, String.class, null);
 
         String responseEntityBody = responseEntity.getBody();
 
@@ -358,15 +267,9 @@ public class ChengTaiAPIService {
 
     }
 
-    public ChengTaiSystemResult system(String token) {
-        HttpHeaders headers = new HttpHeaders();
-
-        headers.add("token", token);
-
+    public ChengTaiSystemResult system(HttpHeaders headers) {
         MultiValueMap<String, String> param = new LinkedMultiValueMap<>();
-
         ChengTaiSystemResult.Response response = requestComponent.get(ChengTaiAPI.System.url(), param, null, ChengTaiSystemResult.Response.class, headers);
-
         List<ChengTaiSystemResult> body = response.getBody();
 
         if (body == null || body.isEmpty()) {
@@ -376,11 +279,7 @@ public class ChengTaiAPIService {
         return body.get(0);
     }
 
-    public boolean findAreaConfig(String token) {
-        HttpHeaders headers = new HttpHeaders();
-
-        headers.add("token", token);
-
+    public boolean findAreaConfig(HttpHeaders headers) {
         MultiValueMap<String, String> param = new LinkedMultiValueMap<>();
         ChengTaiFindAreaConfigResult.Response response = requestComponent.get(ChengTaiAPI.FindAreaConfig.url(), param, null, ChengTaiFindAreaConfigResult.Response.class, headers);
 
@@ -404,17 +303,15 @@ public class ChengTaiAPIService {
     /**
      * 获取详情
      *
-     * @param token
+     * @param headers 请求头
      * @param orderId
      * @return
      */
-    public ChengTaiPremiumcalParam getPolicyModel(String token, String orderId) {
+    public ChengTaiPremiumcalParam getPolicyModel(HttpHeaders headers, String orderId) {
         MultiValueMap<String, String> param = new LinkedMultiValueMap<>();
         param.add("orderId", orderId);
         param.add("businessType", "POLICY");
 
-        HttpHeaders headers = new HttpHeaders();
-        headers.add("token", token);
         ResponseEntity<ChengTaiGetPolicyModelResult.Response> form = requestComponent.form(ChengTaiAPI.GetPolicyModel.url(), param, ChengTaiGetPolicyModelResult.Response.class, headers);
 
         ChengTaiGetPolicyModelResult.Response response = form.getBody();
@@ -426,18 +323,13 @@ public class ChengTaiAPIService {
     /**
      * 获取支付链接
      *
-     * @param token
+     * @param headers 请求头
      * @param uuid
      * @return 就是多个值
      */
-    public List<ChengTaiInsureResult> insure(String token, String uuid) {
-        HttpHeaders headers = new HttpHeaders();
-        headers.add("token", token);
-
+    public List<ChengTaiInsureResult> insure(HttpHeaders headers, String uuid) {
         MultiValueMap<String, String> param = new LinkedMultiValueMap<>();
-
         ChengTaiInsureResult.Response response = requestComponent.get(ChengTaiAPI.Insure.url().replace("{uuid}", uuid), param, null, ChengTaiInsureResult.Response.class, headers);
-
         return response.getBody();
 
     }
@@ -445,23 +337,18 @@ public class ChengTaiAPIService {
     /**
      * 获取保单下载链接
      *
-     * @param token
+     * @param headers 请求头
      * @param contractNo
      * @param policyUuid
      * @return
      */
-    public ChengTaiDownloadAddressResult downloadAddress(String token, String contractNo, String policyUuid, String expiryDate) {
+    public ChengTaiDownloadAddressResult downloadAddress(HttpHeaders headers, String contractNo, String policyUuid, String expiryDate) {
         ChengTaiDownloadAddressParam param = new ChengTaiDownloadAddressParam();
         param.setBusinessType("C");
         param.setPolicyUuid(policyUuid);
         param.setContractNo(contractNo);
         param.setValidDate(expiryDate);
-
-        HttpHeaders headers = new HttpHeaders();
-        headers.add("token", token);
-
         ChengTaiDownloadAddressResult.Response response = post(ChengTaiAPI.DownloadAddress, param, ChengTaiDownloadAddressResult.Response.class, headers);
-
         return response.getBody();
 
     }
@@ -469,22 +356,17 @@ public class ChengTaiAPIService {
     /**
      * 获取意外险
      *
-     * @param token
+     * @param headers 请求头
      * @return
      */
-    public List<ChengTaiAccidentInsurance> hygeiaGet(String token) {
+    public List<ChengTaiAccidentInsurance> hygeiaGet(HttpHeaders headers) {
         ChengTaiHygeiaGetParam param = new ChengTaiHygeiaGetParam();
         param.setComCode("0105");
         param.setSeat(5);
         param.setRiskCode("1158");
         param.setCarKindCode("A0");
         param.setUseNatureCode("8A");
-
-        HttpHeaders headers = new HttpHeaders();
-        headers.add("token", token);
-
         ChengTaiHygeiaGetResult.Response response = post(ChengTaiAPI.HygeiaGet, param, ChengTaiHygeiaGetResult.Response.class, headers);
-
         return response.getBody();
 
     }

+ 30 - 0
tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/crawler/service/ChengTaiCrawlerQuoteProcessService.java

@@ -0,0 +1,30 @@
+package com.jzg.quotation.chengtai.crawler.service;
+
+import org.springframework.http.HttpHeaders;
+
+/**
+ * @ClassName ChengTaiCrawlerQuoteProcessService
+ * @Description 诚泰财险报价过程需要的接口
+ * @Author wenks
+ * @Date 2025/9/9 15:29
+ * @Version 1.0
+ */
+public interface ChengTaiCrawlerQuoteProcessService {
+
+    /**
+     * 登录
+     *
+     * @param username 用户名
+     * @param password 密码
+     */
+    void login(String username, String password) throws Exception;
+
+
+    /**
+     * 获取token
+     *
+     * @return 请求头
+     */
+    HttpHeaders getTokenHeaders(String username, String password);
+
+}

+ 54 - 70
tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/crawler/service/ChengTaiCrawlerRequestService.java

@@ -6,6 +6,9 @@ import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.jzg.commons.entity.quote.vo.*;
 import com.jzg.commons.entity.quote.vo.aggregated.*;
+import com.jzg.commons.entity.quote.vo.base.LoginBase;
+import com.jzg.commons.exception.SystemException;
+import com.jzg.quotation.chengtai.crawler.model.ChengTaiCrawlerConfigureParameters;
 import com.jzg.quotation.chengtai.crawler.model.entity.*;
 import com.jzg.quotation.chengtai.crawler.model.param.ChengTaiImageUploadParam;
 import com.jzg.quotation.chengtai.crawler.model.param.ChengTaiPremiumcalParam;
@@ -13,79 +16,62 @@ import com.jzg.quotation.chengtai.crawler.model.result.*;
 import com.jzg.quotation.chengtai.crawler.repository.ChengTaiLoginSessionRepository;
 import com.jzg.quotation.chengtai.crawler.repository.ChengTaiPremiumcalRepository;
 import com.jzg.commons.entity.quote.vo.image.InsuranceImageVo;
-import com.jzg.quotation.commons.service.QuotationApiBaseService;
-import jakarta.annotation.Resource;
+import com.jzg.quotation.commons.annotation.QuoteCrawlerService;
+import com.jzg.quotation.commons.constant.InsuranceCode;
+import com.jzg.quotation.commons.service.QuotationCrawlerBaseService;
+import com.jzg.quotation.commons.standard.conversion.ConfigureParametersConversion;
+import lombok.RequiredArgsConstructor;
 import org.apache.commons.lang3.StringUtils;
-import org.springframework.stereotype.Service;
+import org.springframework.http.HttpHeaders;
 
 import java.math.BigDecimal;
 import java.text.SimpleDateFormat;
 import java.util.*;
 
-@Service
-public class ChengTaiCrawlerRequestService implements QuotationApiBaseService {
-    @Resource
-    private ChengTaiAPIService chengTaiAPIService;
+@QuoteCrawlerService(value = InsuranceCode.INSURANCE_CHAC)
+@RequiredArgsConstructor
+public class ChengTaiCrawlerRequestService implements QuotationCrawlerBaseService {
 
-    @Resource
-    private ChengTaiLoginSessionRepository chengTaiLoginSessionRepository;
+    private final ChengTaiAPIService chengTaiAPIService;
 
-    @Resource
-    private ChengTaiPremiumcalRepository chengTaiPremiumcalRepository;
+    private final ChengTaiLoginSessionRepository chengTaiLoginSessionRepository;
 
-    private String username;
-    private String password;
+    private final ChengTaiPremiumcalRepository chengTaiPremiumcalRepository;
 
-    public String login() {
-        return login(username, password, null);
-    }
-
-
-    public String login(String username, String password, String captcha) {
-        ChengTaiSession session = chengTaiLoginSessionRepository.findById(username).orElse(null);
-
-        if (session != null) {
-            // 使用 system 接口验证一下 token 是否过期,如果过期置为 null,后面就会重新登录获取新 token。
-            boolean find = chengTaiAPIService.findAreaConfig(session.getToken());
-
-            if (!find) {
-                chengTaiLoginSessionRepository.delete(session);
-                session = null;
-            }
-        }
-
-        if (session == null) {
-            String token = chengTaiAPIService.login(username, password, captcha); // todo
-
-            session = new ChengTaiSession();
-            session.setToken(token);
-            session.setUsername(username);
+    private final ChengTaiCrawlerQuoteProcessService chengTaiCrawlerQuoteProcessService;
 
-            chengTaiLoginSessionRepository.save(session);
+    @Override
+    public void login(LoginBase loginBase)  {
+        try {
+            chengTaiCrawlerQuoteProcessService.login(loginBase.getUsername(), loginBase.getUsername());
+        }catch (Exception ignored){
+            throw new SystemException("登录失败");
         }
-
-        return session.getToken();
     }
 
     @Override
-    public QuoteResultsVo quote(QuoteVo quoteVo) throws JsonProcessingException {
-        String token = login();
-        List<String> riskCodes = Lists.newArrayList();
+    public QuoteResultsVo quote(QuoteVo quoteVo) throws Exception {
+        HttpHeaders httpHeaders = chengTaiCrawlerQuoteProcessService.getTokenHeaders(quoteVo.getOrder().getAttributionInformationVo().getUsername(), quoteVo.getOrder().getAttributionInformationVo().getPassword());
+
+        // 归属配置
+        AttributionInformationVo attributionInformationVo = quoteVo.getOrder().getAttributionInformationVo();
+        ChengTaiCrawlerConfigureParameters parameters = ConfigureParametersConversion.conversionEntity(ChengTaiCrawlerConfigureParameters.class, attributionInformationVo.getConfigInfo());
 
+        List<String> riskCodes = List.of("", "", "");
         // 当前登录人
-        ChengTaiQueryLoginUserInfoResult userInfoResult = chengTaiAPIService.queryLoginUserInfo(token);
+        ChengTaiQueryLoginUserInfoResult userInfoResult = chengTaiAPIService.queryLoginUserInfo(httpHeaders);
 
         // 查询可以使用的业务人员
-        List<ChengTaiFindSaleManVoByDeptCodeResult> saleManVoByDeptCode = chengTaiAPIService.findSaleManVoByDeptCode(token, userInfoResult.getComCode(), "false", riskCodes);
+        List<ChengTaiFindSaleManVoByDeptCodeResult> saleManVoByDeptCode = chengTaiAPIService.findSaleManVoByDeptCode(httpHeaders, userInfoResult.getComCode(), "false", riskCodes);
 
         // 默认使用第1个业务人员
         ChengTaiFindSaleManVoByDeptCodeResult saleManVo = saleManVoByDeptCode.get(0);
 
         // 查询务人员可用的中介协议和代理机构
-        ChengTaiFindCoreConferInfoByHandleCodeResult coreConferInfo = chengTaiAPIService.findCoreConferInfoByHandleCode(token, saleManVo.getUserCode(), riskCodes);
+        ChengTaiFindCoreConferInfoByHandleCodeResult coreConferInfo = chengTaiAPIService.findCoreConferInfoByHandleCode(httpHeaders, saleManVo.getUserCode(), riskCodes);
 
         // 查询务人员可用的业务信息
-        ChengTaiQueryRiskAuthorityResult queryRiskAuthorityResult = chengTaiAPIService.queryRiskAuthority(token, saleManVo.getUserCode(), coreConferInfo.getSolutionCode());
+        ChengTaiQueryRiskAuthorityResult queryRiskAuthorityResult = chengTaiAPIService.queryRiskAuthority(httpHeaders, saleManVo.getUserCode(), coreConferInfo.getSolutionCode());
 
         // 保存保险单数据1 业务人员
         ChengTaiAcciSaleInfo acciSaleInfo = buildChengTaiAcciSaleInfo(coreConferInfo, queryRiskAuthorityResult.getSalesRisks(), queryRiskAuthorityResult.getSubAgreements());
@@ -98,7 +84,7 @@ public class ChengTaiCrawlerRequestService implements QuotationApiBaseService {
         applicant.setSignedbyOrig("0");
         applicant.setComCode("0105040012");
 
-        applicant = chengTaiAPIService.clientIdentify(token, applicant);
+        applicant = chengTaiAPIService.clientIdentify(httpHeaders, applicant);
 
         // 保存保险单数据3 被投保人
         ChengTaiInsured chengTaiInsured = buildChengTaiInsured(quoteVo.getOwnersInfo());
@@ -124,14 +110,13 @@ public class ChengTaiCrawlerRequestService implements QuotationApiBaseService {
         // 保存保险单数据9
         ChengTaiSubmitReqBody chengTaiSubmitReqBody = buildChengTaiSubmitReqBody();
 
-
-        ChengTaiQueryVehicleListResult queryVehicleListResult = chengTaiAPIService.queryVehicleList(token);
+        ChengTaiQueryVehicleListResult queryVehicleListResult = chengTaiAPIService.queryVehicleList(httpHeaders);
 
         List<ChengTaiUseNature> useNatUreNameList = queryVehicleListResult.getUseNatUreNameList();
 
         ImmutableMap<String, ChengTaiUseNature> map = Maps.uniqueIndex(useNatUreNameList, ChengTaiUseNature::getType);
 
-        List<ChengTaiFindAttributionOrgByUserResult> attributionOrgByUser = chengTaiAPIService.findAttributionOrgByUser(token);
+        List<ChengTaiFindAttributionOrgByUserResult> attributionOrgByUser = chengTaiAPIService.findAttributionOrgByUser(httpHeaders);
 
         ChengTaiFindAttributionOrgByUserResult chengTaiFindAttributionOrgByUserResult = attributionOrgByUser.get(0);
 
@@ -139,7 +124,7 @@ public class ChengTaiCrawlerRequestService implements QuotationApiBaseService {
         String plateNo = quoteVo.getCarInfoVo().getEngineNo(); // 车牌号
         String vinCode = quoteVo.getCarInfoVo().getVinNo(); // 车架号
 
-        ChengTaiQueryCarInfoResult queryCarInfoResult = chengTaiAPIService.queryCarInfo(token, comCode, plateNo, vinCode);
+        ChengTaiQueryCarInfoResult queryCarInfoResult = chengTaiAPIService.queryCarInfo(httpHeaders, comCode, plateNo, vinCode);
 
         List<ChengTaiQueryCarInfoResult.QueryCarModel> queryCarModels = queryCarInfoResult.getCarModelList();
 
@@ -147,7 +132,7 @@ public class ChengTaiCrawlerRequestService implements QuotationApiBaseService {
 
         ChengTaiCarFullData fullCarData = queryCarModel.getFullCarData();
 
-        ChengTaiFindCarModelResult carModel = chengTaiAPIService.findCarModel(token, fullCarData.getModelCode());
+        ChengTaiFindCarModelResult carModel = chengTaiAPIService.findCarModel(httpHeaders, fullCarData.getModelCode());
 
         List<ChengTaiCarModel> data = carModel.getData();
 
@@ -175,12 +160,11 @@ public class ChengTaiCrawlerRequestService implements QuotationApiBaseService {
         param.setSubmitReqBody(chengTaiSubmitReqBody);
 
 
-        ChengTaiSaveResult save = chengTaiAPIService.save(token, param);
+        ChengTaiSaveResult save = chengTaiAPIService.save(httpHeaders, param);
 
         param = save.getModel();
 
-
-        ChengTaiPremiumcalResult premiumcalResult = chengTaiAPIService.premiumcal(token, param);
+        ChengTaiPremiumcalResult premiumcalResult = chengTaiAPIService.premiumcal(httpHeaders, param);
 
         param.setSunlightId(premiumcalResult.getSunlightId());
 
@@ -193,9 +177,7 @@ public class ChengTaiCrawlerRequestService implements QuotationApiBaseService {
         // 折扣率
         BigDecimal discount = contractMain.getDiscount();
 
-
         // 保存到 mongo
-
         ChengTaiBiContract saveBiContract = param.getBiContract();
         ChengTaiCiContract saveCiContract = param.getCiContract();
         if (saveBiContract != null) {
@@ -660,13 +642,13 @@ public class ChengTaiCrawlerRequestService implements QuotationApiBaseService {
 
     @Override
     public UnderwritingResultsVo underwriting(UnderwritingVo underwritingVo) {
-        String token = login();
+        HttpHeaders httpHeaders = chengTaiCrawlerQuoteProcessService.getTokenHeaders(underwritingVo.getOrder().getAttributionInformationVo().getUsername(), underwritingVo.getOrder().getAttributionInformationVo().getPassword());
 
         String ordersNo = underwritingVo.getOrder().getOrdersNo();
 
         ChengTaiPremiumcalParam param = chengTaiPremiumcalRepository.findByOrdersNo(ordersNo);
 
-        ChengTaiSubmitResult result = chengTaiAPIService.submit(token, param);
+        ChengTaiSubmitResult result = chengTaiAPIService.submit(httpHeaders, param);
 
         ChengTaiSubmitResult.Head head = result.getHead();
 
@@ -688,7 +670,7 @@ public class ChengTaiCrawlerRequestService implements QuotationApiBaseService {
 
     @Override
     public PaymentLinkResultsVo getPaymentLink(PaymentLinkVo paymentLinkVo) throws JsonProcessingException {
-        String token = login();
+        HttpHeaders httpHeaders = chengTaiCrawlerQuoteProcessService.getTokenHeaders(paymentLinkVo.getOrder().getAttributionInformationVo().getUsername(), paymentLinkVo.getOrder().getAttributionInformationVo().getPassword());
 
         String ordersNo = paymentLinkVo.getOrder().getOrdersNo();
 
@@ -696,13 +678,13 @@ public class ChengTaiCrawlerRequestService implements QuotationApiBaseService {
 
         String orderId = param.getOrderId();
 
-        param = chengTaiAPIService.getPolicyModel(token, orderId);
+        param = chengTaiAPIService.getPolicyModel(httpHeaders, orderId);
 
         ChengTaiBusinessMain businessMain = param.getBusinessMain();
 
         String uuid = businessMain.getUuid();
 
-        List<ChengTaiInsureResult> insure = chengTaiAPIService.insure(token, uuid);
+        List<ChengTaiInsureResult> insure = chengTaiAPIService.insure(httpHeaders, uuid);
 
         if (insure == null || insure.isEmpty()) {
             return null;
@@ -722,7 +704,7 @@ public class ChengTaiCrawlerRequestService implements QuotationApiBaseService {
 
     @Override
     public void uploadImage(InsuranceUploadImageVo insuranceUploadImageVo) {
-        String token = login();
+        HttpHeaders httpHeaders = chengTaiCrawlerQuoteProcessService.getTokenHeaders(insuranceUploadImageVo.getOrder().getAttributionInformationVo().getUsername(), insuranceUploadImageVo.getOrder().getAttributionInformationVo().getPassword());
 
         String ordersNo = insuranceUploadImageVo.getOrder().getOrdersNo();
 
@@ -759,14 +741,14 @@ public class ChengTaiCrawlerRequestService implements QuotationApiBaseService {
                 param.setAppCode("CAR01");
                 param.setBusinessNo(businessNo); // todo
 
-                chengTaiAPIService.imageUpload(token, imageBytes, param);
+                chengTaiAPIService.imageUpload(httpHeaders, imageBytes, param);
             }
         }
     }
 
     @Override
     public DownloadPolicyResultVo downloadPolicy(DownloadPolicyVo downloadPolicyVo) {
-        String token = login();
+        HttpHeaders httpHeaders = chengTaiCrawlerQuoteProcessService.getTokenHeaders(downloadPolicyVo.getOrder().getAttributionInformationVo().getUsername(), downloadPolicyVo.getOrder().getAttributionInformationVo().getPassword());
 
         String ordersNo = downloadPolicyVo.getOrder().getOrdersNo();
 
@@ -774,7 +756,7 @@ public class ChengTaiCrawlerRequestService implements QuotationApiBaseService {
 
         String orderId = param.getOrderId();
 
-        param = chengTaiAPIService.getPolicyModel(token, orderId);
+        param = chengTaiAPIService.getPolicyModel(httpHeaders, orderId);
 
         ChengTaiCiContract ciContract = param.getCiContract();
         ChengTaiBiContract biContract = param.getBiContract();
@@ -791,7 +773,7 @@ public class ChengTaiCrawlerRequestService implements QuotationApiBaseService {
         String policyUuid = contractMain.getPolicyUuid();
         String expiryDate = contractMain.getValidDate();
 
-        ChengTaiDownloadAddressResult chengTaiDownloadAddressResult = chengTaiAPIService.downloadAddress(token, contractNo, policyUuid, expiryDate);
+        ChengTaiDownloadAddressResult chengTaiDownloadAddressResult = chengTaiAPIService.downloadAddress(httpHeaders, contractNo, policyUuid, expiryDate);
 
         List<ChengTaiDownloadAddressResult.QueryResult> queryResults = chengTaiDownloadAddressResult.getQueryResults();
 
@@ -806,7 +788,7 @@ public class ChengTaiCrawlerRequestService implements QuotationApiBaseService {
 
     @Override
     public OrderStatusResultVo queryOrderState(OrderStatusVo orderBase) {
-        String token = login();
+        HttpHeaders httpHeaders = chengTaiCrawlerQuoteProcessService.getTokenHeaders(orderBase.getOrder().getAttributionInformationVo().getUsername(), orderBase.getOrder().getAttributionInformationVo().getPassword());
 
         String ordersNo = orderBase.getOrder().getOrdersNo();
 
@@ -814,7 +796,7 @@ public class ChengTaiCrawlerRequestService implements QuotationApiBaseService {
 
         String orderId = param.getOrderId();
 
-        param = chengTaiAPIService.getPolicyModel(token, orderId);
+        param = chengTaiAPIService.getPolicyModel(httpHeaders, orderId);
 
         ChengTaiCiContract ciContract = param.getCiContract();
         ChengTaiBiContract biContract = param.getBiContract();
@@ -833,4 +815,6 @@ public class ChengTaiCrawlerRequestService implements QuotationApiBaseService {
         System.out.println("状态为:" + underWriteInd);
         return null;
     }
+
+
 }

+ 77 - 0
tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/crawler/service/impl/ChengTaiCrawlerQuoteProcessServiceImpl.java

@@ -0,0 +1,77 @@
+package com.jzg.quotation.chengtai.crawler.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.jzg.commons.constants.quote.enums.base.ExpenseRequestUrl;
+import com.jzg.commons.entity.quote.vo.identify.SliderCaptchaVo;
+import com.jzg.quotation.chengtai.crawler.component.ChengTaiRequestCrawlerComponent;
+import com.jzg.quotation.chengtai.crawler.model.request.ChengTaiCheckCaptchaRequest;
+import com.jzg.quotation.chengtai.crawler.model.request.ChengTaiGetCaptchaRequest;
+import com.jzg.quotation.chengtai.crawler.model.request.ChengTaiLoginRequest;
+import com.jzg.quotation.chengtai.crawler.model.response.ChengTaiCheckCaptchaResponse;
+import com.jzg.quotation.chengtai.crawler.model.response.ChengTaiGetCaptchaResponse;
+import com.jzg.quotation.chengtai.crawler.model.response.ChengTaiLoginResponse;
+import com.jzg.quotation.chengtai.crawler.service.ChengTaiCrawlerQuoteProcessService;
+import com.jzg.quotation.chengtai.utils.CryptoUtils;
+import com.jzg.quotation.chengtai.utils.RSACipher;
+import com.jzg.quotation.commons.service.ExteriorUtilsRequest;
+import com.jzg.quotation.commons.utils.Base64ImageUtils;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Optional;
+
+@Service
+@RequiredArgsConstructor
+public class ChengTaiCrawlerQuoteProcessServiceImpl implements ChengTaiCrawlerQuoteProcessService {
+
+    private final ChengTaiRequestCrawlerComponent chengTaiRequestCrawlerComponent;
+
+    private final ExteriorUtilsRequest exteriorUtilsRequest;
+
+    @Override
+    public void login(String username, String password) throws Exception {
+        // 步骤一 获取验证码
+        ResponseEntity<ChengTaiGetCaptchaResponse> getCaptchaResponseResponseEntity = chengTaiRequestCrawlerComponent.getCaptcha(new ChengTaiGetCaptchaRequest());
+        ChengTaiGetCaptchaResponse.BodyDTO.RepDataDTO repDataDTO = Optional.of(getCaptchaResponseResponseEntity)
+                .map(ResponseEntity::getBody)
+                .map(ChengTaiGetCaptchaResponse::getBody)
+                .map(ChengTaiGetCaptchaResponse.BodyDTO::getRepData)
+                .orElseThrow(() -> new Exception("获取验证码失败"));
+
+        // 步骤二 获取滑动窗口的位置
+        SliderCaptchaVo sliderCaptchaVo = new SliderCaptchaVo(repDataDTO.getOriginalImageBase64(), repDataDTO.getJigsawImageBase64());
+        List<Integer> integers = exteriorUtilsRequest.sliderCaptchaIdentify(ExpenseRequestUrl.SLIDER_MATCH, sliderCaptchaVo);
+        String secretKey = repDataDTO.getSecretKey();
+
+        // 步骤三 校验验证码
+        Base64ImageUtils.ImageDimensions imageDimensions = Base64ImageUtils.getImageDimensions(repDataDTO.getOriginalImageBase64());
+        double i = 310.0 * (integers.get(0) - 1) / imageDimensions.getWidth();
+        ChengTaiCheckCaptchaRequest.NotchLocation notchLocation = new ChengTaiCheckCaptchaRequest.NotchLocation(i, 5);
+        String jsonString = JSON.toJSONString(notchLocation);
+        String encrypt = CryptoUtils.aesEncrypt(jsonString, secretKey);
+        ChengTaiCheckCaptchaRequest chengTaiCheckCaptchaRequest = new ChengTaiCheckCaptchaRequest(encrypt, repDataDTO.getToken());
+        ResponseEntity<ChengTaiCheckCaptchaResponse> chengTaiCheckCaptchaResponseResponseEntity = chengTaiRequestCrawlerComponent.checkCaptcha(chengTaiCheckCaptchaRequest);
+        String publicKey = ChengTaiRequestCrawlerComponent.getPublicKey(chengTaiCheckCaptchaResponseResponseEntity);
+
+        // 步骤四 登录
+        String pointJson = chengTaiCheckCaptchaResponseResponseEntity.getBody().getBody().getRepData().getPointJson();
+        String token = chengTaiCheckCaptchaResponseResponseEntity.getBody().getBody().getRepData().getToken();
+        String aesDecrypt = CryptoUtils.aesDecrypt(pointJson, secretKey);
+        String s = CryptoUtils.aesEncrypt(token + "---" + aesDecrypt, secretKey);
+        String encrypt1 = new RSACipher(publicKey).encrypt(password);
+        ChengTaiLoginRequest chengTaiLoginRequest = new ChengTaiLoginRequest(username, encrypt1, s);
+        ChengTaiLoginResponse login = chengTaiRequestCrawlerComponent.login(chengTaiLoginRequest);
+        System.out.println(login.getBody());
+    }
+
+    @Override
+    public HttpHeaders getTokenHeaders(String username, String password) {
+        HttpHeaders httpHeaders = new HttpHeaders();
+        httpHeaders.set("token", "eyJhbGciOiJIUzUxMiJ9.eyJpYXQiOjE3NTc0OTM3OTQsImV4cCI6MTc1NzUwNDU5NCwicGF5bG9hZCI6IldkeHJsN3BjSjBYLWtObU9ZTGpxV2pQNjJaQk5ZLTl4eFNMT3pONExzY1Y5UzI0VXliS3E0ZzU3VGdQdi1vaWlGRFdiUXRmcFhNUTlNQjJYbEZoamJtdlBqLUxnLUUzMHA2UU9PNXdrWEFtUUNsLXAxMHVLN0dMMHFVSDA3MTJsdGhJakpuQjhqSFl5ajM0VXJwTFpKSFZWenRhMzNBY0VkaHVSdFFqMW5ONE8yanFia3IwM1JwcklOYnpMZTlTc2ExYVFCRjVaLXFaMzRFOVFqbDJUbXFTdDQwLTZzaTdZOWNKMVc5M1Z5c1djdGlmSlAwYmFCeGNQaGs1SWNVTEY4RGF4OHJvSl81UzNvazVnSjNJdnRfUkJFVlcyTjM4cWdxM2kyZV9qTEZyTEpvcjltRzNCTWx1OS1PUVJQSjRHYmlZYkhwZ3A4RlFQNnlodjNRTmhia0pIUllUd3Jwc3VvMTNIdkZ6UDl4Q1pkckZCY0lFZG9ublAtcVh0dVEtOHlmRlpGd3gySnkwcVVlSzlOVVpDcTF2SlFiYXhJcG11MW1CWmp3R3BPd0NiVjR3R3VleGRXOE1WYnRnakhZc3AifQ.pdPy8G3yhiaWHa6oAlycP5ncp3coKD0Slm6rM9nDN_IIlVFGOgJYxNvsjnZCv0qrb1xaL7LCbDLiPgZFrAZO5A");
+        return httpHeaders;
+    }
+
+}

+ 78 - 0
tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/utils/CryptoUtils.java

@@ -0,0 +1,78 @@
+package com.jzg.quotation.chengtai.utils;
+
+import cn.hutool.crypto.symmetric.AES;
+
+import java.nio.charset.StandardCharsets;
+
+/**
+ * 加密工具类(基于 Hutool 封装)
+ */
+public class CryptoUtils {
+
+    // ==================== AES 工具方法(ECB 模式) ====================
+
+    /**
+     * AES-ECB-PKCS5Padding 加密(自动处理密钥为 16 字节)
+     *
+     * @param plainText 明文
+     * @param key       密钥(任意长度,自动补空格/截断为 16 字节)
+     * @return Base64 编码的密文
+     */
+    public static String aesEncrypt(String plainText, String key) {
+        try {
+            // 处理密钥:补空格到 16 字节,过长截断(与 Python ljust(16)[:16] 行为一致)
+            byte[] keyBytes = processAesKey(key.getBytes(StandardCharsets.UTF_8));
+
+            // 创建AES实例
+            AES aes = new AES("ECB", "PKCS5Padding", keyBytes);
+
+            // AES-ECB-PKCS5Padding 加密并 Base64 编码
+            return aes.encryptBase64(plainText, StandardCharsets.UTF_8);
+        } catch (Exception e) {
+            throw new RuntimeException("AES加密失败", e);
+        }
+    }
+
+    public static void main(String[] args) {
+        System.out.println(aesEncrypt("{\"x\":88,\"y\":5}", "kRiGHmDBQerYvzm4"));
+    }
+
+    /**
+     * AES-ECB-PKCS5Padding 解密(自动处理密钥为 16 字节)
+     *
+     * @param encryptedText Base64 编码的密文
+     * @param key           密钥(任意长度,自动补空格/截断为 16 字节)
+     * @return 原始明文
+     */
+    public static String aesDecrypt(String encryptedText, String key) {
+        try {
+            // 处理密钥(与加密逻辑一致)
+            byte[] keyBytes = processAesKey(key.getBytes(StandardCharsets.UTF_8));
+
+            // 创建AES实例
+            AES aes = new AES("ECB", "PKCS5Padding", keyBytes);
+
+            // Base64 解码后 AES 解密
+            return aes.decryptStr(encryptedText, StandardCharsets.UTF_8);
+        } catch (Exception e) {
+            throw new RuntimeException("AES解密失败", e);
+        }
+    }
+
+    /**
+     * 处理 AES 密钥(统一为 16 字节,不足补空格,过长截断)
+     * 与 Python 代码 `key.ljust(16)[:16]` 行为完全一致
+     */
+    private static byte[] processAesKey(byte[] originalKey) {
+        byte[] processedKey = new byte[16];
+        int copyLength = Math.min(originalKey.length, 16);
+        // 复制原始密钥的前 16 字节(或全部,若不足 16 字节)
+        System.arraycopy(originalKey, 0, processedKey, 0, copyLength);
+        // 不足 16 字节的部分用空格填充(与 Python `ljust(16)` 一致)
+        for (int i = copyLength; i < 16; i++) {
+            processedKey[i] = (byte) ' ';
+        }
+        return processedKey;
+    }
+
+}

+ 44 - 0
tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/utils/RSACipher.java

@@ -0,0 +1,44 @@
+package com.jzg.quotation.chengtai.utils;
+
+import cn.hutool.core.codec.Base64;
+import cn.hutool.crypto.asymmetric.KeyType;
+import cn.hutool.crypto.asymmetric.RSA;
+import cn.hutool.crypto.symmetric.AES;
+
+import java.nio.charset.StandardCharsets;
+
+public class RSACipher {
+
+    private final RSA rsa;
+
+    /**
+     * 从 PEM 格式公钥初始化(自动解析头尾标记)
+     * @param publicKeyPem PEM 格式公钥字符串(包含 -----BEGIN PUBLIC KEY----- 头尾)
+     */
+    public RSACipher(String publicKeyPem) {
+        try {
+            // 使用Hutool解析PEM格式公钥
+            this.rsa = new RSA(null, publicKeyPem);
+        } catch (Exception e) {
+            throw new RuntimeException("RSA公钥解析失败", e);
+        }
+    }
+
+    /**
+     * RSA 公钥加密(PKCS#1 v1.5 填充)
+     * @param plaintext 明文(长度限制:RSA 密钥 2048 位时最大 245 字节)
+     * @return Base64 编码的密文
+     */
+    public String encrypt(String plaintext) {
+        try {
+            // 如果 encryptBase64 方法不存在,则使用 encrypt + Base64 编码的方式
+            byte[] encryptedBytes = this.rsa.encrypt(plaintext, StandardCharsets.UTF_8, KeyType.PublicKey);
+            return Base64.encode(encryptedBytes);
+        } catch (Exception e) {
+            throw new RuntimeException("RSA加密失败", e);
+        }
+    }
+
+
+
+}

+ 32 - 0
tenant/insurance/quotation-chengtai/src/main/resources/certs/CFCA EV ROOT.crt

@@ -0,0 +1,32 @@
+-----BEGIN CERTIFICATE-----
+MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJD
+TjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9y
+aXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkx
+MjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEwMC4GA1UECgwnQ2hpbmEgRmluYW5j
+aWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJP
+T1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnVBU03
+sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpL
+TIpTUnrD7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5
+/ZOkVIBMUtRSqy5J35DNuF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp
+7hZZLDRJGqgG16iI0gNyejLi6mhNbiyWZXvKWfry4t3uMCz7zEasxGPrb382KzRz
+EpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7xzbh72fROdOXW3NiGUgt
+hxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9fpy25IGvP
+a931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqot
+aK8KgWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNg
+TnYGmE69g60dWIolhdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfV
+PKPtl8MeNPo4+QgO48BdK4PRVmrJtqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hv
+cWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAfBgNVHSMEGDAWgBTj/i39KNAL
+tbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAd
+BgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB
+ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObT
+ej/tUxPQ4i9qecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdL
+jOztUmCypAbqTuv0axn96/Ua4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBS
+ESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sGE5uPhnEFtC+NiWYzKXZUmhH4J/qy
+P5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfXBDrDMlI1Dlb4pd19
+xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjnaH9d
+Ci77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN
+5mydLIhyPDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe
+/v5WOaHIz16eGWRGENoXkbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+Z
+AAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3CekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ
+5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su
+-----END CERTIFICATE-----

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 112
tenant/insurance/quotation-chengtai/src/test/java/com/jzg/quotation/chengtai/crawler/service/ChengTaiAPIServiceTest.java


+ 43 - 1
tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/component/RequestComponent.java

@@ -3,6 +3,7 @@ package com.jzg.quotation.commons.component;
 
 import com.alibaba.fastjson2.JSON;
 import com.jzg.commons.exception.SystemException;
+import com.jzg.quotation.commons.config.WebClientConfig;
 import com.jzg.quotation.commons.utils.RequestObjectConversion;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -47,6 +48,44 @@ public class RequestComponent {
      */
     private final WebClient webClient;
 
+    private final WebClientConfig webClientConfig;
+
+    /**
+     * 根据URL选择合适的WebClient(支持SSL)
+     *
+     * @param url 请求URL
+     * @return WebClient实例
+     */
+    private WebClient selectWebClient(String url) {
+        try {
+            if (url.contains("https://")) {
+                String domain = extractDomain(url);
+                if (webClientConfig != null) {
+                    return webClientConfig.createSecureWebClient(domain);
+                }
+            }
+        } catch (Exception e) {
+            log.warn("创建安全WebClient失败,使用默认WebClient", e);
+        }
+        return webClient;
+    }
+
+    /**
+     * 从URL中提取域名
+     *
+     * @param url URL地址
+     * @return 域名
+     */
+    private String extractDomain(String url) {
+        try {
+            String[] parts = url.replace("https://", "").replace("http://", "").split("/");
+            return parts[0].split(":")[0]; // 移除端口号
+        } catch (Exception e) {
+            log.warn("提取域名失败: {}", url, e);
+            return "default";
+        }
+    }
+
     /**
      * 设置请求头
      *
@@ -201,6 +240,7 @@ public class RequestComponent {
             log.debug("request body is {}", body);
         }
         body = Optional.ofNullable(body).orElse("");
+        WebClient webClient = selectWebClient(url);
         return webClient.post()
                 .uri(url)
                 .headers(setHeaders(headers))
@@ -304,6 +344,7 @@ public class RequestComponent {
      * @return 响应
      */
     public <Response> ResponseEntity<Response> formData(String url, MultiValueMap<String, Object> parts, Class<Response> responseClass, HttpHeaders headers) {
+        WebClient webClient = selectWebClient(url);
 //        String block = webClient.post()
 //                .uri(url)
 //                .headers(RequestComponent.setHeaders(headers))
@@ -518,7 +559,8 @@ public class RequestComponent {
     }
 
     public <Response> ResponseEntity<Response> form(String url, MultiValueMap<String, String> formData, Class<Response> responseClass, HttpHeaders headers) {
-        return WebClient.create()
+        WebClient selectWebClient = selectWebClient(url);
+        return selectWebClient
                 .post()
                 .uri(url)
                 .headers(RequestComponent.setHeaders(headers))

+ 54 - 0
tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/config/SslConfig.java

@@ -0,0 +1,54 @@
+package com.jzg.quotation.commons.config;
+
+import io.netty.handler.ssl.SslContext;
+import io.netty.handler.ssl.SslContextBuilder;
+import org.springframework.util.ResourceUtils;
+
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+import java.io.File;
+import java.io.FileInputStream;
+import java.security.KeyStore;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+
+public class SslConfig {
+
+    // 从 .crt 文件创建 X509TrustManager
+    public static X509TrustManager createTrustManager(String certPath) throws Exception {
+        // 加载 .crt 证书
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+        File certFile = ResourceUtils.getFile(certPath);
+        FileInputStream fis = new FileInputStream(certFile);
+        Certificate cert = cf.generateCertificate(fis);
+        fis.close();
+
+        // 创建 KeyStore 并存储证书
+        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+        keyStore.load(null, null); // 初始化空 KeyStore
+        keyStore.setCertificateEntry("server-cert", cert);
+
+        // 初始化 TrustManagerFactory
+        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+        tmf.init(keyStore);
+
+        // 获取 X509TrustManager
+        TrustManager[] trustManagers = tmf.getTrustManagers();
+        for (TrustManager tm : trustManagers) {
+            if (tm instanceof X509TrustManager) {
+                return (X509TrustManager) tm;
+            }
+        }
+        throw new IllegalStateException("No X509TrustManager found");
+    }
+
+    // 构建 SslContext
+    public static SslContext buildSslContext(String certPath) throws Exception {
+        X509TrustManager trustManager = createTrustManager(certPath);
+        return SslContextBuilder.forClient().trustManager(trustManager)
+                // 若服务端证书主机名与实际域名不一致(如自签名),可禁用主机名验证(仅测试用)
+                // .hostnameVerifier((hostname, session) -> true)
+                .build();
+    }
+}

+ 85 - 37
tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/config/WebClientConfig.java

@@ -1,14 +1,17 @@
 package com.jzg.quotation.commons.config;
 
 import io.netty.channel.ChannelOption;
+import io.netty.handler.ssl.SslContext;
 import io.netty.handler.timeout.ReadTimeoutHandler;
 import io.netty.handler.timeout.WriteTimeoutHandler;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.http.ssl.SSLContextBuilder;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.MediaType;
 import org.springframework.http.client.reactive.ReactorClientHttpConnector;
+import org.springframework.util.ResourceUtils;
 import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
 import org.springframework.web.reactive.function.client.ExchangeStrategies;
 import org.springframework.web.reactive.function.client.WebClient;
@@ -16,8 +19,11 @@ import org.springframework.web.util.DefaultUriBuilderFactory;
 import reactor.core.publisher.Mono;
 import reactor.netty.http.client.HttpClient;
 import reactor.netty.resources.ConnectionProvider;
+import reactor.netty.tcp.SslProvider;
 
 import java.time.Duration;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.Map;
 
 /**
  * @description: WebClientCon 配置类
@@ -43,50 +49,92 @@ public class WebClientConfig {
 
     public static final int MAX_IN_MEMORY_SIZE = 10 * 1024 * 1024;
 
+    // 存储域名与证书路径的映射关系
+    private final Map<String, String> domainCertMap = new ConcurrentHashMap<>();
+
+    // 存储SSL上下文缓存
+    private final Map<String, SslContext> sslContextCache = new ConcurrentHashMap<>();
+
+    public WebClientConfig() {
+        // 初始化域名与证书映射关系
+        domainCertMap.put("champion-ic.com", "classpath:certs/CFCA EV ROOT.crt");
+    }
+
     @Bean
     public WebClient clientBuilder() {
+        // 配置默认HTTP客户端(无SSL)
+        ConnectionProvider connectionProvider = ConnectionProvider.builder("http").maxConnections(CONNECTION_PROVIDER_MAX_CONNECTIONS).maxIdleTime(CONNECTION_PROVIDER_MAX_IDLE_TIME).build();
+
+        HttpClient httpClient = HttpClient.create(connectionProvider).option(ChannelOption.CONNECT_TIMEOUT_MILLIS, HTTPCLIENT_CONNECT_TIMEOUT_MILLIS).responseTimeout(HTTPCLIENT_RESPONSE_TIMEOUT).doOnConnected(conn -> conn.addHandlerLast(new ReadTimeoutHandler(READ_TIMEOUT)).addHandlerLast(new WriteTimeoutHandler(WRITE_TIMEOUT)));
+
+        // 构建WebClient实例
+        DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory();
+        factory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.VALUES_ONLY);
+        return WebClient.builder().exchangeStrategies(ExchangeStrategies.builder().codecs(clientCodecConfigurer -> clientCodecConfigurer.defaultCodecs().maxInMemorySize(MAX_IN_MEMORY_SIZE)).build()).uriBuilderFactory(factory).clientConnector(new ReactorClientHttpConnector(httpClient)).defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).filter(ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
+            log.info("Client request: {}", clientRequest.url());
+            // 打印请求头信息
+            clientRequest.headers().forEach((key, values) -> {
+                log.info("请求头: {}: {}", key, values);
+            });
+            return Mono.just(clientRequest);
+        })).build();
+    }
+
+    /**
+     * 为特定域名创建带SSL认证的WebClient
+     *
+     * @param domain 域名
+     * @return WebClient实例
+     */
+    public WebClient createSecureWebClient(String domain) throws Exception {
         // 配置HTTP连接池
-        ConnectionProvider connectionProvider = ConnectionProvider
-                .builder("http")
-                .maxConnections(CONNECTION_PROVIDER_MAX_CONNECTIONS)
-                .maxIdleTime(CONNECTION_PROVIDER_MAX_IDLE_TIME)
-                .build();
-
-        // 配置HTTP客户端
-        HttpClient httpClient = HttpClient
-                .create(connectionProvider)
-                .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, HTTPCLIENT_CONNECT_TIMEOUT_MILLIS)
-                .responseTimeout(HTTPCLIENT_RESPONSE_TIMEOUT)
-                .doOnConnected(conn ->
-                        conn
-                                .addHandlerLast(new ReadTimeoutHandler(READ_TIMEOUT))
-                                .addHandlerLast(new WriteTimeoutHandler(WRITE_TIMEOUT)));
+        ConnectionProvider connectionProvider = ConnectionProvider.builder("secure-" + domain).maxConnections(CONNECTION_PROVIDER_MAX_CONNECTIONS).maxIdleTime(CONNECTION_PROVIDER_MAX_IDLE_TIME).build();
+
+        // 获取域名对应的SSL上下文
+        SslContext sslContext = getSSLContextForDomain(domain);
+
+        // 配置带SSL的HTTP客户端
+        HttpClient httpClient = HttpClient.create(connectionProvider).option(ChannelOption.CONNECT_TIMEOUT_MILLIS, HTTPCLIENT_CONNECT_TIMEOUT_MILLIS).responseTimeout(HTTPCLIENT_RESPONSE_TIMEOUT).secure(spec -> spec.sslContext(sslContext)).doOnConnected(conn -> conn.addHandlerLast(new ReadTimeoutHandler(READ_TIMEOUT)).addHandlerLast(new WriteTimeoutHandler(WRITE_TIMEOUT)));
+
         // 构建WebClient实例
         DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory();
         factory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.VALUES_ONLY);
-        return WebClient
-                .builder()
-                .exchangeStrategies(ExchangeStrategies.builder()
-                        .codecs(clientCodecConfigurer -> clientCodecConfigurer.defaultCodecs().maxInMemorySize(MAX_IN_MEMORY_SIZE))
-                        .build())
-                .uriBuilderFactory(factory)
-                .clientConnector(new ReactorClientHttpConnector(httpClient))
-                .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
-                .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
-                .filter(ExchangeFilterFunction.ofRequestProcessor(
-                        clientRequest -> {
-                            log.info("Client request: {}", clientRequest.url());
-                            // 打印请求头信息
-                            clientRequest
-                                    .headers()
-                                    .forEach((key, values) -> {
-                                        log.info("请求头: {}: {}", key, values);
-                                    });
-                            return Mono.just(clientRequest);
-                        }
-                ))
-                .build();
+        return WebClient.builder().exchangeStrategies(ExchangeStrategies.builder().codecs(clientCodecConfigurer -> clientCodecConfigurer.defaultCodecs().maxInMemorySize(MAX_IN_MEMORY_SIZE)).build()).uriBuilderFactory(factory).clientConnector(new ReactorClientHttpConnector(httpClient)).defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).filter(ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
+            log.info("Secure client request: {}", clientRequest.url());
+            // 打印请求头信息
+            clientRequest.headers().forEach((key, values) -> {
+                log.info("请求头: {}: {}", key, values);
+            });
+            return Mono.just(clientRequest);
+        })).build();
     }
 
+    /**
+     * 根据域名获取对应的SSL上下文
+     *
+     * @param domain 域名
+     * @return SSLContext实例
+     */
+    private SslContext getSSLContextForDomain(String domain) throws Exception {
+        // 先从缓存中获取
+        if (sslContextCache.containsKey(domain)) {
+            return sslContextCache.get(domain);
+        }
 
+        // 获取域名对应的证书路径
+        String certPath = domainCertMap.getOrDefault(domain, "classpath:certs/CFCA EV ROOT.crt");
+
+        try {
+            // 创建SSL上下文
+            SslContext sslContext = SslConfig.buildSslContext(certPath);
+
+            // 缓存SSL上下文
+            sslContextCache.put(domain, sslContext);
+
+            return sslContext;
+        } catch (Exception e) {
+            log.error("Failed to create SSL context for domain: {}, certPath: {}", domain, certPath, e);
+            throw e;
+        }
+    }
 }

+ 2 - 1
tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/service/ExteriorUtilsRequest.java

@@ -1,6 +1,7 @@
 package com.jzg.quotation.commons.service;
 
 
+import com.jzg.commons.constants.quote.enums.base.ExpenseRequestUrl;
 import com.jzg.commons.entity.quote.vo.identify.ReinsuranceCaptchaVo;
 import com.jzg.commons.entity.quote.vo.identify.SliderCaptchaVo;
 
@@ -35,6 +36,6 @@ public interface ExteriorUtilsRequest {
      * @param sliderCaptchaVo 滑块验证码
      * @return 识别位置列表 [x, y]
      */
-    List<Integer> sliderCaptchaIdentify(SliderCaptchaVo sliderCaptchaVo);
+    List<Integer> sliderCaptchaIdentify(ExpenseRequestUrl expenseRequestUrl, SliderCaptchaVo sliderCaptchaVo);
 }
 

+ 5 - 4
tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/service/impl/ExteriorUtilsRequestImpl.java

@@ -54,12 +54,13 @@ public class ExteriorUtilsRequestImpl implements ExteriorUtilsRequest {
     }
 
     @Override
-    public List<Integer> sliderCaptchaIdentify(SliderCaptchaVo sliderCaptchaVo) {
-        ExpenseRequestUrl captcha = ExpenseRequestUrl.SLIDER_IDENTIFY;
-        String url = ExpenseRequestUrl.getUrl(captchaRecognitionProperties.getUrl(), captcha.getUri());
-        R<List<Integer>> response = requestComponent.post(url, sliderCaptchaVo, captcha.getDescription(), new ParameterizedTypeReference<>() {
+    public List<Integer> sliderCaptchaIdentify(ExpenseRequestUrl expenseRequestUrl, SliderCaptchaVo sliderCaptchaVo) {
+        String url = ExpenseRequestUrl.getUrl(captchaRecognitionProperties.getUrl(), expenseRequestUrl.getUri());
+        R<List<Integer>> response = requestComponent.post(url, sliderCaptchaVo, expenseRequestUrl.getDescription(), new ParameterizedTypeReference<>() {
         }, new HttpHeaders());
         return response.getData();
     }
 
+
+
 }

+ 56 - 0
tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/utils/Base64ImageUtils.java

@@ -0,0 +1,56 @@
+package com.jzg.quotation.commons.utils;
+
+
+import com.jzg.commons.exception.SystemException;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.Base64;
+
+public final class Base64ImageUtils {
+
+    /**
+     * 获取 Base64 图片的宽高
+     *
+     * @param base64Str Base64 图片字符串(可能包含前缀)
+     * @return 宽高数组 [width, height],失败返回 null
+     */
+    public static ImageDimensions getImageDimensions(String base64Str) {
+        try {
+            // 步骤1:去除 Base64 前缀(如果有)
+            String base64Data = base64Str.replaceAll("^data:image/[^;]+;base64,", "");
+
+            // 步骤2:Base64 解码为字节数组
+            byte[] imageBytes = Base64.getDecoder().decode(base64Data);
+
+            // 步骤3:通过 ImageIO 读取图片并获取宽高
+            BufferedImage image = ImageIO.read(new ByteArrayInputStream(imageBytes));
+            if (image == null) {
+                throw new SystemException("无法识别的图片格式");
+            }
+            return new ImageDimensions(image.getWidth(), image.getHeight());
+
+        } catch (IllegalArgumentException e) {
+            throw new SystemException("Base64 解码失败:" + e.getMessage());
+        } catch (IOException e) {
+            throw new SystemException("读取图片失败:" + e.getMessage());
+        }
+    }
+
+    @Data
+    @AllArgsConstructor
+    public static class ImageDimensions {
+
+        private final int width;
+
+        private final int height;
+
+    }
+
+
+}

+ 182 - 182
tenant/insurance/quotation-summary/src/test/java/com/jzg/quotation/taikang/crawler/service/ChengTaiCrawlerRequestServiceTest.java

@@ -1,182 +1,182 @@
-package com.jzg.quotation.taikang.crawler.service;
-
-import com.jzg.quotation.chengtai.crawler.JsonUtil;
-import com.jzg.quotation.chengtai.crawler.model.entity.ChengTaiBiContract;
-import com.jzg.quotation.chengtai.crawler.model.entity.ChengTaiCiContract;
-import com.jzg.quotation.chengtai.crawler.model.entity.ChengTaiContractMain;
-import com.jzg.quotation.chengtai.crawler.model.param.ChengTaiPremiumcalParam;
-import com.jzg.quotation.chengtai.crawler.model.result.ChengTaiDownloadAddressResult;
-import com.jzg.quotation.chengtai.crawler.model.result.ChengTaiInsureResult;
-import com.jzg.quotation.chengtai.crawler.model.result.ChengTaiSystemResult;
-import com.jzg.quotation.chengtai.crawler.service.ChengTaiAPIService;
-import com.jzg.quotation.chengtai.crawler.service.ChengTaiCrawlerRequestService;
-import com.jzg.quotation.summary.SummaryQuotationApplication;
-import jakarta.annotation.Resource;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.boot.test.context.SpringBootTest;
-
-import java.util.List;
-
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-
-@SpringBootTest(classes = {SummaryQuotationApplication.class})
-public class ChengTaiCrawlerRequestServiceTest {
-    private static final Logger logger = LoggerFactory.getLogger(ChengTaiCrawlerRequestServiceTest.class);
-
-    @Resource
-    private ChengTaiCrawlerRequestService chengTaiCrawlerRequestService;
-
-    @Resource
-    public ChengTaiAPIService chengTaiAPIService;
-
-    @BeforeAll
-    public static void befroe() {
-       // ChengTaiAPIHelper.initAPI("https://b2b.champion-ic.com");
-    }
-
-    @Test
-    public void login() {
-        String username = "0105B122";
-        String password = "Tqct@2024.";
-        String captcha = "2QVPHjQEJk/FLGkVXPgNndHmbd/ywg0/iZM+6WkEnTOWSiim4s9Ez9dUyvDBF/1S/dR8n4gabCJJ/iOq8b7HT1K1F0YOuOs/jffMBk/T9Cg=";
-
-        String token = chengTaiCrawlerRequestService.login(username, password, captcha);
-
-        assertNotNull(token);
-    }
-
-    @Test
-    public void system() {
-        String token = chengTaiCrawlerRequestService.login("0105B122", null, null);
-
-        ChengTaiSystemResult system = chengTaiAPIService.system(token);
-
-        assertNotNull(system);
-    }
-
-    @Test
-    public void getPolicyModel() {
-        String token = chengTaiCrawlerRequestService.login("0105B122", null, null);
-
-        String orderId = "1909779147122143234";
-
-        ChengTaiPremiumcalParam result = chengTaiAPIService.getPolicyModel(token, orderId);
-
-        assertNotNull(result);
-
-        System.out.println("==================================================");
-
-        System.out.println(JsonUtil.toJsonString(result));
-
-        System.out.println();
-        System.out.println();
-        System.out.println();
-
-
-        System.out.println(JsonUtil.toJsonString(result.getUnknownFields()));
-    }
-
-    @Test
-    public void insure() {
-        String token = chengTaiCrawlerRequestService.login("0105B122", null, null);
-
-        String uuid = "uXu-BI-WTN6M2kEpoZdaDQ";
-
-        List<ChengTaiInsureResult> result = chengTaiAPIService.insure(token, uuid);
-
-        assertNotNull(result);
-
-        System.out.println("==================================================");
-
-        System.out.println(JsonUtil.toJsonString(result));
-
-        System.out.println();
-        System.out.println();
-        System.out.println();
-
-
-        for (ChengTaiInsureResult  item : result) {
-            System.out.println(JsonUtil.toJsonString(item.getUnknownFields()));
-
-            System.out.println(item.getPayUrl());
-        }
-    }
-
-    @Test
-    public void downloadAddress() {
-        String token = chengTaiCrawlerRequestService.login("0105B122", null, null);
-
-        String contractNo = "6050400082120250005927";
-        String policyUuid = "8s3HUoSHRxeLvJcFa40T9g";
-        String expiryDate = "2026-04-10 00:00:00";
-
-        ChengTaiDownloadAddressResult result = chengTaiAPIService.downloadAddress(token, contractNo, policyUuid, expiryDate);
-
-        assertNotNull(result);
-        assertNotNull(result.getQueryResults());
-
-        System.out.println("==================================================");
-
-        System.out.println(JsonUtil.toJsonString(result));
-
-        System.out.println();
-        System.out.println();
-        System.out.println();
-
-        System.out.println(JsonUtil.toJsonString(result.getUnknownFields()));
-
-        List<ChengTaiDownloadAddressResult.QueryResult> queryResults = result.getQueryResults();
-
-        for (ChengTaiDownloadAddressResult.QueryResult item : queryResults) {
-            System.out.println(item.getDownLoadURL());
-        }
-    }
-
-    @Test
-    public void downloadAddress2() {
-        String token = chengTaiCrawlerRequestService.login("0105B122", null, null);
-
-        String orderId = "1909864837421408258";
-
-        ChengTaiPremiumcalParam param = chengTaiAPIService.getPolicyModel(token, orderId);
-
-        ChengTaiCiContract ciContract = param.getCiContract();
-        ChengTaiBiContract biContract = param.getBiContract();
-
-        ChengTaiContractMain contractMain = null;
-        if (ciContract != null) {
-            contractMain = ciContract.getContractMain();
-        }
-        if (contractMain == null && biContract != null) {
-            contractMain = biContract.getContractMain();
-        }
-
-        String contractNo = contractMain.getPolicyNo();
-        String policyUuid = contractMain.getPolicyUuid();
-        String expiryDate = contractMain.getValidDate();
-
-        ChengTaiDownloadAddressResult result = chengTaiAPIService.downloadAddress(token, contractNo, policyUuid, expiryDate);
-
-        assertNotNull(result);
-        assertNotNull(result.getQueryResults());
-
-        System.out.println("==================================================");
-
-        System.out.println(JsonUtil.toJsonString(result));
-
-        System.out.println();
-        System.out.println();
-        System.out.println();
-
-        System.out.println(JsonUtil.toJsonString(result.getUnknownFields()));
-
-        List<ChengTaiDownloadAddressResult.QueryResult> queryResults = result.getQueryResults();
-
-        for (ChengTaiDownloadAddressResult.QueryResult item : queryResults) {
-            System.out.println(item.getDownLoadURL());
-        }
-    }
-}
+//package com.jzg.quotation.taikang.crawler.service;
+//
+//import com.jzg.quotation.chengtai.crawler.JsonUtil;
+//import com.jzg.quotation.chengtai.crawler.model.entity.ChengTaiBiContract;
+//import com.jzg.quotation.chengtai.crawler.model.entity.ChengTaiCiContract;
+//import com.jzg.quotation.chengtai.crawler.model.entity.ChengTaiContractMain;
+//import com.jzg.quotation.chengtai.crawler.model.param.ChengTaiPremiumcalParam;
+//import com.jzg.quotation.chengtai.crawler.model.result.ChengTaiDownloadAddressResult;
+//import com.jzg.quotation.chengtai.crawler.model.result.ChengTaiInsureResult;
+//import com.jzg.quotation.chengtai.crawler.model.result.ChengTaiSystemResult;
+//import com.jzg.quotation.chengtai.crawler.service.ChengTaiAPIService;
+//import com.jzg.quotation.chengtai.crawler.service.ChengTaiCrawlerRequestService;
+//import com.jzg.quotation.summary.SummaryQuotationApplication;
+//import jakarta.annotation.Resource;
+//import org.junit.jupiter.api.BeforeAll;
+//import org.junit.jupiter.api.Test;
+//import org.slf4j.Logger;
+//import org.slf4j.LoggerFactory;
+//import org.springframework.boot.test.context.SpringBootTest;
+//
+//import java.util.List;
+//
+//import static org.junit.jupiter.api.Assertions.assertNotNull;
+//
+//@SpringBootTest(classes = {SummaryQuotationApplication.class})
+//public class ChengTaiCrawlerRequestServiceTest {
+//    private static final Logger logger = LoggerFactory.getLogger(ChengTaiCrawlerRequestServiceTest.class);
+//
+//    @Resource
+//    private ChengTaiCrawlerRequestService chengTaiCrawlerRequestService;
+//
+//    @Resource
+//    public ChengTaiAPIService chengTaiAPIService;
+//
+//    @BeforeAll
+//    public static void befroe() {
+//       // ChengTaiAPIHelper.initAPI("https://b2b.champion-ic.com");
+//    }
+//
+//    @Test
+//    public void login() {
+//        String username = "0105B122";
+//        String password = "Tqct@2024.";
+//        String captcha = "2QVPHjQEJk/FLGkVXPgNndHmbd/ywg0/iZM+6WkEnTOWSiim4s9Ez9dUyvDBF/1S/dR8n4gabCJJ/iOq8b7HT1K1F0YOuOs/jffMBk/T9Cg=";
+//
+//        String token = chengTaiCrawlerRequestService.login(username, password, captcha);
+//
+//        assertNotNull(token);
+//    }
+//
+//    @Test
+//    public void system() {
+//        String token = chengTaiCrawlerRequestService.login("0105B122", null, null);
+//
+//        ChengTaiSystemResult system = chengTaiAPIService.system(token);
+//
+//        assertNotNull(system);
+//    }
+//
+//    @Test
+//    public void getPolicyModel() {
+//        String token = chengTaiCrawlerRequestService.login("0105B122", null, null);
+//
+//        String orderId = "1909779147122143234";
+//
+//        ChengTaiPremiumcalParam result = chengTaiAPIService.getPolicyModel(token, orderId);
+//
+//        assertNotNull(result);
+//
+//        System.out.println("==================================================");
+//
+//        System.out.println(JsonUtil.toJsonString(result));
+//
+//        System.out.println();
+//        System.out.println();
+//        System.out.println();
+//
+//
+//        System.out.println(JsonUtil.toJsonString(result.getUnknownFields()));
+//    }
+//
+//    @Test
+//    public void insure() {
+//        String token = chengTaiCrawlerRequestService.login("0105B122", null, null);
+//
+//        String uuid = "uXu-BI-WTN6M2kEpoZdaDQ";
+//
+//        List<ChengTaiInsureResult> result = chengTaiAPIService.insure(token, uuid);
+//
+//        assertNotNull(result);
+//
+//        System.out.println("==================================================");
+//
+//        System.out.println(JsonUtil.toJsonString(result));
+//
+//        System.out.println();
+//        System.out.println();
+//        System.out.println();
+//
+//
+//        for (ChengTaiInsureResult  item : result) {
+//            System.out.println(JsonUtil.toJsonString(item.getUnknownFields()));
+//
+//            System.out.println(item.getPayUrl());
+//        }
+//    }
+//
+//    @Test
+//    public void downloadAddress() {
+//        String token = chengTaiCrawlerRequestService.login("0105B122", null, null);
+//
+//        String contractNo = "6050400082120250005927";
+//        String policyUuid = "8s3HUoSHRxeLvJcFa40T9g";
+//        String expiryDate = "2026-04-10 00:00:00";
+//
+//        ChengTaiDownloadAddressResult result = chengTaiAPIService.downloadAddress(token, contractNo, policyUuid, expiryDate);
+//
+//        assertNotNull(result);
+//        assertNotNull(result.getQueryResults());
+//
+//        System.out.println("==================================================");
+//
+//        System.out.println(JsonUtil.toJsonString(result));
+//
+//        System.out.println();
+//        System.out.println();
+//        System.out.println();
+//
+//        System.out.println(JsonUtil.toJsonString(result.getUnknownFields()));
+//
+//        List<ChengTaiDownloadAddressResult.QueryResult> queryResults = result.getQueryResults();
+//
+//        for (ChengTaiDownloadAddressResult.QueryResult item : queryResults) {
+//            System.out.println(item.getDownLoadURL());
+//        }
+//    }
+//
+//    @Test
+//    public void downloadAddress2() {
+//        String token = chengTaiCrawlerRequestService.login("0105B122", null, null);
+//
+//        String orderId = "1909864837421408258";
+//
+//        ChengTaiPremiumcalParam param = chengTaiAPIService.getPolicyModel(token, orderId);
+//
+//        ChengTaiCiContract ciContract = param.getCiContract();
+//        ChengTaiBiContract biContract = param.getBiContract();
+//
+//        ChengTaiContractMain contractMain = null;
+//        if (ciContract != null) {
+//            contractMain = ciContract.getContractMain();
+//        }
+//        if (contractMain == null && biContract != null) {
+//            contractMain = biContract.getContractMain();
+//        }
+//
+//        String contractNo = contractMain.getPolicyNo();
+//        String policyUuid = contractMain.getPolicyUuid();
+//        String expiryDate = contractMain.getValidDate();
+//
+//        ChengTaiDownloadAddressResult result = chengTaiAPIService.downloadAddress(token, contractNo, policyUuid, expiryDate);
+//
+//        assertNotNull(result);
+//        assertNotNull(result.getQueryResults());
+//
+//        System.out.println("==================================================");
+//
+//        System.out.println(JsonUtil.toJsonString(result));
+//
+//        System.out.println();
+//        System.out.println();
+//        System.out.println();
+//
+//        System.out.println(JsonUtil.toJsonString(result.getUnknownFields()));
+//
+//        List<ChengTaiDownloadAddressResult.QueryResult> queryResults = result.getQueryResults();
+//
+//        for (ChengTaiDownloadAddressResult.QueryResult item : queryResults) {
+//            System.out.println(item.getDownLoadURL());
+//        }
+//    }
+//}

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 33
tenant/insurance/quotation-taikang/src/test/java/com/jzg/quotation/taikang/crawler/TaiKangHttpClientTest.java


Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff