xuqiang il y a 1 mois
Parent
commit
1579d72145

+ 81 - 177
tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/component/GsCrawlerLoginComponent.java

@@ -1,28 +1,27 @@
 package com.jzg.quotation.guoshou.crawler.component;
 
 import cn.hutool.core.util.ReUtil;
-import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.jzg.commons.entity.quote.vo.AttributionInformationVo;
+import com.jzg.commons.exception.SystemException;
+import com.jzg.commons.util.StringUtils;
 import com.jzg.quotation.commons.component.RequestComponent;
+import com.jzg.quotation.guoshou.crawler.component.enums.RequestUrl;
 import com.jzg.quotation.guoshou.crawler.constant.GsConstants;
+import com.jzg.quotation.guoshou.crawler.entity.response.*;
+import com.jzg.quotation.guoshou.crawler.properties.GuoShouCrawlerProperties;
+import com.jzg.quotation.guoshou.crawler.util.RsaUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.http.HttpResponse;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.HttpClients;
-import org.apache.http.util.EntityUtils;
 import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Component;
+import org.springframework.util.LinkedMultiValueMap;
 
-import java.io.IOException;
 import java.net.URLDecoder;
 import java.nio.charset.StandardCharsets;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.Objects;
 import java.util.concurrent.TimeUnit;
 
 @Slf4j
@@ -30,150 +29,69 @@ import java.util.concurrent.TimeUnit;
 @RequiredArgsConstructor
 
 public class GsCrawlerLoginComponent {
-    private String uname;
-    private String pwd;
-    private String token;
-    private String tkMessage;
-    private String bid;
-    private String userId;
-    private String phone;
-    private String identifyNumber;
-    private String userCode;
-    private String h5Token;
-    private String gstcItem;
-    private String businessOffice;
-    private String provincialCom;
-    private String h5Url;
-    private String viewtoken;
 
+    private final GsCrawlerRequestComponent gsCrawlerRequestComponent;
+    private final GuoShouCrawlerProperties guoShouCrawlerProperties;
     private final StringRedisTemplate redisTemplate;
     private final RequestComponent requestComponent;
+    private final int MAXIMUM_LOGIN = 3;
 
-    /**
-     * 获取token(硬编码部分+接口请求部分)
-     */
-    public void getToken() {
-        // 硬编码token映射
-        Map<String, String> tokenMap = new HashMap<String, String>() {{
-            put("142230198812181723", "9ed09b3d3cf84abf85a63582a5a1ba40");
-            put("140702199001207189", "8aac4ed3e4c44110b37e9bd9d62aaf9c");
-            put("140123198503130219", "20b1e8e8e05347d78afbd46532871a3d");
-        }};
 
-        // 优先使用硬编码token
-        if (tokenMap.containsKey(uname)) {
-            this.token = tokenMap.get(uname);
-            return;
+    public UserInfoResponse.UserData getLoginInfo(AttributionInformationVo attributionInformationVo) {
+        String username = attributionInformationVo.getConfigInfo().get("username");
+        for (int retryCount = 0; retryCount < MAXIMUM_LOGIN; retryCount++) {
+            try {
+                RedisResultDTO redisValue = getRedisKey(attributionInformationVo);
+                UserInfoResponse loginInfo = gsCrawlerRequestComponent.getLoginInfo(redisValue);
+                // 正常返回
+                if (loginInfo != null && "200".equals(loginInfo.getStatus())) {
+                    loginInfo.getData().setRedisResultDTO(redisValue);
+                    redisTemplate.opsForValue().set(GsConstants.GS_REDIS_LOGIN_KEY + username,JSONObject.toJSONString(redisValue),GsConstants.REDIS_EXPIRE_SECONDS, TimeUnit.SECONDS);
+                    return loginInfo.getData();
+                }
+                // 登录失败:清理缓存
+                log.warn("登录信息获取失败,状态异常,username:{},msg:{},重试次数:{}",
+                        username,
+                        loginInfo == null ? "响应为空" : loginInfo.getMsg(),
+                        retryCount + 1);
+                redisTemplate.delete(GsConstants.GS_REDIS_LOGIN_KEY + username);
+            } catch (Exception e) {
+                log.error("调用登录接口出现异常,username:{}", username, e);
+            }
         }
+        // 达到最大重试次数
+        log.error("登录信息获取失败,已达到最大重试次数:{},username:{}", MAXIMUM_LOGIN, username);
+        throw new SystemException("登录信息获取失败,已达到最大重试次数");
+    }
 
-        // 硬编码没有则调用接口
-
-        // 设置请求头
-        HttpHeaders headers = new HttpHeaders();
-        headers.add("Content-Type", GsConstants.CONTENT_TYPE);
-        headers.add("User-Agent", "Android 2.3.7");
-        // 构造请求体
-        JSONObject data = new JSONObject();
-        data.put("password", pwd);
-        data.put("phone", uname);
-        data.put("User-Agent", "Android 2.3.7");
-        try {
-            ResponseEntity<JSONObject> responseEntity = requestComponent.post(GsConstants.CHECK_PASSWORD_URL, JSONObject.toJSONString(data), JSONObject.class, headers);
-            JSONObject body = responseEntity.getBody();
-
-            // 原Python代码中这部分逻辑被注释,这里保留结构
-            /*
-            if ("200".equals(resJson.getString("status"))) {
-                // 获取Set-Cookie(原代码逻辑)
-                this.token = response.getFirstHeader("Set-Cookie").getValue();
-            } else {
-                this.tkMessage = resJson.getString("message");
-            }
-            */
-        } catch (Exception e) {
-            e.printStackTrace();
+    public RedisResultDTO getRedisKey(AttributionInformationVo attributionInformationVo) {
+        String username = attributionInformationVo.getConfigInfo().get("username");
+        RedisResultDTO value = JSONObject.parseObject(redisTemplate.opsForValue().get(GsConstants.GS_REDIS_LOGIN_KEY + username),RedisResultDTO.class);
+        if (Objects.isNull(value)) {
+            return login(attributionInformationVo);
         }
+        return value;
     }
 
+
     /**
      * 获取用户ID等基础信息
      */
-    public void getUserId() {
-        if (token == null || token.isEmpty()) {
-            return;
-        }
-        CloseableHttpClient client = HttpClients.createDefault();
-        HttpGet get = new HttpGet(GsConstants.USER_INFO_URL);
-        // 设置请求头
-        get.setHeader("token", token);
-        get.setHeader("Host", "messh.chinalife-p.com.cn");
-        get.setHeader("User-Agent", "okhttp/4.9.0");
-        get.setHeader("Content-Type", GsConstants.CONTENT_TYPE);
-        get.setHeader("If-Modified-Since", "Mon, 03 Mar 2025 02:55:57 GMT");
-        try {
-            HttpResponse response = client.execute(get);
-            String result = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
-            JSONObject resJson = JSON.parseObject(result);
-            if (!"200".equals(resJson.getString("status"))){
-                throw new RuntimeException("获取用户信息失败");
-            }
-            JSONObject data = resJson.getJSONObject("data");
-            this.bid = data.getString("provinceBid");
-            this.userId = data.getString("userId");
-            this.phone = data.getString("phone");
-            this.identifyNumber = data.getString("userCode");
-        } catch (IOException e) {
-            e.printStackTrace();
-        } finally {
-            try {
-                client.close();
-            } catch (IOException e) {
-                e.printStackTrace();
-            }
-        }
+    public GetUserInfoResponse getUserId(HttpHeaders headers) {
+        return requestComponent.get(RequestUrl.USER_INFO_URL.getRequestUrl(guoShouCrawlerProperties.getBaseUrl()), new LinkedMultiValueMap<>(), null, GetUserInfoResponse.class, headers);
     }
 
     /**
      * 获取用户编码等H5链接相关信息
      */
-    public void getUserCode() {
-        if (token == null || token.isEmpty()) {
-            return;
-        }
-        CloseableHttpClient client = HttpClients.createDefault();
-        HttpGet get = new HttpGet(GsConstants.MY_STORE_URL);
-        // 设置请求头
-        get.setHeader("token", token);
-        get.setHeader("AndroidVersion", "1.1.108");
-        get.setHeader("Host", "messh.chinalife-p.com.cn");
-        get.setHeader("User-Agent", "okhttp/4.9.0");
-        get.setHeader("If-Modified-Since", "Thu, 04 Jul 2024 09:35:54 GMT");
-        try {
-            HttpResponse response = client.execute(get);
-            String result = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
-            log.info("result:{}", result);
-            JSONObject resJson = JSON.parseObject(result);
-            this.h5Url = resJson.getJSONObject("data").getString("jumpLink");
-            log.info("H5链接:{}", h5Url);
-            // 正则提取参数(使用hutool的ReUtil简化正则操作)
-            this.viewtoken = ReUtil.getGroup1("token=(.+)", h5Url);
-            this.userCode = ReUtil.getGroup1("userCode=(.*?)&", h5Url);
-            this.gstcItem = ReUtil.getGroup1("gstcItem=(.*?)&", h5Url);
-        } catch (IOException e) {
-            e.printStackTrace();
-        } finally {
-            try {
-                client.close();
-            } catch (IOException e) {
-                e.printStackTrace();
-            }
-        }
+    public ApiResponse getUserCode(HttpHeaders headers) {
+        return requestComponent.get(RequestUrl.MY_STORE_URL.getRequestUrl(guoShouCrawlerProperties.getBaseUrl()),new LinkedMultiValueMap<>(),"",ApiResponse.class,headers);
     }
 
     /**
      * 获取H5 Token
      */
-    public void getH5Token() {
+    public String getH5Token(String bid) {
         // 设置请求头
         HttpHeaders headers = new HttpHeaders();
         headers.add("Content-Type", GsConstants.CONTENT_TYPE);
@@ -187,21 +105,21 @@ public class GsCrawlerLoginComponent {
         data.put("bid", "");
 
         try {
-            ResponseEntity<JSONObject> responseEntity = requestComponent.post(GsConstants.GET_TOKEN_URL, JSONObject.toJSONString(data), JSONObject.class, headers);
+            headers.set("secretParameter",RsaUtils.generateSecretParameter(data));
+            ResponseEntity<JSONObject> responseEntity = requestComponent.post(RequestUrl.GET_TOKEN_URL.getRequestUrl(guoShouCrawlerProperties.getTokenUrl()),data, JSONObject.class, headers);
             JSONObject body = responseEntity.getBody();
-            this.h5Token = body.getJSONObject("data").getString("token");
+            return  body.getJSONObject("data").getString("token");
         } catch (Exception e) {
             e.printStackTrace();
         }
+        return "";
     }
 
     /**
      * 获取营业网点等信息
      */
-    public void getBusinessOffice() {
-        if (h5Token == null || h5Token.isEmpty() || userCode == null || userCode.isEmpty()) {
-            return;
-        }
+    public LoginInfoResponse getBusinessOffice(String h5Token,String bid,String userCode,String viewtoken) {
+
         // 设置请求头
         HttpHeaders headers = new HttpHeaders();
         headers.add("User-Agent", GsConstants.USER_AGENT);
@@ -214,40 +132,39 @@ public class GsCrawlerLoginComponent {
         data.put("systemSource", "gstc");
         data.put("salesGethdbyhpFlag", "1");
         data.put("token", viewtoken);
-        try {
-            ResponseEntity<JSONObject> responseEntity = requestComponent.post(GsConstants.GET_LOGIN_INFO_URL, JSONObject.toJSONString(data), JSONObject.class, headers);
-            JSONObject jsonObject = responseEntity.getBody().getJSONObject("data");
-            this.businessOffice = jsonObject.getString("userDepartment");
-            this.userId = jsonObject.getString("userCode");
-            this.provincialCom = jsonObject.getString("provincialCom");
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
+        ResponseEntity<LoginInfoResponse> responseEntity = requestComponent.post(RequestUrl.GET_LOGIN_INFO_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()), JSONObject.toJSONString(data), LoginInfoResponse.class, headers);
+        return responseEntity.getBody();
     }
 
     /**
      * @return 结果Map或错误信息
      */
-    public void login(AttributionInformationVo attributionInformationVo) {
+    public RedisResultDTO login(AttributionInformationVo attributionInformationVo) {
         try {
-            this.uname = attributionInformationVo.getConfigInfo().get("username");
-            this.token = attributionInformationVo.getConfigInfo().get("token");
-            if (token != null && !token.isEmpty()) {
-                this.getUserId();
-                this.getUserCode();
-                this.getH5Token();
-                this.getBusinessOffice();
-
-                Map<String, String> result = new HashMap<>();
-                result.put("token", h5Token);
-                result.put("userCode", userCode);
-                result.put("bid", bid);
-                result.put("gstcItem", URLDecoder.decode(gstcItem, StandardCharsets.UTF_8));
-                result.put("businessOffice", businessOffice);
-                result.put("userID", userId);
-                result.put("H5URL", this.h5Url);
-                result.put("viewtoken", viewtoken);
-                redisTemplate.opsForValue().set(GsConstants.GS_REDIS_LOGIN_KEY +this.uname,JSONObject.toJSONString(result),GsConstants.REDIS_EXPIRE_SECONDS, TimeUnit.SECONDS);
+            String uname = attributionInformationVo.getConfigInfo().get("username");
+            String token = attributionInformationVo.getConfigInfo().get("token");
+            if (StringUtils.isNotEmpty(token)) {
+                HttpHeaders httpHeaders = new HttpHeaders();
+                httpHeaders.set("token", token);
+                httpHeaders.set("Host", "messh.chinalife-p.com.cn");
+                httpHeaders.set("User-Agent", "okhttp/4.9.0");
+                httpHeaders.set("Content-Type", GsConstants.CONTENT_TYPE);
+                httpHeaders.set("If-Modified-Since", "Mon, 03 Mar 2025 02:55:57 GMT");
+                GetUserInfoResponse userInfoResponse = getUserId(httpHeaders);
+                GetUserInfoResponse.UserData userData = userInfoResponse.getData();
+                String bid = userData.getProvinceBid();
+                String userId = userData.getUserId();
+                String phone = userData.getPhone();
+                ApiResponse code = getUserCode(httpHeaders);
+                ApiResponse.StoreData data = code.getData();
+                String h5Url = data.getJumpLink();
+                // 正则提取参数(使用hutool的ReUtil简化正则操作)
+                String viewtoken = ReUtil.getGroup1("token=(.+)", h5Url);
+                String userCode = ReUtil.getGroup1("userCode=(.*?)&", h5Url);
+                String gstcItem = ReUtil.getGroup1("gstcItem=(.*?)&", h5Url);
+                String h5Token = getH5Token(bid);
+                LoginInfoResponse businessOffice = getBusinessOffice(h5Token, bid, userCode, viewtoken);
+                return new RedisResultDTO().build(h5Token, userCode, bid, gstcItem, businessOffice.getData().getUserDepartment(), businessOffice.getData().getUserCode(), h5Url, viewtoken);
             } else {
                 throw new RuntimeException("登录失败");
             }
@@ -257,18 +174,5 @@ public class GsCrawlerLoginComponent {
         }
     }
 
-    /**
-     * 获取H5 Token的快捷方法
-     * @return H5 Token
-     */
-//    public String getUrl() {
-//        this.getToken();
-//        if (token != null && !token.isEmpty()) {
-//            this.getUserId();
-//            this.getUserCode();
-//            return h5Token;
-//        }
-//        return null;
-//    }
 
 }

+ 183 - 150
tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/component/GsCrawlerRequestComponent.java

@@ -3,9 +3,11 @@ package com.jzg.quotation.guoshou.crawler.component;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson2.JSONObject;
 import com.jzg.quotation.commons.component.RequestComponent;
+import com.jzg.quotation.guoshou.crawler.component.enums.RequestUrl;
 import com.jzg.quotation.guoshou.crawler.constant.GsConstants;
 import com.jzg.quotation.guoshou.crawler.entity.request.*;
 import com.jzg.quotation.guoshou.crawler.entity.response.*;
+import com.jzg.quotation.guoshou.crawler.properties.GuoShouCrawlerProperties;
 import com.jzg.quotation.guoshou.crawler.util.RsaUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -30,6 +32,7 @@ import java.util.Objects;
 @RequiredArgsConstructor
 public class GsCrawlerRequestComponent {
 
+    private final GuoShouCrawlerProperties guoShouCrawlerProperties;
     private final RequestComponent requestComponent;
     private final RsaUtils rsaUtils;
 
@@ -48,23 +51,6 @@ public class GsCrawlerRequestComponent {
         return headers;
     }
 
-    /**
-     * 从redis字符串中解析token
-     * @param redisValue redis存储的JSON字符串
-     * @return token
-     */
-    public String getToken(String redisValue) {
-        // 空值保护
-        if (redisValue == null || redisValue.isEmpty()) {
-            throw new IllegalArgumentException("redisValue不能为空");
-        }
-        JSONObject jsonObject = JSONObject.parseObject(redisValue);
-        String token = jsonObject.getString("token");
-        if (token == null || token.isEmpty()) {
-            throw new RuntimeException("从redisValue中解析token失败,token为空");
-        }
-        return token;
-    }
 
     /**
      * 通用响应状态检查(JSON对象类型)
@@ -111,7 +97,7 @@ public class GsCrawlerRequestComponent {
         Objects.requireNonNull(token, "token不能为空");
 
         ResponseEntity<GsCrawlerCarQueryResponse> responseEntity = requestComponent.post(
-                GsConstants.CAR_INFO_URL,
+                RequestUrl.CAR_INFO_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(carQueryRequest),
                 GsCrawlerCarQueryResponse.class,
                 getHeaders(token)
@@ -119,8 +105,6 @@ public class GsCrawlerRequestComponent {
 
         GsCrawlerCarQueryResponse body = responseEntity.getBody();
         checkCustomResponseStatus(body, "查询车辆信息");
-        log.info("查询车辆信息成功,结果:{}", body);
-
         // 空值保护
         return body.getData() != null ? body.getData().getData() : List.of();
     }
@@ -128,19 +112,13 @@ public class GsCrawlerRequestComponent {
     /**
      * 查询订单号
      * @param insuranceApplicationEntity 请求参数
-     * @param redisValue redis存储的JSON字符串
      * @return 订单号
      */
-    public String queryOrderNo(InsuranceApplicationEntity insuranceApplicationEntity, String redisValue) {
+    public String queryOrderNo(InsuranceApplicationEntity insuranceApplicationEntity, String token) {
         Objects.requireNonNull(insuranceApplicationEntity, "insuranceApplicationEntity不能为空");
-        Objects.requireNonNull(redisValue, "redisValue不能为空");
-
-        JSONObject jsonObject = JSONObject.parseObject(redisValue);
-        String token = jsonObject.getString("token");
-        Objects.requireNonNull(token, "从redisValue中解析的token不能为空");
 
         ResponseEntity<RenewalSaveResponse> responseEntity = requestComponent.post(
-                GsConstants.ORDER_ID_URL,
+                RequestUrl.ORDER_ID_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(insuranceApplicationEntity),
                 RenewalSaveResponse.class,
                 getHeaders(token)
@@ -148,7 +126,6 @@ public class GsCrawlerRequestComponent {
 
         RenewalSaveResponse body = responseEntity.getBody();
         checkCustomResponseStatus(body, "查询订单号");
-        log.info("查询订单号成功,结果:{}", body);
 
         // 空值保护
         return body.getData() != null ? body.getData().getOrderNo() : "";
@@ -165,7 +142,7 @@ public class GsCrawlerRequestComponent {
         Objects.requireNonNull(token, "token不能为空");
 
         ResponseEntity<CarInsuranceQueryResponse> responseEntity = requestComponent.post(
-                GsConstants.QUERY_INS_URL,
+                RequestUrl.QUERY_INS_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(informationRequest),
                 CarInsuranceQueryResponse.class,
                 getHeaders(token)
@@ -180,21 +157,19 @@ public class GsCrawlerRequestComponent {
 
     /**
      * 获取绑定信息
-     * @param redisValue redis存储的JSON字符串
+     * @param token redis存储的JSON字符串
      * @param userCode 用户编码
      * @return 绑定信息列表
      */
-    public List<JSONObject> getBindInfo(String redisValue, String userCode) {
-        Objects.requireNonNull(redisValue, "redisValue不能为空");
+    public List<JSONObject> getBindInfo(String token, String userCode) {
+        Objects.requireNonNull(token, "redisValue不能为空");
         Objects.requireNonNull(userCode, "userCode不能为空");
 
         Map<String, Object> bindParam = new HashMap<>();
         bindParam.put("userCode", rsaUtils.encrypt(userCode));
         bindParam.put("systemSource", "gstc");
-
-        String token = getToken(redisValue);
         ResponseEntity<JSONObject> responseEntity = requestComponent.post(
-                GsConstants.BIND_INFO_URL,
+                RequestUrl.BIND_INFO_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(bindParam),
                 JSONObject.class,
                 getHeaders(token)
@@ -212,28 +187,25 @@ public class GsCrawlerRequestComponent {
      * @param redisValue redis存储的JSON字符串
      * @return 用户信息响应
      */
-    public UserInfoResponse getLoginInfo(String redisValue) {
+    public UserInfoResponse getLoginInfo(RedisResultDTO redisValue) {
         Objects.requireNonNull(redisValue, "redisValue不能为空");
 
-        JSONObject jsonObject = JSONObject.parseObject(redisValue);
         JSONObject data = new JSONObject();
         try {
-            data.put("userCode", URLDecoder.decode(jsonObject.getString("userCode"), StandardCharsets.UTF_8));
+            data.put("userCode",URLDecoder.decode(redisValue.getUserCode(), StandardCharsets.UTF_8));
         } catch (Exception e) {
             log.error("解码userCode失败", e);
             throw new RuntimeException("解码userCode失败", e);
         }
-        data.put("bid", jsonObject.getString("bid"));
+        data.put("bid", redisValue.getBid());
         data.put("systemSource", "gstc");
         data.put("salesGethdbyhpFlag", "1");
-        data.put("token", jsonObject.getString("viewtoken"));
-
-        String token = getToken(redisValue);
+        data.put("token", redisValue.getViewtoken());
         ResponseEntity<UserInfoResponse> responseEntity = requestComponent.post(
-                GsConstants.GET_LOGIN_INFO_URL,
+                RequestUrl.GET_LOGIN_INFO_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(data),
                 UserInfoResponse.class,
-                getHeaders(token)
+                getHeaders(redisValue.getToken())
         );
 
         // 空值保护
@@ -249,10 +221,8 @@ public class GsCrawlerRequestComponent {
     public SubmitResponse submitInsuranceInformationRequest(SubmitInsuranceInformationRequest submitInsuranceInformationRequest, String token) {
         Objects.requireNonNull(submitInsuranceInformationRequest, "submitInsuranceInformationRequest不能为空");
         Objects.requireNonNull(token, "token不能为空");
-
-        log.info("提交保险信息请求参数:{}", JSONObject.toJSONString(submitInsuranceInformationRequest));
         ResponseEntity<SubmitResponse> responseEntity = requestComponent.post(
-                GsConstants.SUBMIT_INS_URL,
+                RequestUrl.SUBMIT_INS_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(submitInsuranceInformationRequest),
                 SubmitResponse.class,
                 getHeaders(token)
@@ -278,7 +248,7 @@ public class GsCrawlerRequestComponent {
         headers.add("Connection", "keep-alive");
 
         ResponseEntity<JSONObject> responseEntity = requestComponent.post(
-                GsConstants.ENCRYPTION_CONVERT_URL,
+                RequestUrl.ENCRYPTION_CONVERT_URL.getRequestUrl(guoShouCrawlerProperties.getBaseUrl()),
                 JSONObject.toJSONString(jsonObject),
                 JSONObject.class,
                 headers
@@ -305,7 +275,7 @@ public class GsCrawlerRequestComponent {
         jsonObject.put("orderId", orderNo);
 
         ResponseEntity<JSONObject> responseEntity = requestComponent.post(
-                GsConstants.CAR_CONFIRM_URL,
+                RequestUrl.CAR_CONFIRM_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(jsonObject),
                 JSONObject.class,
                 getHeaders(token)
@@ -328,7 +298,7 @@ public class GsCrawlerRequestComponent {
         Objects.requireNonNull(token, "token不能为空");
 
         ResponseEntity<JSONObject> responseEntity = requestComponent.post(
-                GsConstants.UPDATE_CAR_INFO_URL,
+                RequestUrl.UPDATE_CAR_INFO_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(carInfo),
                 JSONObject.class,
                 getHeaders(token)
@@ -350,7 +320,7 @@ public class GsCrawlerRequestComponent {
 
         try {
             ResponseEntity<JSONObject> responseEntity = requestComponent.post(
-                    GsConstants.GET_PLAT_CAR_INFO_URL,
+                    RequestUrl.GET_PLAT_CAR_INFO_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                     JSONObject.toJSONString(platCarInfoRequest),
                     JSONObject.class,
                     getHeaders(token)
@@ -383,7 +353,7 @@ public class GsCrawlerRequestComponent {
 
         try {
             ResponseEntity<InsuranceInitResponse> responseEntity = requestComponent.post(
-                    GsConstants.CALCULATION_INITIALIZATION_URL,
+                    RequestUrl.CALCULATION_INITIALIZATION_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                     JSONObject.toJSONString(initializationRequest),
                     InsuranceInitResponse.class,
                     getHeaders(token)
@@ -412,16 +382,13 @@ public class GsCrawlerRequestComponent {
         Objects.requireNonNull(token, "token不能为空");
 
         try {
-            log.info("开始计算保费,请求参数:{}", JSONObject.toJSONString(doCalculateRequest));
             ResponseEntity<PremiumCalculateResponse> responseEntity = requestComponent.post(
-                    GsConstants.CALCULATE_URL,
+                    RequestUrl.CALCULATE_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                     JSONObject.toJSONString(doCalculateRequest),
                     PremiumCalculateResponse.class,
                     getHeaders(token)
             );
-
             PremiumCalculateResponse body = responseEntity.getBody();
-            log.info("保费计算成功,结果:{}", body != null ? JSONObject.toJSONString(body.getData()) : "无数据");
             return Objects.requireNonNull(body, "保费计算响应体为空");
         } catch (Exception e) {
             e.printStackTrace();
@@ -439,18 +406,14 @@ public class GsCrawlerRequestComponent {
     public FeeCalculateResponse.DataDTO creatOrder(String token, JSONObject data) {
         Objects.requireNonNull(token, "token不能为空");
         Objects.requireNonNull(data, "data不能为空");
-
         ResponseEntity<FeeCalculateResponse> responseEntity = requestComponent.post(
-                GsConstants.CREAT_ORDER_URL,
+                RequestUrl.CREAT_ORDER_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(data),
                 FeeCalculateResponse.class,
                 getHeaders(token)
         );
-
         FeeCalculateResponse body = responseEntity.getBody();
         checkCustomResponseStatus(body, "创建订单");
-        log.info("创建订单成功");
-
         // 空值保护
         return body.getData() != null ? body.getData() : null;
     }
@@ -469,15 +432,13 @@ public class GsCrawlerRequestComponent {
         accidentParam.put("tranNo", orderId);
 
         ResponseEntity<JSONObject> responseEntity = requestComponent.post(
-                GsConstants.DO_ACCIDENT_RECORD,
+                RequestUrl.DO_ACCIDENT_RECORD.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(accidentParam),
                 JSONObject.class,
                 getHeaders(token)
         );
-
         JSONObject body = responseEntity.getBody();
         checkJsonResponseStatus(body, "添加事故记录");
-
         // 空值保护
         JSONObject data = body.getJSONObject("data");
         return data != null ? data : new JSONObject();
@@ -486,71 +447,59 @@ public class GsCrawlerRequestComponent {
     /**
      * 自动生成数据
      * @param generateDataRequest 请求参数
-     * @param redisValue redis存储的JSON字符串
+     * @param token redis存储的JSON字符串
      */
-    public void doAutoGenerate(GenerateDataRequest generateDataRequest, String redisValue) {
+    public void doAutoGenerate(GenerateDataRequest generateDataRequest, String token) {
         Objects.requireNonNull(generateDataRequest, "generateDataRequest不能为空");
-        Objects.requireNonNull(redisValue, "redisValue不能为空");
-
-        String token = getToken(redisValue);
+        Objects.requireNonNull(token, "redisValue不能为空");
         ResponseEntity<JSONObject> responseEntity = requestComponent.post(
                 GsConstants.DO_AUTO_GENERATE,
                 JSONObject.toJSONString(generateDataRequest),
                 JSONObject.class,
                 getHeaders(token)
         );
-
-        log.info("自动生成数据成功,响应:{}", JSONObject.toJSONString(responseEntity.getBody()));
     }
 
     /**
      * 获取MES订单详情
-     * @param redisValue redis存储的JSON字符串
+     * @param token redis存储的JSON字符串
      * @param value 请求参数
      * @return 订单详情
      */
-    public JSONObject doMesOrderDetail(String redisValue, JSONObject value) {
-        Objects.requireNonNull(redisValue, "redisValue不能为空");
+    public JSONObject doMesOrderDetail(String token, JSONObject value) {
+        Objects.requireNonNull(token, "redisValue不能为空");
         Objects.requireNonNull(value, "value不能为空");
-
         JSONObject detailData = new JSONObject();
         detailData.put("orderNo", value.getString("orderId"));
         detailData.put("structureId", value.getString("structureId"));
         detailData.put("userCode", value.getString("userCode"));
         detailData.put("userLoginType", "1");
         detailData.put("sellCode", null);
-
-        String token = getToken(redisValue);
         ResponseEntity<JSONObject> responseEntity = requestComponent.post(
-                GsConstants.DO_MESORDER_DETAIL,
+                RequestUrl.DO_MESORDER_DETAIL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(detailData),
                 JSONObject.class,
                 getHeaders(token)
         );
-
         JSONObject body = responseEntity.getBody();
         checkJsonResponseStatus(body, "获取MES订单详情");
-        log.info("获取MES订单详情成功,响应:{}", JSONObject.toJSONString(body));
-
         return body;
     }
 
     /**
      * 获取上传状态
-     * @param redisValue redis存储的JSON字符串
+     * @param token redis存储的JSON字符串
      * @param quote 报价信息
      */
-    public void getUploadSuccess(String redisValue, JSONObject quote) {
-        Objects.requireNonNull(redisValue, "redisValue不能为空");
+    public void getUploadSuccess(String token, JSONObject quote) {
+        Objects.requireNonNull(token, "redisValue不能为空");
         Objects.requireNonNull(quote, "quote不能为空");
 
         JSONObject uploadStatusData = new JSONObject();
         uploadStatusData.put("orderNo", quote.getString("orderId"));
         uploadStatusData.put("userCode", quote.getString("userCode"));
-
-        String token = getToken(redisValue);
         ResponseEntity<JSONObject> responseEntity = requestComponent.post(
-                GsConstants.GET_UPLOAD_SUCCESS,
+                RequestUrl.GET_UPLOAD_SUCCESS.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(uploadStatusData),
                 JSONObject.class,
                 getHeaders(token)
@@ -558,68 +507,58 @@ public class GsCrawlerRequestComponent {
 
         JSONObject body = responseEntity.getBody();
         checkJsonResponseStatus(body, "获取上传状态");
-        log.info("获取上传状态成功,响应:{}", JSONObject.toJSONString(body));
     }
 
     /**
      * 查询日志
-     * @param redisValue redis存储的JSON字符串
+     * @param token redis存储的JSON字符串
      * @param logData 日志查询参数
      * @return 日志响应
      */
-    public QueryLogResponse doQueryLog(String redisValue, JSONObject logData) {
-        Objects.requireNonNull(redisValue, "redisValue不能为空");
+    public QueryLogResponse doQueryLog(String token, JSONObject logData) {
+        Objects.requireNonNull(token, "redisValue不能为空");
         Objects.requireNonNull(logData, "logData不能为空");
-
-        String token = getToken(redisValue);
         ResponseEntity<QueryLogResponse> responseEntity = requestComponent.post(
-                GsConstants.DO_QUERY_LOG,
+                RequestUrl.DO_QUERY_LOG.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(logData),
                 QueryLogResponse.class,
                 getHeaders(token)
         );
-
         return Objects.requireNonNull(responseEntity.getBody(), "查询日志响应体为空");
     }
 
     /**
      * 检查图片
-     * @param redisValue redis存储的JSON字符串
+     * @param token redis存储的JSON字符串
      * @param uploadRequest 图片上传请求
      * @return 图片检查响应
      */
-    public CheckImageResponse doCheckImage(String redisValue, ImageUploadRequest uploadRequest) {
-        Objects.requireNonNull(redisValue, "redisValue不能为空");
+    public CheckImageResponse doCheckImage(String token, ImageUploadRequest uploadRequest) {
+        Objects.requireNonNull(token, "redisValue不能为空");
         Objects.requireNonNull(uploadRequest, "uploadRequest不能为空");
-
-        String token = getToken(redisValue);
         ResponseEntity<CheckImageResponse> responseEntity = requestComponent.post(
-                GsConstants.CHECK_IMAGES_ALL,
+                RequestUrl.CHECK_IMAGES_ALL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(uploadRequest),
                 CheckImageResponse.class,
                 getHeaders(token)
         );
-
         return Objects.requireNonNull(responseEntity.getBody(), "检查图片响应体为空");
     }
 
     /**
      * 上传图片
      * @param imageBusinessRequest 图片上传请求
-     * @param redisValue redis存储的JSON字符串
+     * @param token redis存储的JSON字符串
      */
-    public void uploadImages(UploadImagesRequest imageBusinessRequest, String redisValue) {
+    public void uploadImages(UploadImagesRequest imageBusinessRequest, String token) {
         Objects.requireNonNull(imageBusinessRequest, "imageBusinessRequest不能为空");
-        Objects.requireNonNull(redisValue, "redisValue不能为空");
-
-        String token = getToken(redisValue);
+        Objects.requireNonNull(token, "redisValue不能为空");
         ResponseEntity<UploadImageResponse> responseEntity = requestComponent.post(
-                GsConstants.UPLOAD_URL,
-                JSONObject.toJSONString(imageBusinessRequest),
+                RequestUrl.UPLOAD_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
+                imageBusinessRequest,
                 UploadImageResponse.class,
                 getHeaders(token)
         );
-
         UploadImageResponse body = responseEntity.getBody();
         checkCustomResponseStatus(body, "上传图片");
         log.info("上传图片成功");
@@ -628,42 +567,36 @@ public class GsCrawlerRequestComponent {
     /**
      * 完成核保任务
      * @param heBaoData 核保数据
-     * @param redisValue redis存储的JSON字符串
+     * @param token redis存储的JSON字符串
      * @return 核保响应
      */
-    public JSONObject doCompleteTask(OrderEntity heBaoData, String redisValue) {
+    public JSONObject doCompleteTask(OrderEntity heBaoData, String token) {
         Objects.requireNonNull(heBaoData, "heBaoData不能为空");
-        Objects.requireNonNull(redisValue, "redisValue不能为空");
-
-        String token = getToken(redisValue);
+        Objects.requireNonNull(token, "redisValue不能为空");
         ResponseEntity<JSONObject> responseEntity = requestComponent.post(
-                GsConstants.HE_BAO_URL,
+                RequestUrl.HE_BAO_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(heBaoData),
                 JSONObject.class,
                 getHeaders(token)
         );
-
         return Objects.requireNonNull(responseEntity.getBody(), "完成核保任务响应体为空");
     }
 
     /**
      * 获取认证token
      * @param tokenData token请求数据
-     * @param redisValue redis存储的JSON字符串
+     * @param token redis存储的JSON字符串
      * @return token响应
      */
-    public JSONObject getTokenUrl(Map<String, Object> tokenData, String redisValue) {
+    public JSONObject getTokenUrl(Map<String, Object> tokenData, String token) {
         Objects.requireNonNull(tokenData, "tokenData不能为空");
-        Objects.requireNonNull(redisValue, "redisValue不能为空");
-
-        String token = getToken(redisValue);
+        Objects.requireNonNull(token, "redisValue不能为空");
         ResponseEntity<JSONObject> responseEntity = requestComponent.post(
-                GsConstants.GET_AUTH_TOKEN,
+                RequestUrl.GET_AUTH_TOKEN.getRequestUrl(guoShouCrawlerProperties.getBaseUrl()),
                 JSONObject.toJSONString(tokenData),
                 JSONObject.class,
                 getHeaders(token)
         );
-
         return Objects.requireNonNull(responseEntity.getBody(), "获取认证token响应体为空");
     }
 
@@ -676,17 +609,16 @@ public class GsCrawlerRequestComponent {
     public ResponseDTO getShareInfo(JSONObject tokenResponse, String redisValue) {
         Objects.requireNonNull(tokenResponse, "tokenResponse不能为空");
         Objects.requireNonNull(redisValue, "redisValue不能为空");
-
         MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
         JSONObject data = tokenResponse.getJSONObject("data");
         Objects.requireNonNull(data, "tokenResponse中的data不能为空");
         formData.set("id", data.getString("id"));
-
-        HttpHeaders headers = getHeaders(getToken(redisValue));
+        //String token = getToken(redisValue);
+        HttpHeaders headers = getHeaders("token");
         headers.add("Content-Type", "application/x-www-form-urlencoded");
 
         ResponseEntity<ResponseDTO> responseEntity = requestComponent.form(
-                GsConstants.GET_SHARE_INFO,
+                RequestUrl.GET_SHARE_INFO.getRequestUrl(guoShouCrawlerProperties.getBaseUrl()),
                 formData,
                 ResponseDTO.class,
                 headers
@@ -694,7 +626,6 @@ public class GsCrawlerRequestComponent {
 
         ResponseDTO body = responseEntity.getBody();
         Objects.requireNonNull(body, "获取分享信息响应体为空");
-
         // 特殊状态校验
         if (!"SUCCESS".equals(body.getStatus()) && !"查看成功".equals(body.getMsg())) {
             throw new RuntimeException("获取分享信息失败:" + body.getMsg());
@@ -721,7 +652,7 @@ public class GsCrawlerRequestComponent {
         removeData.put("userLoginType", "1");
 
         ResponseEntity<JSONObject> responseEntity = requestComponent.post(
-                GsConstants.REMOVE_ORDER_URL,
+                RequestUrl.REMOVE_ORDER_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(removeData),
                 JSONObject.class,
                 getHeaders(token)
@@ -749,18 +680,15 @@ public class GsCrawlerRequestComponent {
         data.put("queryWord", "");
         data.put("businessOffice", jsonObject.getString("businessOffice"));
         data.put("authority", "2");
-
-        // 修复原代码bug:请求体应该传data而不是jsonObject
         ResponseEntity<JSONObject> responseEntity = requestComponent.post(
-                GsConstants.GET_FROMCAR_PRODUCTS_URL,
+                RequestUrl.GET_FROMCAR_PRODUCTS_URL.getRequestUrl(guoShouCrawlerProperties.getBaseUrl()),
                 JSONObject.toJSONString(data),
                 JSONObject.class,
-                getHeaders(getToken(redisValue))
+                getHeaders("token")
         );
 
         JSONObject body = responseEntity.getBody();
         checkJsonResponseStatus(body, "获取非车险信息");
-        log.info("获取非车险信息成功,响应:{}", JSONObject.toJSONString(body));
     }
 
     /**
@@ -778,9 +706,8 @@ public class GsCrawlerRequestComponent {
         JSONObject data = new JSONObject();
         data.put("orderId", orderNo);
         data.put("userLoginCode", bindInfo.getString("userCode"));
-
         ResponseEntity<JSONObject> responseEntity = requestComponent.post(
-                GsConstants.SALES_FCBE_LONG_INFO_URL,
+                RequestUrl.SALES_FCBE_LONG_INFO_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(data),
                 JSONObject.class,
                 getHeaders(token)
@@ -788,7 +715,6 @@ public class GsCrawlerRequestComponent {
 
         JSONObject body = responseEntity.getBody();
         checkJsonResponseStatus(body, "获取非车险归属信息");
-
         // 空值保护
         return body.getJSONObject("data") != null ? body.getJSONObject("data") : new JSONObject();
     }
@@ -796,21 +722,20 @@ public class GsCrawlerRequestComponent {
     /**
      * 获取订单详情
      * @param id 订单ID
-     * @param redisValue redis存储的JSON字符串
+     * @param token redis存储的JSON字符串
      * @return 订单详情
      */
-    public JSONObject getOrderDetail(String id, String redisValue) {
+    public JSONObject getOrderDetail(String id, String token) {
         Objects.requireNonNull(id, "id不能为空");
-        Objects.requireNonNull(redisValue, "redisValue不能为空");
+        Objects.requireNonNull(token, "redisValue不能为空");
 
         MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
         formData.set("id", id);
-
-        HttpHeaders headers = getHeaders(getToken(redisValue));
+        HttpHeaders headers = getHeaders(token);
         headers.add("Content-Type", "application/x-www-form-urlencoded");
 
         ResponseEntity<JSONObject> responseEntity = requestComponent.form(
-                GsConstants.GET_ORDER_DETAIL_URL,
+                RequestUrl.GET_ORDER_DETAIL_URL.getRequestUrl(guoShouCrawlerProperties.getBaseUrl()),
                 formData,
                 JSONObject.class,
                 headers
@@ -822,16 +747,15 @@ public class GsCrawlerRequestComponent {
     /**
      * 获取MES订单列表
      * @param doMesOrdersRequest 请求参数
-     * @param redisValue redis存储的JSON字符串
+     * @param token redis存储的JSON字符串
      * @return 订单列表
      */
-    public JSONObject doMesOrders(DoMesOrdersRequest doMesOrdersRequest, String redisValue) {
+    public JSONObject doMesOrders(DoMesOrdersRequest doMesOrdersRequest, String token) {
         Objects.requireNonNull(doMesOrdersRequest, "doMesOrdersRequest不能为空");
-        Objects.requireNonNull(redisValue, "redisValue不能为空");
+        Objects.requireNonNull(token, "redisValue不能为空");
 
-        String token = getToken(redisValue);
         ResponseEntity<JSONObject> responseEntity = requestComponent.post(
-                GsConstants.DO_MES_ORDERS_URL,
+                RequestUrl.DO_MES_ORDERS_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(doMesOrdersRequest),
                 JSONObject.class,
                 getHeaders(token)
@@ -845,4 +769,113 @@ public class GsCrawlerRequestComponent {
     }
 
 
+    public JSONObject encryptionConvert(MultiValueMap<String, String> formData, String token) {
+        HttpHeaders headers = getHeaders(token);
+        headers.add("Connection", "keep-alive");
+        headers.set("Content-Type","application/x-www-form-urlencoded;charset=UTF-8");
+        ResponseEntity<JSONObject> responseEntity = requestComponent.form(
+                RequestUrl.ENCRYPTIONCONVERT_URL.getRequestUrl(guoShouCrawlerProperties.getBaseUrl()),
+                formData,
+                JSONObject.class,
+                headers
+        );
+        JSONObject body = responseEntity.getBody();
+        return body;
+    }
+
+    public JSONObject employeeLogin(MultiValueMap<String, String> data2, String token) {
+        HttpHeaders headers = getHeaders(token);
+        headers.add("Connection", "keep-alive");
+        headers.set("Content-Type","application/x-www-form-urlencoded;charset=UTF-8");
+        ResponseEntity<JSONObject> responseEntity = requestComponent.form(
+                RequestUrl.EMPLOYEELOGIN_URL.getRequestUrl(guoShouCrawlerProperties.getBaseUrl()),
+                data2,
+                JSONObject.class,
+                headers
+        );
+
+        return responseEntity.getBody();
+    }
+
+    public JSONObject fromCarModelCheck(JSONObject data3, String token) {
+
+        ResponseEntity<JSONObject> responseEntity = requestComponent.post(
+                RequestUrl.FROMCARMODELCHECK_URL.getRequestUrl(guoShouCrawlerProperties.getBaseUrl()),
+                data3,
+                JSONObject.class,
+                getHeaders(token)
+        );
+        return responseEntity.getBody();
+    }
+
+    public JSONObject getUnderwritingById( MultiValueMap<String, String> data4, String token) {
+        ResponseEntity<JSONObject> responseEntity = requestComponent.form(
+                RequestUrl.GET_UNDERWRITING_URL.getRequestUrl(guoShouCrawlerProperties.getBaseUrl()),
+                data4,
+                JSONObject.class,
+                getHeaders(token)
+        );
+        log.info("===============",JSONObject.toJSONString(responseEntity));
+        return responseEntity.getBody();
+    }
+
+    public JSONObject underwritingPre(JSONObject nextData, String token,String bid) {
+        HttpHeaders headers = getHeaders(token);
+        headers.add("bid",bid);
+        ResponseEntity<JSONObject> responseEntity = requestComponent.post(
+                RequestUrl.UNDERWRITING_PRE_URL.getRequestUrl(guoShouCrawlerProperties.getBaseUrl()),
+                nextData,
+                JSONObject.class,
+                headers
+
+        );
+
+        return responseEntity.getBody();
+    }
+
+    public JSONObject getProductInfoById(MultiValueMap<String, String> data3, String token) {
+        ResponseEntity<JSONObject> responseEntity = requestComponent.form(
+                RequestUrl.GET_PRODUCT_INFO_BY_ID_URL.getRequestUrl(guoShouCrawlerProperties.getBaseUrl()),
+                data3,
+                JSONObject.class,
+                getHeaders(token)
+        );
+        log.info("===============",JSONObject.toJSONString(responseEntity));
+        return responseEntity.getBody();
+    }
+
+    public JSONObject getIndividualVo(MultiValueMap<String, String> data4, String token) {
+        ResponseEntity<JSONObject> responseEntity = requestComponent.form(
+                RequestUrl.GET_INDIVIDUAL_VO_URL.getRequestUrl(guoShouCrawlerProperties.getBaseUrl()),
+                data4,
+                JSONObject.class,
+                getHeaders(token)
+        );
+        log.info("===============",JSONObject.toJSONString(responseEntity));
+        return responseEntity.getBody();
+    }
+
+    public JSONObject findAgentRate(JSONObject data7, String token) {
+        ResponseEntity<JSONObject> responseEntity = requestComponent.post(
+                RequestUrl.FINDAGENTRATE_URL.getRequestUrl(guoShouCrawlerProperties.getBaseUrl()),
+                data7,
+                JSONObject.class,
+                getHeaders(token)
+
+        );
+        return responseEntity.getBody();
+    }
+
+    public JSONObject underwritingVariablePremiumVariablePremium(JSONObject data8vo, String token) {
+        HttpHeaders headers = getHeaders(token);
+        headers.add("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8");
+        ResponseEntity<JSONObject> responseEntity = requestComponent.post(
+                RequestUrl.UNDERWRITINGVARIABLE_PREMIUMVARIABLE_PREMIUM_URL.getRequestUrl(guoShouCrawlerProperties.getBaseUrl()),
+                data8vo,
+                JSONObject.class,
+                headers
+
+        );
+        return responseEntity.getBody();
+    }
 }

+ 2 - 2
tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/entity/request/CreatOrderRequest.java

@@ -9,14 +9,14 @@ import lombok.Data;
 public class CreatOrderRequest {
 
 
-    public static JSONObject creatOrderRequest(PremiumCalculateResponse.DataDTO dataDTO, String syShow, String redisValue, UserInfoResponse.UserData loginInfo){
+    public static JSONObject creatOrderRequest(PremiumCalculateResponse.DataDTO dataDTO, String syShow,String userID, UserInfoResponse.UserData loginInfo){
         // 构建请求参数
         JSONObject data = JSONObject.parseObject(JSONObject.toJSONString(dataDTO));
         data.put("syShow", syShow);
         data.put("businessNatureCode", "");
         data.put("businessOffice", loginInfo.getUserDepartment());
         data.put("structureId", loginInfo.getProvincialCom());
-        data.put("userCode", JSONObject.parseObject(redisValue).getString("userID"));
+        data.put("userCode",userID);
         data.put("reformFlag", "1");
         data.put("oriSysOperator", "EM2_user");
         data.put("oriSysOperatorKey", "RU0yZW0y");

+ 28 - 4
tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/entity/request/GuoShouCrawlerQuoteResultsVoBuild.java

@@ -2,12 +2,14 @@ package com.jzg.quotation.guoshou.crawler.entity.request;
 
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson2.JSONObject;
-import com.google.common.collect.Lists;
 import com.jzg.commons.constants.dict.InsOrderStatusEnum;
+import com.jzg.commons.entity.quote.vo.KindInfoVo;
 import com.jzg.commons.entity.quote.vo.QuoteVo;
+import com.jzg.commons.entity.quote.vo.RiskInfoVo;
 import com.jzg.commons.entity.quote.vo.aggregated.QuoteResultsVo;
 import com.jzg.quotation.guoshou.crawler.entity.response.PremiumCalculateResponse;
 
+import java.util.List;
 import java.util.Map;
 
 public class GuoShouCrawlerQuoteResultsVoBuild {
@@ -17,9 +19,8 @@ public class GuoShouCrawlerQuoteResultsVoBuild {
         PremiumCalculateResponse.OrderVoDTO orderVo = premiumCalculateResponse.getData().getOrderVo();
         QuoteResultsVo quoteResultsVo = new QuoteResultsVo();
         quoteResultsVo.setOrdersNo(quoteVo.getOrder().getOrdersNo());
-        quoteResultsVo.setCiRiskInfoVo(quoteVo.getCiRiskInfoVo());
-        quoteResultsVo.setBiRiskInfoVo(quoteVo.getBiRiskInfoVo());
-        quoteResultsVo.setKindInfoVo(Lists.newArrayList());
+        quoteResultsVo.setCiRiskInfoVo(buildRiskInfoVo(premiumCalculateResponse,quoteVo.getCiRiskInfoVo()));
+        quoteResultsVo.setBiRiskInfoVo(quoteResultsVo.getBiRiskInfoVo());
         quoteResultsVo.setCiStartDate(orderVo.getJqStartDate());
         quoteResultsVo.setCiEndDate(orderVo.getJqEndDate());
         quoteResultsVo.setBiStartDate(orderVo.getSyStartDate());
@@ -31,6 +32,29 @@ public class GuoShouCrawlerQuoteResultsVoBuild {
         return quoteResultsVo;
     }
 
+    /**
+     * 构造交强商业时间信息
+     * @param premiumCalculateResponse 保司返回险种信息
+     */
+    private static RiskInfoVo buildRiskInfoVo(PremiumCalculateResponse premiumCalculateResponse,RiskInfoVo ciRiskInfoVo) {
+        ciRiskInfoVo.setStartDate(premiumCalculateResponse.getData().getOrderVo().getJqStartDate());
+        ciRiskInfoVo.setEndDate(premiumCalculateResponse.getData().getOrderVo().getJqEndDate());
+        return ciRiskInfoVo;
+
+    }
+
+
+
+    /**
+     * 构造商业险险种信息
+     *
+     * @param kindInfoVo 商业险险种信息
+     * @param DataDTO dataDTO   保司返回商业险险种信息
+     */
+    private static void buildKindInfo(List<KindInfoVo> kindInfoVo,PremiumCalculateResponse.DataDTO dataDTO) {
+
+    }
+
     private static QuoteResultsVo.ScoreVo getScoreVo(PremiumCalculateResponse premiumCalculateResponse,Map<String, String> accidentResult){
         PremiumCalculateResponse.OrderVoDTO orderVo = premiumCalculateResponse.getData().getOrderVo();
         QuoteResultsVo.ScoreVo scoreVo = new QuoteResultsVo.ScoreVo();

+ 4 - 4
tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/entity/request/InsuranceApplicationEntity.java

@@ -2,6 +2,7 @@ package com.jzg.quotation.guoshou.crawler.entity.request;
 
 import com.alibaba.fastjson2.JSONObject;
 import com.jzg.commons.util.StringUtils;
+import com.jzg.quotation.guoshou.crawler.entity.response.RedisResultDTO;
 import com.jzg.quotation.guoshou.crawler.entity.response.UserInfoResponse;
 import lombok.Data;
 
@@ -13,8 +14,7 @@ import lombok.Data;
 public class InsuranceApplicationEntity {
 
 
-    public InsuranceApplicationEntity(String redisValue, JSONObject bindInfo, UserInfoResponse.UserData loginInfo, String licenseNo, String userCode, String energyTypeCode) {
-        JSONObject jsonObject = JSONObject.parseObject(redisValue);
+    public InsuranceApplicationEntity(RedisResultDTO redisResultDTO, JSONObject bindInfo, UserInfoResponse.UserData loginInfo, String licenseNo, String userCode, String energyTypeCode) {
         this.businessOffice =loginInfo.getUserDepartment();
         this.businessOfficeName = loginInfo.getGroupType();
         this.structureId = loginInfo.getProvincialCom();
@@ -31,7 +31,7 @@ public class InsuranceApplicationEntity {
         this.licnesTypeName = "小型汽车号牌";
         this.positionCode = "";
         this.positionName = "";
-        this.loginUserCode = jsonObject.getString("userID");
+        this.loginUserCode = redisResultDTO.getUserID();
         this.lifeInsuranceUserCode = null;
         this.newCarFlag = "0";
         this.bindId = bindInfo.getString("id");
@@ -67,7 +67,7 @@ public class InsuranceApplicationEntity {
         this.oriSysOperator = loginInfo.getOriSysOperator();
         this.oriSysOperatorKey = loginInfo.getOriSysOperatorKey();
         this.bpUserCode = null;
-        this.gstcItem = jsonObject.getString("gstcItem");
+        this.gstcItem = redisResultDTO.getGstcItem();
         this.collectionSourcesName = null;
         this.collectionSourcesCode = null;
         this.customerPhone = "";

+ 5 - 4
tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/entity/request/SubmitInsuranceInformationRequest.java

@@ -215,7 +215,7 @@ public class SubmitInsuranceInformationRequest {
         mesOrderVo.setDocSalePracticeNo("");
         mesOrderVo.setDocSalesPhone("");
         mesOrderVo.setIfFalse("2");
-        mesOrderVo.setAgreeCustomerShareFlag("0");
+        mesOrderVo.setAgreeCustomerShareFlag(null);
         mesOrderVo.setAgreementFixedFlag("0");
         mesOrderVo.setApplicantToCarowner("1");
         mesOrderVo.setPublicinsurantToApplicant("1");
@@ -248,7 +248,7 @@ public class SubmitInsuranceInformationRequest {
         carVoFront.setBrandCode(vehicleModelDetail.getBrandCode());
         carVoFront.setBrandName(vehicleModelDetail.getBrandName());
         carVoFront.setRbCode(vehicleModelDetail.getRbCode());
-        carVoFront.setVehiclecode(vehicleModelDetail.getStandardName());
+        carVoFront.setVehiclecode(vehicleModelDetail.getPlatModelCode());
         carVoFront.setVehiclestyledesc(vehicleModelDetail.getStandardName());
         carVoFront.setExhaustscale(vehicleModelDetail.getDisplacement());
         carVoFront.setPassengersNumber(vehicleModelDetail.getSeat());
@@ -306,7 +306,7 @@ public class SubmitInsuranceInformationRequest {
         carVoFront.setChgownerflag(carInfoVo.isTransfer() ? "1" : "0");
         carVoFront.setEngineNo(RsaUtils.encrypt(carInfoVo.getEngineNo()));
         carVoFront.setEnrollDate(carInfoVo.getRegisterDate());
-        carVoFront.setBuyDate(carInfoVo.getIssueDate());
+        carVoFront.setBuyDate(carInfoVo.getRegisterDate());
         carVoFront.setForeignCarFlag("0");
         carVoFront.setFrameNo(RsaUtils.encrypt(carInfoVo.getVinNo()));
         carVoFront.setLicenseNo(RsaUtils.encrypt(carInfoVo.getLicenseNo()));
@@ -886,6 +886,7 @@ public class SubmitInsuranceInformationRequest {
         @JsonProperty("carUserCodeName")
         private String carUserCodeName;
 
+//        发证日期
         @JsonProperty("certificateDate")
         private String certificateDate;
 
@@ -900,7 +901,7 @@ public class SubmitInsuranceInformationRequest {
 
         @JsonProperty("engineNo")
         private String engineNo;
-
+//初登日期
         @JsonProperty("enrollDate")
         private String enrollDate;
 

+ 3 - 0
tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/entity/response/UserInfoResponse.java

@@ -158,6 +158,9 @@ public class UserInfoResponse {
          * 用户登录类型
          */
         private String userLoginType;
+
+        private RedisResultDTO redisResultDTO;
+
     }
 
     /**

+ 592 - 123
tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/service/Impl/GuoshouCrawlerRequestImpl.java

@@ -6,6 +6,7 @@ import com.alibaba.fastjson.TypeReference;
 import com.alibaba.fastjson2.JSONArray;
 import com.alibaba.fastjson2.JSONObject;
 import com.jzg.commons.constants.dict.InsOrderStatusEnum;
+import com.jzg.commons.entity.orders.po.InsOrders;
 import com.jzg.commons.entity.quote.vo.*;
 import com.jzg.commons.entity.quote.vo.aggregated.*;
 import com.jzg.commons.entity.quote.vo.base.LoginBase;
@@ -19,6 +20,7 @@ import com.jzg.quotation.commons.entity.DetectLoginRequest;
 import com.jzg.quotation.commons.entity.GetCaptchaRequest;
 import com.jzg.quotation.commons.entity.GetCaptchaResponse;
 import com.jzg.quotation.commons.filter.CarModelsFilterUtils;
+import com.jzg.quotation.commons.utils.TimeProcessing;
 import com.jzg.quotation.guoshou.crawler.component.GsCrawlerLoginComponent;
 import com.jzg.quotation.guoshou.crawler.component.GsCrawlerRequestComponent;
 import com.jzg.quotation.guoshou.crawler.constant.GsConstants;
@@ -27,7 +29,7 @@ import com.jzg.quotation.guoshou.crawler.entity.response.*;
 import com.jzg.quotation.guoshou.crawler.service.GuoshouCrawlerRequest;
 import com.jzg.quotation.guoshou.crawler.util.DateUtils;
 import com.jzg.quotation.guoshou.crawler.util.FirstMatchUtils;
-import com.jzg.quotation.guoshou.crawler.util.QrCodeReader;
+import com.jzg.quotation.guoshou.crawler.util.ModularDataProcessor;
 import com.jzg.quotation.guoshou.crawler.util.RsaUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -38,14 +40,14 @@ import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.pdfbox.pdmodel.PDDocument;
 import org.apache.pdfbox.text.PDFTextStripper;
 import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
 
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.time.LocalDate;
+import java.util.*;
 import java.util.concurrent.TimeUnit;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -63,6 +65,7 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
 
     private final GsCrawlerRequestComponent gsCrawlerRequestComponent;
     private final GsCrawlerLoginComponent gsCrawlerLoginComponent;
+    private final ModularDataProcessor dataProcessor;
     private final StringRedisTemplate redisTemplate;
     private final RsaUtils rsaUtils;
     private final OrgClient orgClient;
@@ -91,7 +94,7 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
             configInfo.put("username", username);
             configInfo.put("password", password);
             attributionInformationVo.setConfigInfo(configInfo);
-            return getLoginInfo(attributionInformationVo) != null;
+            return gsCrawlerLoginComponent.getLoginInfo(attributionInformationVo) != null;
         }
         return true;
     }
@@ -101,23 +104,28 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
     public QuoteResultsVo quote(QuoteVo quoteVo) throws Exception {
         OrderBase order = quoteVo.getOrder();
         AttributionInformationVo attributionInformationVo = order.getAttributionInformationVo();
-        CarInfoVo carInfoVo = quoteVo.getCarInfoVo();
         // 查询loginInfo
-        UserInfoResponse.UserData loginInfo = getLoginInfo(attributionInformationVo);
-        String redisValue = redisTemplate.opsForValue().get(GsConstants.GS_REDIS_LOGIN_KEY + attributionInformationVo.getConfigInfo().get("username"));
-        String token = JSONObject.parseObject(redisValue).getString("token");
-        String userID = JSONObject.parseObject(redisValue).getString("userID");
-        JSONObject bindInfo = getBindInfo(redisValue, loginInfo);
+        UserInfoResponse.UserData loginInfo = gsCrawlerLoginComponent.getLoginInfo(attributionInformationVo);
+        CarInfoVo carInfoVo = quoteVo.getCarInfoVo();
+        RedisResultDTO redisResultDTO = loginInfo.getRedisResultDTO();
+        String token = redisResultDTO.getToken();
+        String userID = redisResultDTO.getUserID();
+        JSONObject bindInfo = getBindInfo(token, loginInfo);
         if (bindInfo.isEmpty()) {
             log.error("未匹配到归属信息,username:{}, gsName:{}", "140123198503130219", "腾晟保险代理有限公司山西分公司");
             throw new RuntimeException("请输入正确的归属信息");
         }
         log.info("绑定信息查询成功,userAgentName:{}", bindInfo.getString("userAgentName"));
         //  调用订单号接口
-        InsuranceApplicationEntity insuranceApplicationEntity = new InsuranceApplicationEntity(redisValue, bindInfo, loginInfo, rsaUtils.encrypt(carInfoVo.getLicenseNo()),
-                rsaUtils.encrypt(JSONObject.parseObject(redisValue).getString("userID")), carInfoVo.getEnergyTypeCode());
-        String orderNo = gsCrawlerRequestComponent.queryOrderNo(insuranceApplicationEntity, redisValue);
+        InsuranceApplicationEntity insuranceApplicationEntity = new InsuranceApplicationEntity(redisResultDTO, bindInfo, loginInfo, rsaUtils.encrypt(carInfoVo.getLicenseNo()),
+                rsaUtils.encrypt(redisResultDTO.getUserID()), carInfoVo.getEnergyTypeCode());
+        String orderNo = gsCrawlerRequestComponent.queryOrderNo(insuranceApplicationEntity, token);
         log.info("获取订单号成功,orderId:{}", orderNo);
+
+        //  获取销售归属信息
+        JSONObject jsonObject = gsCrawlerRequestComponent.salesFCBelongInfo(token, orderNo, bindInfo);
+        String businessNatureCode = jsonObject.getString("businessNatureCode");
+
         // 获取保险信息
         InsuranceInformationRequest informationRequest = new InsuranceInformationRequest(rsaUtils.encrypt(bindInfo.getString("userAgentCode")), orderNo, "");
         CarInsuranceQueryResponse.CarInsuranceData insuranceInformation = gsCrawlerRequestComponent.getInsuranceInformation(informationRequest, token);
@@ -126,15 +134,21 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
         //查询车型
         List<GsCrawlerCarQueryResponse.VehicleModelDetail> vehicleModelDetails = gsCrawlerRequestComponent.carQuery(carQueryRequest, token);
         GsCrawlerCarQueryResponse.VehicleModelDetail vehicleModelDetail = CarModelsFilterUtils.to(vehicleModelDetails, carInfoVo);
+
         if (vehicleModelDetail == null) {
             log.error("未匹配到车辆信息,vin:{}, seatCount:{}", carInfoVo.getVinNo());
             throw new RuntimeException("暂未查询到车型");
         }
-        JSONObject jsonObject = gsCrawlerRequestComponent.salesFCBelongInfo(token, orderNo, bindInfo);
-        String businessNatureCode = jsonObject.getString("businessNatureCode");
+
         log.info("车辆信息查询成功,standardName:{}, seat:{}", vehicleModelDetail.getStandardName(), vehicleModelDetail.getSeat());
+        //   查询获取承保方式
+//        ProductUnderwriteRequest request = new ProductUnderwriteRequest("","",businessNatureCode,"","","","");
+//        gsCrawlerRequestComponent.getUnderwritingById(token,request);
+
+
         //  封装submit参数
         SubmitInsuranceInformationRequest submitInsuranceInformationRequest = new SubmitInsuranceInformationRequest(orderNo, quoteVo, vehicleModelDetail, loginInfo, bindInfo, insuranceInformation, userID, orgClient, businessNatureCode);
+        log.info("submit提交参数:{}{}", JSONObject.toJSONString(submitInsuranceInformationRequest));
         SubmitResponse submitResponse = gsCrawlerRequestComponent.submitInsuranceInformationRequest(submitInsuranceInformationRequest, token);
         if ("500".equals(submitResponse.getStatus())) {
             throw new RuntimeException("提交保险信息失败" + submitResponse.getMsg());
@@ -156,7 +170,7 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
         }
         // 加密转换查询
         //String encrypt_userCode = gsCrawlerRequestComponent.getEncryptionConvert(userID, token);
-        return calculation(orderNo, redisValue, quoteVo, insuranceInformation, loginInfo, vehicleModelDetail, bindInfo, businessNatureCode);
+        return calculation(orderNo, redisResultDTO, quoteVo, insuranceInformation, loginInfo, vehicleModelDetail, bindInfo, businessNatureCode,jsonObject);
     }
 
     @Override
@@ -164,9 +178,8 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
         AttributionInformationVo attributionInformationVo = underwritingVo.getOrder().getAttributionInformationVo();
         String ordersNo = underwritingVo.getOrder().getOrdersNo();
         JSONObject quoteInfo = JSONObject.parseObject(redisTemplate.opsForValue().get(GsConstants.GS_REDIS_QUOTE_KEY + ordersNo));
-        UserInfoResponse.UserData loginInfo = getLoginInfo(attributionInformationVo);
-        String redisValue = redisTemplate.opsForValue().get(GsConstants.GS_REDIS_LOGIN_KEY + attributionInformationVo.getConfigInfo().get("username"));
-        JSONObject res = gsCrawlerRequestComponent.doCompleteTask(new OrderEntity(quoteInfo), redisValue);
+        UserInfoResponse.UserData loginInfo = gsCrawlerLoginComponent.getLoginInfo(attributionInformationVo);
+        JSONObject res = gsCrawlerRequestComponent.doCompleteTask(new OrderEntity(quoteInfo), loginInfo.getRedisResultDTO().getToken());
         log.info("核保结果:{}", res);
         UnderwritingResultsVo underwritingResultsVo = new UnderwritingResultsVo();
         if (!"核保通过".equals(res.getString("msg"))) {
@@ -180,7 +193,7 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
             underwritingResultsVo.setCompanyOrderNo(quoteInfo.getString("orderId"));
             underwritingResultsVo.setUnderwritingStatus(InsOrderStatusEnum.PAY_PENDING);
             underwritingResultsVo.setUnderwritingResult(res.getString("msg"));
-            underwritingResultsVo.setPaymentLink(getPayUrl(quoteInfo, redisValue));
+            underwritingResultsVo.setPaymentLink(getPayUrl(quoteInfo, loginInfo.getRedisResultDTO()));
         } else {
             underwritingResultsVo.setUnderwritingStatus(InsOrderStatusEnum.AUDIT_FAIL);
         }
@@ -227,32 +240,31 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
 
     @Override
     public PaymentLinkResultsVo getPaymentLink(PaymentLinkVo paymentLinkVo) throws Exception {
+        InsOrders insOrders = paymentLinkVo.getInsOrders();
         AttributionInformationVo attributionInformationVo = paymentLinkVo.getOrder().getAttributionInformationVo();
-        String ordersNo = paymentLinkVo.getOrder().getOrdersNo();
-        JSONObject quoteInfo = JSONObject.parseObject(redisTemplate.opsForValue().get(GsConstants.GS_REDIS_QUOTE_KEY + ordersNo));
-        getLoginInfo(attributionInformationVo);
-        String redisValue = redisTemplate.opsForValue().get(GsConstants.GS_REDIS_LOGIN_KEY + attributionInformationVo.getConfigInfo().get("username"));
+        UserInfoResponse.UserData loginInfo = gsCrawlerLoginComponent.getLoginInfo(attributionInformationVo);
         PaymentLinkResultsVo paymentLinkResultsVo = new PaymentLinkResultsVo();
-        paymentLinkResultsVo.setPaymentLink(getPayUrl(quoteInfo, redisValue));
+        //paymentLinkResultsVo.setPaymentLink(getPayUrl(quoteInfo, redisValue));
         return paymentLinkResultsVo;
     }
 
 
-    public String getPayUrl(JSONObject quoteInfo, String redisValue) {
+    public String getPayUrl(JSONObject quoteInfo,RedisResultDTO redisResultDTO) {
         // 核保通过   获取订单详情
-        Map<String, Object> detailData = new HashMap<>();
-        detailData.put("orderNo", quoteInfo.getString("orderId"));
-        detailData.put("structureId", JSONObject.parseObject(redisValue).getString("structureId"));
-        detailData.put("userCode", JSONObject.parseObject(redisValue).getString("username"));
-        detailData.put("userLoginType", "1");
-        detailData.put("sellCode", null);
-        detailData.put("systemSource", "gstc");
-        JSONObject doMesOrderDetailRes = gsCrawlerRequestComponent.doMesOrderDetail(redisValue, quoteInfo);
-        // 提取支付链接
-        String payUrl = JSONObject.parseObject(doMesOrderDetailRes.getString("data")).getString("payUrl");
-        JSONObject tokenResponse = gsCrawlerRequestComponent.getTokenUrl(getTokenData(payUrl), redisValue);
-        ResponseDTO shareInfo = gsCrawlerRequestComponent.getShareInfo(tokenResponse, redisValue);
-        return QrCodeReader.parseQrCodeUrl(shareInfo.getData().getUrl());
+//        Map<String, Object> detailData = new HashMap<>();
+//        detailData.put("orderNo", quoteInfo.getString("orderId"));
+//        detailData.put("structureId", JSONObject.parseObject(redisValue).getString("structureId"));
+//        detailData.put("userCode", JSONObject.parseObject(redisValue).getString("username"));
+//        detailData.put("userLoginType", "1");
+//        detailData.put("sellCode", null);
+//        detailData.put("systemSource", "gstc");
+//        JSONObject doMesOrderDetailRes = gsCrawlerRequestComponent.doMesOrderDetail(redisValue, quoteInfo);
+//        // 提取支付链接
+//        String payUrl = JSONObject.parseObject(doMesOrderDetailRes.getString("data")).getString("payUrl");
+//        JSONObject tokenResponse = gsCrawlerRequestComponent.getTokenUrl(getTokenData(payUrl), redisValue);
+//        ResponseDTO shareInfo = gsCrawlerRequestComponent.getShareInfo(tokenResponse, redisValue);
+  //      return QrCodeReader.parseQrCodeUrl(shareInfo.getData().getUrl());
+        return null;
     }
 
 
@@ -263,17 +275,16 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
         String value = redisTemplate.opsForValue().get(GsConstants.GS_REDIS_QUOTE_KEY + orderBase.getOrdersNo());
         JSONObject quote = JSONObject.parseObject(value);
         // 查询loginInfo
-        UserInfoResponse.UserData loginInfo = getLoginInfo(attributionInformationVo);
-        String redisValue = redisTemplate.opsForValue().get(GsConstants.GS_REDIS_LOGIN_KEY + attributionInformationVo.getConfigInfo().get("username"));
+        UserInfoResponse.UserData loginInfo = gsCrawlerLoginComponent.getLoginInfo(attributionInformationVo);
         // 获取归属信息
-        JSONObject bindInfo = getBindInfo(redisValue, loginInfo);
+        JSONObject bindInfo = getBindInfo(loginInfo.getRedisResultDTO().getToken(), loginInfo);
         // 1. 自动生成订单
         GenerateDataRequest generateDataRequest = new GenerateDataRequest(quote);
-        gsCrawlerRequestComponent.doAutoGenerate(generateDataRequest, redisValue);
+        gsCrawlerRequestComponent.doAutoGenerate(generateDataRequest, loginInfo.getRedisResultDTO().getToken());
         // 2. 获取订单详情
-        JSONObject doMesOrderDetail = gsCrawlerRequestComponent.doMesOrderDetail(redisValue, quote);
+        JSONObject doMesOrderDetail = gsCrawlerRequestComponent.doMesOrderDetail(loginInfo.getRedisResultDTO().getToken(), quote);
         // 3. 获取上传状态
-        gsCrawlerRequestComponent.getUploadSuccess(redisValue, quote);
+        gsCrawlerRequestComponent.getUploadSuccess(loginInfo.getRedisResultDTO().getToken(), quote);
         // 4. 查询日志
         JSONObject logData = new JSONObject();
         logData.put("orderNo", quote.getString("orderId"));
@@ -284,7 +295,7 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
         logData.put("oriSysOperatorKey", "RU0yZW0y");
         logData.put("bancassuranceFlag", 0);
         logData.put("checkOrganizationFlag", "0");
-        QueryLogResponse queryLogResponse = gsCrawlerRequestComponent.doQueryLog(redisValue, logData);
+        QueryLogResponse queryLogResponse = gsCrawlerRequestComponent.doQueryLog(loginInfo.getRedisResultDTO().getToken(), logData);
         String JQ_Policy = "";
         String SY_Policy = "";
         String JYX_Policy = "";
@@ -296,7 +307,7 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
                 logData.put("oriSysOperator", "E11_user");
                 logData.put("oriSysOperatorKey", "RTExZTEx");
                 logData.put("vinUseChangeStatusFlag", "1");
-                queryLogResponse = gsCrawlerRequestComponent.doQueryLog(redisValue, logData);
+                queryLogResponse = gsCrawlerRequestComponent.doQueryLog(loginInfo.getRedisResultDTO().getToken(), logData);
             }
             QueryLogResponse.DataDTO responseData = queryLogResponse.getData();
             // 解析投保单号
@@ -312,13 +323,13 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
             redisTemplate.opsForValue().set(GsConstants.GS_REDIS_QUOTE_KEY + orderBase.getOrdersNo() + ":SY_Policy:", SY_Policy, GsConstants.REDIS_EXPIRE_SECONDS, TimeUnit.SECONDS);
             redisTemplate.opsForValue().set(GsConstants.GS_REDIS_QUOTE_KEY + orderBase.getOrdersNo() + ":JYX_Policy:", JYX_Policy, GsConstants.REDIS_EXPIRE_SECONDS, TimeUnit.SECONDS);
             // 再次获取订单详情
-            gsCrawlerRequestComponent.doMesOrderDetail(redisValue, quote);
+            gsCrawlerRequestComponent.doMesOrderDetail(loginInfo.getRedisResultDTO().getToken(), quote);
         } else {
-            log.info("查询QueryLog日志{}", queryLogResponse.getMsg());
+            log.info("查询QueryLog日志{}", JSONObject.toJSONString(queryLogResponse));
             throw new RuntimeException("获取报价日志失败{}:" + queryLogResponse.getMsg());
         }
 
-        JSONObject upload = upload(insuranceUploadImageVo.getImageVoList(), JQ_Policy, SY_Policy, JYX_Policy, loginInfo, bindInfo, quote, redisValue);
+        JSONObject upload = upload(insuranceUploadImageVo.getImageVoList(), JQ_Policy, SY_Policy, JYX_Policy, loginInfo, bindInfo, quote, loginInfo.getRedisResultDTO().getToken());
         if (!"200".equals(upload.getString("code"))) {
             throw new RuntimeException("上传失败" + upload.getString("message"));
         } else {
@@ -336,18 +347,17 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
         AttributionInformationVo attributionInformationVo = downloadPolicyVo.getOrder().getAttributionInformationVo();
         OrderBase orderBase = downloadPolicyVo.getOrder();
         JSONObject quote = JSONObject.parseObject(redisTemplate.opsForValue().get(GsConstants.GS_REDIS_QUOTE_KEY + orderBase.getOrdersNo()));
-        UserInfoResponse.UserData loginInfo = getLoginInfo(attributionInformationVo);
-        String redisValue = redisTemplate.opsForValue().get(GsConstants.GS_REDIS_LOGIN_KEY + attributionInformationVo.getConfigInfo().get("username"));
+        UserInfoResponse.UserData loginInfo = gsCrawlerLoginComponent.getLoginInfo(attributionInformationVo);
         // 1. 获取订单列表
         DoMesOrdersRequest doMesOrdersRequest = new DoMesOrdersRequest(loginInfo.getAesCode(), "");
-        JSONObject mesOrders = gsCrawlerRequestComponent.doMesOrders(doMesOrdersRequest, redisValue);
+        JSONObject mesOrders = gsCrawlerRequestComponent.doMesOrders(doMesOrdersRequest, loginInfo.getRedisResultDTO().getToken());
         JSONObject order = JSONObject.parseObject(JSONObject.toJSONString(mesOrders.getJSONObject("data").getJSONArray("data").get(0)));
         quote.put("orderId", order.getString("orderNo"));
         //  获取订单详情
-        JSONObject jsonObject = gsCrawlerRequestComponent.doMesOrderDetail(redisValue, quote);
-        JSONObject tokenResponse = gsCrawlerRequestComponent.getTokenUrl(getTokenData(JSONObject.toJSONString(jsonObject)), redisValue);
+        JSONObject jsonObject = gsCrawlerRequestComponent.doMesOrderDetail(loginInfo.getRedisResultDTO().getToken(), quote);
+        JSONObject tokenResponse = gsCrawlerRequestComponent.getTokenUrl(getTokenData(JSONObject.toJSONString(jsonObject)), loginInfo.getRedisResultDTO().getToken());
         String id = tokenResponse.getJSONObject("data").getString("id");
-        JSONObject orderDetail = gsCrawlerRequestComponent.getOrderDetail(id, redisValue);
+        JSONObject orderDetail = gsCrawlerRequestComponent.getOrderDetail(id, loginInfo.getRedisResultDTO().getToken());
         JSONArray dzbdList = orderDetail.getJSONObject("data").getJSONArray("list");
         // 遍历保单列表,赋值对应URL
         String syxUrl = "";
@@ -426,7 +436,7 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
     @Override
     public OrderStatusResultVo queryOrderState(OrderStatusVo orderStatusVo) throws Exception {
         AttributionInformationVo attributionInformationVo = orderStatusVo.getOrder().getAttributionInformationVo();
-        UserInfoResponse.UserData loginInfo = getLoginInfo(attributionInformationVo);
+        UserInfoResponse.UserData loginInfo = gsCrawlerLoginComponent.getLoginInfo(attributionInformationVo);
         String redisValue = redisTemplate.opsForValue().get(GsConstants.GS_REDIS_LOGIN_KEY + attributionInformationVo.getConfigInfo().get("username"));
         // 1. 获取订单列表
         DoMesOrdersRequest doMesOrdersRequest = new DoMesOrdersRequest(loginInfo.getAesCode(), rsaUtils.encrypt(orderStatusVo.getCarInfo().getLicenseNo()));
@@ -492,36 +502,8 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
         return resultVo;
     }
 
-    public String getRedisKey(AttributionInformationVo attributionInformationVo) {
-        String username = attributionInformationVo.getConfigInfo().get("username");
-        String value = redisTemplate.opsForValue().get(GsConstants.GS_REDIS_LOGIN_KEY + username);
-        if (StringUtils.isEmpty(value)) {
-            gsCrawlerLoginComponent.login(attributionInformationVo);
-            value = redisTemplate.opsForValue().get(GsConstants.GS_REDIS_LOGIN_KEY + username);
-            if (StringUtils.isEmpty(value)) {
-                getRedisKey(attributionInformationVo);
-            }
-        }
-        return value;
-    }
 
 
-    public UserInfoResponse.UserData getLoginInfo(AttributionInformationVo attributionInformationVo) {
-        String username = attributionInformationVo.getConfigInfo().get("username");
-        String redisValue = getRedisKey(attributionInformationVo);
-        UserInfoResponse loginInfo = gsCrawlerRequestComponent.getLoginInfo(redisValue);
-        if (loginInfo == null || !"200".equals(loginInfo.getStatus())) {
-            log.warn("登录信息接口响应异常,重新获取用户信息,username:{}", loginInfo.getMsg());
-            redisTemplate.delete(GsConstants.GS_REDIS_LOGIN_KEY + username);
-            redisValue = getRedisKey(attributionInformationVo);
-            loginInfo = gsCrawlerRequestComponent.getLoginInfo(redisValue);
-            if (loginInfo == null || !"200".equals(loginInfo.getStatus())) {
-                getLoginInfo(attributionInformationVo);
-            }
-        }
-        return loginInfo.getData();
-    }
-
 
     @Override
     public void qutoationCrawler(InsuranceUploadImageVo insuranceUploadImageVo) {
@@ -529,9 +511,9 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
     }
 
 
-    public JSONObject getBindInfo(String redisValue, UserInfoResponse.UserData loginInfo) {
+    public JSONObject getBindInfo(String token, UserInfoResponse.UserData loginInfo) {
         // 获取绑定信息
-        List<JSONObject> bindInfoData = gsCrawlerRequestComponent.getBindInfo(redisValue, loginInfo.getUserCode());
+        List<JSONObject> bindInfoData = gsCrawlerRequestComponent.getBindInfo(token, loginInfo.getUserCode());
         if (CollectionUtil.isEmpty(bindInfoData)) {
             log.error("绑定信息为空,username:{}");
             throw new RuntimeException("未查询到归属信息");
@@ -555,11 +537,11 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
         return bindInfo;
     }
 
-    public QuoteResultsVo calculation(String orderNo, String redisValue, QuoteVo quoteVo, CarInsuranceQueryResponse.CarInsuranceData insuranceInformation, UserInfoResponse.UserData loginInfo,
-                                      GsCrawlerCarQueryResponse.VehicleModelDetail vehicleModelDetail, JSONObject bindInfo, String businessNatureCode) {
+    public QuoteResultsVo calculation(String orderNo,RedisResultDTO redisResultDTO, QuoteVo quoteVo, CarInsuranceQueryResponse.CarInsuranceData insuranceInformation, UserInfoResponse.UserData loginInfo,
+                                      GsCrawlerCarQueryResponse.VehicleModelDetail vehicleModelDetail, JSONObject bindInfo, String businessNatureCode,JSONObject jsonObject) {
         try {
-            String token = JSONObject.parseObject(redisValue).getString("token");
-            String userID = JSONObject.parseObject(redisValue).getString("userID");
+            String token = redisResultDTO.getToken();
+            String userID = redisResultDTO.getUserID();
             CarInfoVo carInfoVo = quoteVo.getCarInfoVo();
             CustomerInfoVo policyHolderInfo = quoteVo.getPolicyHolderInfo();
             RiskInfoVo ciRiskInfoVo = quoteVo.getCiRiskInfoVo();
@@ -640,10 +622,12 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
             List<InsuranceInitResponse.ClauseInfo> clauseInfoList = insuranceInitData.getClauseInfoList();
             // TODO 配置险种参数
             configClauseInfo(clauseInfoList, quoteVo);
+
             DoCalculateRequest doCalculateRequest = new DoCalculateRequest(desensitizationJson, orderVo, clauseInfoList, syShow, loginInfo, bindInfo);
             PremiumCalculateResponse premiumCalculateResponse = gsCrawlerRequestComponent.doCalculate(doCalculateRequest, token);
-            return repeat(premiumCalculateResponse, orderNo, redisValue, quoteVo, insuranceInformation, loginInfo,
-                    vehicleModelDetail, bindInfo, businessNatureCode, token, syShow);
+            log.info("报价返回信息========:{}{}", JSONObject.toJSONString(premiumCalculateResponse));
+            return repeat(premiumCalculateResponse, orderNo, redisResultDTO, quoteVo, insuranceInformation, loginInfo,
+                    vehicleModelDetail, bindInfo, businessNatureCode, token, syShow,userID,jsonObject);
 
 
         } catch (Exception e) {
@@ -653,33 +637,491 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
     }
 
 
+    public void get_fcxdata(QuoteVo quoteVo,String token,String userID,String businessNatureCode,UserInfoResponse.UserData loginInfo,String orderNo,String seat,JSONObject jsonObject){
+        List<AccidentalDrivingVo> accidentalDrivings = quoteVo.getAccidentalDrivings();
+        if (CollectionUtil.isNotEmpty(accidentalDrivings)){
+            for (AccidentalDrivingVo accidentalDriving : accidentalDrivings) {
+                // 1
+                MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
+                formData.add("convert", userID);
+                JSONObject encryptionConvert = gsCrawlerRequestComponent.encryptionConvert(formData,token);
+                String encrypt_userCode = encryptionConvert.getString("data");
+                // 2
+                MultiValueMap<String, String> data2 = new LinkedMultiValueMap<>();
+                data2.add("userCode", encrypt_userCode);
+                data2.add("loginUserType", "1");
+                data2.add("isApp", "1");
+                JSONObject employeeLogin = gsCrawlerRequestComponent.employeeLogin(data2,token);
+
+                JSONObject empData = employeeLogin.getJSONObject("data");
+                String managerId = empData.getString("id");
+                String saleAgreementNo = empData.getString("saleAgreementNo");
+                String userName = empData.getString("userName");
+                String branchOfficeName = empData.getString("branchOfficeName");
+                //3
+                MultiValueMap<String, String> data3 = new LinkedMultiValueMap<>();
+                data3.add("productId",accidentalDriving.getProductCode() );
+                data3.add("managerId", managerId);
+                data3.add("businessNatureCode",businessNatureCode);
+                data3.add("comCode", loginInfo.getUserDepartment());
+                JSONObject productInfo = gsCrawlerRequestComponent.getProductInfoById(data3,token);
+
+                //4
+                MultiValueMap<String, String> data4 = new LinkedMultiValueMap<>();
+                data4.add("thisId",orderNo );
+
+                JSONObject individualVo = gsCrawlerRequestComponent.getIndividualVo(data4,token);
+
+
+                JSONObject data5 = new JSONObject();
+                data5.put("productId",accidentalDriving.getProductCode() );
+                data5.put("carUserNatureCode", "8A");
+                data5.put("passengersNumber",seat);
+                data5.put("carKindCode","A0");
+                JSONObject fromCarModelCheck = gsCrawlerRequestComponent.fromCarModelCheck(data5,token);
+
+
+                MultiValueMap<String, String> data6 = new LinkedMultiValueMap<>();
+                data6.add("productId",accidentalDriving.getProductCode() );
+                data6.add("managerId", managerId);
+                data6.add("businessNatureCode",businessNatureCode);
+                data6.add("comCode", loginInfo.getUserDepartment());
+                JSONObject underwritingById = gsCrawlerRequestComponent.getUnderwritingById(data6,token);
+                JSONObject next_data = underwritingById.getJSONObject("data");
+                // -------------------- 5. underwritingPre --------------------
+                next_data.put("carOrderId", orderNo);
+                next_data.put("systemSource", "fromCar");
+                next_data.put("comCode",loginInfo.getUserDepartment());
+                JSONObject underwritingPre = gsCrawlerRequestComponent.underwritingPre(next_data,token,loginInfo.getRedisResultDTO().getBid());
+                String preId = underwritingPre.getJSONObject("data").getString("preId");
+                String salesman = jsonObject.getString("salesman");
+                String saleAgreementNo1 = jsonObject.getString("saleAgreementNo");
+                String businessNatureName = jsonObject.getString("businessNatureName");
+                String channelType = jsonObject.getString("channelType");
+
+
+                JSONObject data7 = new JSONObject();
+                data7.put("productId",accidentalDriving.getProductCode() );
+                data7.put("managerId", managerId);
+                data7.put("businessNatureCode",businessNatureCode);
+                data7.put("salesman",salesman);
+                JSONObject findAgentRate = gsCrawlerRequestComponent.findAgentRate(data7,token);
+
+
+                JSONObject data7vo = gsCrawlerRequestComponent.getIndividualVo(data4,token);
+
+
+                MultiValueMap<String, String> data8 = new LinkedMultiValueMap<>();
+                data8.add("productId",accidentalDriving.getProductCode() );
+                data8.add("managerId", managerId);
+                data8.add("businessNatureCode",businessNatureCode);
+                data8.add("comCode", loginInfo.getUserDepartment());
+
+                data8.add("preId", preId);
+                data8.add("isPreUnderwriting","1");
+                data8.add("systemSource", "fromCar");
+                JSONObject data8vo = gsCrawlerRequestComponent.getUnderwritingById(data8,token);
+                JSONObject voString = data8vo.getJSONObject("data");
+
+                // 获取模块化列表(JSONArray)
+                JSONArray second_data = voString.getJSONArray("modularList");
+                if (second_data == null || second_data.isEmpty()) {
+                    return;
+                }
+
+
+                dataProcessor.processModularData(second_data,accidentalDriving.getProductCode(),quoteVo,seat, jsonObject,loginInfo,branchOfficeName,voString);
+
+
+                JSONObject underwritingVariablePremiumVariablePremium = gsCrawlerRequestComponent.underwritingVariablePremiumVariablePremium(voString,token);
+                System.out.println("==================");
+
+            }
+
+
+        }
+
+    }
+
+
+
+
+    public void processModularData(JSONArray modularList, String productId,QuoteVo quoteVo, String seat,JSONObject jsonObject,UserInfoResponse.UserData loginInfo,String branchOfficeName,JSONObject data8vo) {
+
+        // 白名单产品ID
+        List<String> validProductIds = List.of(
+                "fd2dc8abe5f94eacbc8efd3bf62a8581",
+                "39f47efbd6004899b4fa7c80bfdba801",
+                "54b7cce17316444aade70427d8abea0a",
+                "7e1108d1db2c428d8cf35e3e6896bb15",
+                "fc9cd193ce444508b355b5d5522ffc00",
+                "71d3c2271fe5404d82c78fb07d116cf0",
+                "77bcfb9bff014a93bfca0ed792c30258",
+                "new-2d0bc85a46c799ff4ad0c8521348",
+                "f65730fe001a4c998aabc1d2e7258a96"
+        );
+
+        if (!validProductIds.contains(productId)) {
+            return;
+        }
+        CarInfoVo carInfoVo = quoteVo.getCarInfoVo();
+        CustomerInfoVo policyHolderInfo = quoteVo.getPolicyHolderInfo();
+        CustomerInfoVo insuredPersonInfo = quoteVo.getInsuredPersonInfo();
+        for (int i = 0; i < modularList.size(); i++) {
+            JSONObject modular = modularList.getJSONObject(i);
+            Integer sortNo = modular.getInteger("sortNo");
+            if (sortNo == null) {
+                continue;
+            }
+            JSONArray infoList = modular.getJSONArray("ncispUnderwritingInfoList");
+            if (infoList == null) {
+                continue;
+            }
+            JSONArray newInfoList = new JSONArray();
+            // ====================== sortNo = 0 ======================
+            if (sortNo == 0) {
+                for (int j = 0; j < infoList.size(); j++) {
+                    JSONObject item = infoList.getJSONObject(j);
+                    String fieldName = item.getString("backEndTranslationNameYl");
+                    String type = item.getString("type");
+
+                    if ("1".equals(type)) {
+                        switch (fieldName) {
+                            case "customerName":
+                                item.put("fieldType", "-1");
+                                item.put("mustFill", "2");
+                                item.put("display", "block");
+                                String encryptedName = RsaUtils.encrypt(policyHolderInfo.getName());
+                                item.put("fieldValue", encryptedName);
+                                item.put("fieldValueName", encryptedName);
+                                break;
+                            case "mobile":
+                                item.put("fieldType", "-1");
+                                item.put("mustFill", "2");
+                                item.put("display", "block");
+                                String encryptedPhone = RsaUtils.encrypt(policyHolderInfo.getMobile());
+                                item.put("fieldValue", encryptedPhone);
+                                item.put("fieldValueName", encryptedPhone);
+                                break;
+                            case "identifyType":
+                                item.put("readonly", "1");
+                                item.put("fieldValue", "idCard");
+                                item.put("fieldValueName", "居民身份证");
+                                item.put("mustFill", "2");
+                                item.put("display", "block");
+                                break;
+                            case "identifyNumber":
+                                item.put("fieldType", "-1");
+                                item.put("mustFill", "2");
+                                item.put("display", "block");
+                                String encryptedIdNo = RsaUtils.encrypt(policyHolderInfo.getIdentifyNumber());
+                                item.put("fieldValue", encryptedIdNo);
+                                item.put("fieldValueName", encryptedIdNo);
+                                break;
+                            case "age":
+                                item.put("display", "none");
+                                break;
+                            case "sex":
+                                String sexVal = item.getString("fieldValueName");
+                                if ("2".equals(sexVal)) {
+                                    item.put("fieldValueName", "女");
+                                } else {
+                                    item.put("fieldValueName", "男");
+                                }
+                                item.put("fieldValue", "1");
+                                item.put("display", "none");
+                                break;
+                            case "identifyEffectiveStartDate":
+                                String today = LocalDate.now().toString();
+                                item.put("fieldType", "-1");
+                                item.put("mustFill", "0");
+                                item.put("display", "block");
+                                item.put("minDate", "1900-01-01");
+                                item.put("maxDate", today);
+                                break;
+                            case "identifyEffectiveTerm":
+                                item.put("fieldType", "-1");
+                                item.put("fieldValue", "100");
+                                item.put("mustFill", "0");
+                                item.put("display", "block");
+                                break;
+                            case "citizenship":
+                                item.put("display", "block");
+                                break;
+                            case "provinceCode":
+                                item.put("readonly", "1");
+                                item.put("fieldDescribe", "省市地区");
+                                item.put("fieldValue", policyHolderInfo.getProvinceCode());
+                                item.put("fieldValueName", policyHolderInfo.getProvince());
+                                item.put("areaCodeList", List.of(policyHolderInfo.getProvinceCode(),
+                                        policyHolderInfo.getCityCode(),
+                                        policyHolderInfo.getCountyCode()
+                                ));
+                                item.put("remarks", policyHolderInfo.getProvince());
+                                item.put("display", "block");
+                                break;
+                            case "cityCode":
+                                item.put("readonly", "1");
+                                item.put("fieldValue", policyHolderInfo.getCityCode());
+                                item.put("fieldValueName", policyHolderInfo.getCity());
+                                item.put("remarks", policyHolderInfo.getCity());
+                                item.put("display", "none");
+                                break;
+                            case "districtCode":
+                                item.put("readonly", "1");
+                                item.put("fieldValue", policyHolderInfo.getCountyCode());
+                                item.put("fieldValueName", policyHolderInfo.getCounty());
+                                item.put("remarks",  policyHolderInfo.getCounty());
+                                item.put("display", "none");
+                                break;
+                            case "email":
+                                if (item.get("type") == null) {
+                                    item.put("display", "block");
+                                }
+                                break;
+                        }
+                    }
+                    newInfoList.add(item);
+                }
+                modular.put("selected", true);
+                modular.put("ncispUnderwritingInfoList", newInfoList);
+            }
+
+            // ====================== sortNo = 100 ======================
+            else if (sortNo == 100) {
+                for (int j = 0; j < infoList.size(); j++) {
+                    JSONObject item = infoList.getJSONObject(j);
+                    String fieldName = item.getString("backEndTranslationNameYl");
+                    String type = item.getString("type");
+
+                    if ("1".equals(type)) {
+                        switch (fieldName) {
+                            case "relationToApplicantCode":
+                                item.put("fieldValue", "1");
+                                item.put("fieldValueName", "本人");
+                                item.put("display", "block");
+                                break;
+                            case "customerName":
+                                item.put("display", "none");
+                                String bbEncName = RsaUtils.encrypt(insuredPersonInfo.getName());
+                                item.put("fieldValue", bbEncName);
+                                item.put("fieldValueName", bbEncName);
+                                break;
+                            case "mobile":
+                                item.put("display", "none");
+                                String bbEncPhone = RsaUtils.encrypt(insuredPersonInfo.getMobile());
+                                item.put("fieldValue", bbEncPhone);
+                                item.put("fieldValueName", bbEncPhone);
+                                break;
+                            case "identifyType":
+                                item.put("display", "none");
+                                item.put("fieldValueName", "居民身份证");
+                                break;
+                            case "identifyNumber":
+                                item.put("display", "none");
+                                String bbEncIdNo = RsaUtils.encrypt(insuredPersonInfo.getIdentifyNumber());
+                                item.put("fieldValue", bbEncIdNo);
+                                item.put("fieldValueName", bbEncIdNo);
+                                break;
+                            case "sex":
+                                String sexVal = item.getString("fieldValueName");
+                                item.put("fieldValueName", "2".equals(sexVal) ? "女" : "男");
+                                item.put("display", "none");
+                                break;
+                            case "citizenship":
+                            case "age":
+                                item.put("display", "none");
+                                break;
+                            case "identifyEffectiveStartDate":
+                                String today = LocalDate.now().toString();
+                                item.put("minDate", "1900-01-01");
+                                item.put("maxDate", today);
+                                item.put("display", "none");
+                                item.put("mustFill", "0");
+                                break;
+                            case "identifyEffectiveTerm":
+                                item.put("display", "none");
+                                item.put("mustFill", "0");
+                                break;
+                            case "provinceCode":
+                                item.put("fieldValue", insuredPersonInfo.getProvinceCode());
+                                item.put("fieldValueName", insuredPersonInfo.getProvince());
+                                item.put("fieldDescribe", "省市地区");
+                                item.put("remarks", insuredPersonInfo.getProvince());
+                                item.put("areaCodeList", List.of(
+                                        insuredPersonInfo.getProvinceCode(),
+                                        insuredPersonInfo.getCityCode(),
+                                        insuredPersonInfo.getCountyCode()
+                                ));
+                                item.put("display", "none");
+                                break;
+                            case "cityCode":
+                                item.put("fieldValue", insuredPersonInfo.getCityCode());
+                                item.put("fieldValueName", insuredPersonInfo.getCity());
+                                item.put("remarks", insuredPersonInfo.getCity());
+                                item.put("display", "none");
+                                break;
+                            case "districtCode":
+                                item.put("fieldValue", insuredPersonInfo.getCountyCode());
+                                item.put("fieldValueName", insuredPersonInfo.getCounty());
+                                item.put("remarks",  insuredPersonInfo.getCounty());
+                                item.put("display", "none");
+                                break;
+                        }
+                    }
+                    newInfoList.add(item);
+                }
+                modular.put("selected", true);
+                modular.put("ncispUnderwritingInfoList", newInfoList);
+            }
+
+            // ====================== sortNo = 200 ======================
+            else if (sortNo == 200) {
+                for (int j = 0; j < infoList.size(); j++) {
+                    JSONObject item = infoList.getJSONObject(j);
+                    String fieldName = item.getString("backEndTranslationNameYl");
+
+                    if (item.get("type") == null) {
+                        switch (fieldName) {
+                            case "licensePlateNo":
+                                item.put("fieldType", "-1");
+                                item.put("mustFill", "2");
+                                item.put("display", "block");
+                                String encLicense = RsaUtils.encrypt(carInfoVo.getLicenseNo());
+                                item.put("fieldValue", encLicense);
+                                item.put("fieldValueName", encLicense);
+                                break;
+                            case "engineNumber":
+                                item.put("fieldType", "-1");
+                                item.put("mustFill", "2");
+                                item.put("display", "block");
+                                String encEngine = RsaUtils.encrypt(carInfoVo.getEngineNo());
+                                item.put("fieldValue", encEngine);
+                                item.put("fieldValueName", encEngine);
+                                break;
+                            case "frameNo":
+                                item.put("fieldType", "-1");
+                                item.put("mustFill", "2");
+                                item.put("display", "block");
+                                String encVin = RsaUtils.encrypt(carInfoVo.getVinNo());
+                                item.put("fieldValue", encVin);
+                                item.put("fieldValueName", encVin);
+                                break;
+                            case "passengersNumber":
+                                item.put("readonly", "1");
+                                String seatNum = carInfoVo.getSeatCount();
+                                item.put("fieldValue", seatNum);
+                                item.put("fieldValueName", seatNum + "座");
+                                item.put("mustFill", "2");
+                                item.put("display", "block");
+                                break;
+                            case "carUserNatureCode":
+                                item.put("readonly", "1");
+                                item.put("fieldValue", "8A");
+                                item.put("fieldValueName", "家庭自用");
+                                item.put("mustFill", "2");
+                                item.put("display", "block");
+                                break;
+                        }
+                    }
+                    newInfoList.add(item);
+                }
+                modular.put("selected", true);
+                modular.put("ncispUnderwritingInfoList", newInfoList);
+            }
+
+            // ====================== sortNo = 300 / 600 ======================
+            else if (sortNo == 300 || sortNo == 600) {
+                for (int j = 0; j < infoList.size(); j++) {
+                    JSONObject item = infoList.getJSONObject(j);
+                    String fieldName = item.getString("backEndTranslationNameYl");
+                    if (item.get("type") == null && "passengersNumber".equals(fieldName)) {
+                        item.put("fieldValue", String.valueOf(seat));
+                        item.put("fieldValueName", seat + "座");
+                        newInfoList.add(item);
+                    }
+                }
+            }
+
+            // ====================== sortNo = 9999 ======================
+            else if (sortNo == 9999) {
+                for (int j = 0; j < infoList.size(); j++) {
+                    JSONObject item = infoList.getJSONObject(j);
+                    String fieldName = item.getString("backEndTranslationNameYl");
+                    if (item.get("type") == null && "mark1".equals(fieldName)) {
+                        item.put("display", "block");
+                        newInfoList.add(item);
+                    }
+                }
+                modular.put("selected", true);
+                modular.put("ncispUnderwritingInfoList", newInfoList);
+            }
+        }
+
+
+    }
+
+
+
+    public static MultiValueMap<String, String> jsonToMultiValueMap(JSONObject json) {
+        MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
+
+        if (json == null || json.isEmpty()) {
+            return map;
+        }
+
+        // 遍历所有 key
+        for (String key : json.keySet()) {
+            Object value = json.get(key);
+            // 转成字符串(null 转空串)
+            String strValue = value == null ? "" : String.valueOf(value);
+            map.add(key, strValue);
+        }
+
+        return map;
+    }
+
+
     /**
      * 重复报价处理(处理重复投保问题)
      *
      * @param premiumCalculateResponse 报价响应
      * @return 最终报价结果
      */
-    public QuoteResultsVo repeat(PremiumCalculateResponse premiumCalculateResponse, String orderNo, String redisValue, QuoteVo quoteVo, CarInsuranceQueryResponse.CarInsuranceData insuranceInformation, UserInfoResponse.UserData loginInfo,
-                                 GsCrawlerCarQueryResponse.VehicleModelDetail vehicleModelDetail, JSONObject bindInfo, String businessNatureCode, String token, String syShow) {
+    public QuoteResultsVo repeat(PremiumCalculateResponse premiumCalculateResponse, String orderNo,RedisResultDTO redisResultDTO, QuoteVo quoteVo, CarInsuranceQueryResponse.CarInsuranceData insuranceInformation, UserInfoResponse.UserData loginInfo,
+                                 GsCrawlerCarQueryResponse.VehicleModelDetail vehicleModelDetail, JSONObject bindInfo, String businessNatureCode, String token, String syShow,String userID,JSONObject jsonObject) {
         QuoteResultsVo quoteResultsVo = new QuoteResultsVo();
         // 2. 处理商业险重复投保
         String jqRepeatinfo = "";
         String syRepeatinfo = "";
         String msg = premiumCalculateResponse.getMsg();
-        String doubleMsg = premiumCalculateResponse.getData().getDoubleMsg();
-        if (msg.contains("商业险") && msg.contains("重复投保")) {
-            String sy = DateUtils.getTime(doubleMsg);
-            log.info("商业险重复投保,更新开始日期,newChesunStartDate:{}", sy);
-            // 重新报价
-            return calculation(orderNo, redisValue, quoteVo, insuranceInformation, loginInfo,
-                    vehicleModelDetail, bindInfo, businessNatureCode);
-
+        if (msg.contains("商业险") && msg.contains("重复投保") && msg.contains("保险期间:")) {
+            if (msg.contains("<br")) {
+                String sy = DateUtils.getTime(msg);
+                log.info("商业险重复投保,更新开始日期,newChesunStartDate:{}", sy);
+                RiskInfoVo biRiskInfoVo = quoteVo.getBiRiskInfoVo();
+                biRiskInfoVo.setStartDate("");
+                biRiskInfoVo.setEndDate("");
+                // 重新报价
+                return calculation(orderNo, redisResultDTO, quoteVo, insuranceInformation, loginInfo,
+                        vehicleModelDetail, bindInfo, businessNatureCode,jsonObject);
+            }else {
+                quoteResultsVo.setErrorMessage(msg);
+                quoteResultsVo.setQuoteStatusEnum(InsOrderStatusEnum.QUOTE_FAIL);
+            }
         } // 3. 处理交强险重复投保
-        else if (msg.contains("交强险") && msg.contains("重复投保")) {
-            String jq = DateUtils.getTime(doubleMsg);
-            quoteVo.getCiRiskInfoVo().setStartDate(jq);
-            return calculation(orderNo, redisValue, quoteVo, insuranceInformation, loginInfo,
-                    vehicleModelDetail, bindInfo, businessNatureCode);
+        else if (msg.contains("交强险") && msg.contains("重复投保") && msg.contains("终保日期")) {
+            if (msg.contains("保单号") && msg.contains("起保日期") && msg.contains("终保日期")) {
+                String startTime = extractDuplicateEndTime(msg);
+                String endTime = TimeProcessing.minusOneSecondAfterYear(startTime);
+                quoteVo.getCiRiskInfoVo().setStartDate(startTime);
+                quoteVo.getCiRiskInfoVo().setEndDate(endTime);
+                return calculation(orderNo, redisResultDTO, quoteVo, insuranceInformation, loginInfo,
+                        vehicleModelDetail, bindInfo, businessNatureCode,jsonObject);
+            }else {
+                quoteResultsVo.setErrorMessage(msg);
+                quoteResultsVo.setQuoteStatusEnum(InsOrderStatusEnum.QUOTE_FAIL);
+            }
         } // 4. 报价失败处理
         else if (!"200".equals(premiumCalculateResponse.getStatus())) {
             String info = "";
@@ -695,9 +1137,26 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
             quoteResultsVo.setErrorMessage(errorMsg);
             quoteResultsVo.setQuoteStatusEnum(InsOrderStatusEnum.QUOTE_FAIL);
         } else if ("200".equals(premiumCalculateResponse.getStatus())) {
-            FeeCalculateResponse.DataDTO dataDTO = gsCrawlerRequestComponent.creatOrder(token, CreatOrderRequest.creatOrderRequest(premiumCalculateResponse.getData(), syShow, redisValue, loginInfo));
+
+            get_fcxdata( quoteVo, token, userID, businessNatureCode, loginInfo, orderNo,vehicleModelDetail.getSeat(),jsonObject);
+
+
+            FeeCalculateResponse.DataDTO dataDTO = gsCrawlerRequestComponent.creatOrder(token, CreatOrderRequest.creatOrderRequest(premiumCalculateResponse.getData(), syShow,redisResultDTO.getUserID(), loginInfo));
             Object businessCalcFeeVo = dataDTO.getBusinessCalcFeeVo();
-            String sy_discountRate = "";
+
+            return processCalcSuccessResult(premiumCalculateResponse, quoteVo, token);
+        } else {
+            quoteResultsVo.setErrorMessage("报价失败");
+            quoteResultsVo.setQuoteStatusEnum(InsOrderStatusEnum.QUOTE_FAIL);
+        }
+        return quoteResultsVo;
+    }
+
+
+    /*
+
+
+   String sy_discountRate = "";
             String discountRate = "";
             if (businessCalcFeeVo != null) {
                 sy_discountRate = JSONObject.parseObject(JSONObject.toJSONString(businessCalcFeeVo)).getString("'discountRate'");
@@ -713,8 +1172,8 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
             saveRedis.put("username", loginInfo.getUserCode());
             saveRedis.put("businessOffice", loginInfo.getUserDepartment());
             saveRedis.put("structureId", loginInfo.getProvincialCom());
-            saveRedis.put("userCode", JSONObject.parseObject(redisValue).getString("userID"));
-            saveRedis.put("token", JSONObject.parseObject(redisValue).getString("token"));
+            saveRedis.put("userCode", redisResultDTO.getUserID());
+            saveRedis.put("token",redisResultDTO.getToken());
             saveRedis.put("license", quoteVo.getCarInfoVo().getLicenseNo());
             saveRedis.put("zhanghao_info", loginInfo.getProvincialCom());
             saveRedis.put("gs_info", JSONObject.toJSONString(bindInfo));
@@ -728,6 +1187,7 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
             if ("200".equals(premiumCalculateResponse.getStatus())) {
                 PremiumCalculateResponse.OrderVoDTO resOrderVo = premiumCalculateResponse.getData().getOrderVo();
                 tranNo = resOrderVo.getTransactionNo();
+
                 orderId = resOrderVo.getOrderNo();
             }
             saveRedis.put("orderId", orderId);
@@ -735,14 +1195,23 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
             saveRedis.put("bj_res", JSONObject.toJSONString(premiumCalculateResponse));
             saveRedis.put("bjresdata", JSON.toJSONString(premiumCalculateResponse.getData()));
             redisTemplate.opsForValue().set(GsConstants.GS_REDIS_QUOTE_KEY + quoteVo.getOrder().getOrdersNo(), JSONObject.toJSONString(saveRedis), GsConstants.REDIS_EXPIRE_SECONDS, TimeUnit.SECONDS);
-            return processCalcSuccessResult(premiumCalculateResponse, quoteVo, token);
-        } else {
-            quoteResultsVo.setErrorMessage("报价失败");
-            quoteResultsVo.setQuoteStatusEnum(InsOrderStatusEnum.QUOTE_FAIL);
+
+    * */
+
+
+    // 截取重复投保终保日期
+    private static final Pattern DUPLICATE_END_TIME_PATTERN = Pattern.compile("终保日期 (\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2})");
+    private String extractDuplicateEndTime(String returnMessage) {
+        Matcher matcher = DUPLICATE_END_TIME_PATTERN.matcher(returnMessage);
+        if (matcher.find()) {
+            String shortEndTime = matcher.group(1);
+            return shortEndTime + ":00";
         }
-        return quoteResultsVo;
+        return null;
     }
 
+
+
     /**
      * 处理报价成功结果
      *
@@ -1008,7 +1477,7 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
     /**
      * 图片上传
      */
-    public JSONObject upload(List<InsuranceImageVo> imageVoList, String JQ_Policy, String SY_Policy, String JYX_Policy, UserInfoResponse.UserData loginInfo, JSONObject bindInfo, JSONObject quoteInfo, String redisValue) {
+    public JSONObject upload(List<InsuranceImageVo> imageVoList, String JQ_Policy, String SY_Policy, String JYX_Policy, UserInfoResponse.UserData loginInfo, JSONObject bindInfo, JSONObject quoteInfo, String token) {
         String ryMessage = null; // 人员照片错误
         String rybMessage = null; // 人员照片背面错误
         String clMessage = null; // 行驶证照片错误
@@ -1018,7 +1487,7 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
             InsuranceImageVo.ImageDTO imageDTO = insuranceImageVo.getImageBase64List().get(0);
             // 构建图片请求参数
             ImageUploadRequest uploadRequest = new ImageUploadRequest(imageDTO, quoteInfo, loginInfo, JQ_Policy, SY_Policy, imageType);
-            CheckImageResponse checkImage = gsCrawlerRequestComponent.doCheckImage(redisValue, uploadRequest);
+            CheckImageResponse checkImage = gsCrawlerRequestComponent.doCheckImage(token, uploadRequest);
             if (!"200".equals(checkImage.getStatus()) && !"201".equals(checkImage.getStatus())) {
                 log.error("图片上传失败:{}", checkImage.getMsg());
                 String imageMsg = checkImage.getMsg();
@@ -1043,7 +1512,7 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
                 continue;
             }
             UploadImagesRequest imageBusinessRequest = new UploadImagesRequest(loginInfo, JQ_Policy, SY_Policy, imageType, checkImage.getData(), quoteInfo, imageDTO.getImageBase64Str());
-            gsCrawlerRequestComponent.uploadImages(imageBusinessRequest, redisValue);
+            gsCrawlerRequestComponent.uploadImages(imageBusinessRequest, token);
         }
 
         // 构建返回结果
@@ -1093,7 +1562,7 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
     public void revocation(String orderNo) {
 //        String userName = "";
 //        // 查询loginInfo
-//        UserInfoResponse.UserData loginInfo = getLoginInfo(attributionInformationVo);
+//        UserInfoResponse.UserData loginInfo = gsCrawlerLoginComponent.getLoginInfo(attributionInformationVo);
 //        String redisValue = redisTemplate.opsForValue().get(GsConstants.GS_REDIS_LOGIN_KEY+ attributionInformationVo.getConfigInfo().get("username"));
 //        String quote = redisTemplate.opsForValue().get(GsConstants.GS_REDIS_QUOTE_KEY + orderNo);
 //        String token = JSONObject.parseObject(redisValue).getString("token");

+ 54 - 0
tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/util/RsaUtils.java

@@ -1,5 +1,6 @@
 package com.jzg.quotation.guoshou.crawler.util;
 
+import com.alibaba.fastjson2.JSONObject;
 import lombok.extern.slf4j.Slf4j;
 import org.bouncycastle.jce.provider.BouncyCastleProvider;
 import org.slf4j.Logger;
@@ -7,6 +8,8 @@ import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Component;
 
 import javax.crypto.Cipher;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
 import java.security.KeyFactory;
 import java.security.PrivateKey;
 import java.security.PublicKey;
@@ -14,6 +17,7 @@ import java.security.Security;
 import java.security.spec.PKCS8EncodedKeySpec;
 import java.security.spec.X509EncodedKeySpec;
 import java.util.Base64;
+import java.util.Map;
 
 /**
  * RSA加密工具类(对应原Python RSA.js逻辑)
@@ -33,6 +37,12 @@ public class RsaUtils {
    // @Value("${business.rsa-public-key}")
     private static String publicKeyStr = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwGbMAecQuqsZ2hQELuqSHI+R8R0NcM9SNqw245OB/vDed4Z65z97YlrjG7+bE2CPs6TLNezYey/PqdeuUfbIaG6ou+FATs5y+MZQMEMpgJBMGvjivn0cNN5yICMM/G2ZdS66Hx5U1iK6yzsDi5o3rNpXsNzN36xLhSCVaZ96y1QIDAQAB";
 
+    private static final String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwGbMAecQuqsZ2hQELuqSHI+R8" +
+            "R0NcM9SNqw245OB/vDed4Z65z97YlrjG7+bE2CPs6TLNezYey/PqdeuUfbIaG6ou" +
+            "+FATs5y+MZQMEMpgJBMGvjivn0cNN5yICMM/G2ZdS66Hx5U1iK6yzsDi5o3rNpXs" +
+            "NzN36xLhSCVaZ96y1QIDAQAB";
+
+
     static {
         // 加载BouncyCastleProvider
         Security.addProvider(new BouncyCastleProvider());
@@ -109,4 +119,48 @@ public class RsaUtils {
             throw new RuntimeException("RSA解密异常", e);
         }
     }
+
+
+    /**
+     * RSA分段加密(117字节分段)+ Base64
+     */
+    public static String generateSecretParameter(Map<String, Object> data) throws Exception {
+        // 加入时间戳
+        data.put("timestamp", System.currentTimeMillis());
+        // 紧凑JSON
+        String plainText = JSONObject.toJSONString(data);
+        // URL编码(等价JS encodeURIComponent)
+        String encoded = URLEncoder.encode(plainText, StandardCharsets.UTF_8.name()).replace("+", "%20");
+
+        // 加载公钥
+        byte[] keyBytes = Base64.getDecoder().decode(PUBLIC_KEY);
+        X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
+        KeyFactory factory = KeyFactory.getInstance("RSA", "BC");
+        PublicKey publicKey = factory.generatePublic(spec);
+
+        // 分段加密(117字节)
+        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "BC");
+        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
+        byte[] encodedBytes = encoded.getBytes(StandardCharsets.UTF_8);
+        int chunkSize = 117;
+        byte[] result = new byte[0];
+
+        for (int i = 0; i < encodedBytes.length; i += chunkSize) {
+            int end = Math.min(i + chunkSize, encodedBytes.length);
+            byte[] chunk = new byte[end - i];
+            System.arraycopy(encodedBytes, i, chunk, 0, chunk.length);
+            byte[] encrypted = cipher.doFinal(chunk);
+
+            // 拼接结果
+            byte[] temp = new byte[result.length + encrypted.length];
+            System.arraycopy(result, 0, temp, 0, result.length);
+            System.arraycopy(encrypted, 0, temp, result.length, encrypted.length);
+            result = temp;
+        }
+
+        return Base64.getEncoder().encodeToString(result);
+    }
+
+
+
 }