lixiaolong 3 ヶ月 前
コミット
b3a20409db
30 ファイル変更4544 行追加602 行削除
  1. 140 0
      tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/component/RequestComponent.java
  2. 48 0
      tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/config/WebClientConfig.java
  3. 2 0
      tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/constant/InsuranceTypeCorrespondence.java
  4. 220 0
      tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/utils/HtEncryptDecryptUtils.java
  5. 30 0
      tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/utils/JsonUtils.java
  6. 30 0
      tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/utils/RequestObjectConversion.java
  7. 54 27
      tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/build/HuaTaiCrawlerQuoteResultsVoBuild.java
  8. 117 145
      tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/component/HtCrawlerRequestComponent.java
  9. 52 1
      tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/component/HuaTaiCrawlerCacheComponent.java
  10. 23 12
      tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/constant/enums/RequestUrl.java
  11. 2 0
      tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/entity/HtCrawlerConfigureParameters.java
  12. 48 6
      tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/entity/Request/HtCrawlerCarQueryRequest.java
  13. 1 1
      tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/entity/Request/HtCrawlerGerUploadUrlRequest.java
  14. 9 9
      tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/entity/Request/HtCrawlerLoginRequest.java
  15. 145 3
      tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/entity/Request/HtCrawlerPaymentLinkRequest.java
  16. 246 47
      tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/entity/Request/HtCrawlerQuoteRequest.java
  17. 633 47
      tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/entity/Request/HtCrawlerSaveOneStepRequest.java
  18. 458 267
      tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/entity/Request/HtCrawlerSubmitRequest.java
  19. 2 0
      tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/entity/Response/HtCrawlerCarQueryResponse.java
  20. 9 0
      tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/entity/Response/HtCrawlerQuoteResponse.java
  21. 1 1
      tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/entity/Response/HtCrawlerSubmitResponse.java
  22. 101 0
      tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/entity/Response/HtCrawlerSubmitRightResponse.java
  23. 3 0
      tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/entity/dto/LoginDTO.java
  24. 10 0
      tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/entity/po/HtCrawlerOrder.java
  25. 3 1
      tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/service/HuaTaiCrawlerRequest.java
  26. 940 34
      tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/service/Impl/HuaTaiCrawlerRequestImpl.java
  27. 679 0
      tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/util/CookieUtils.java
  28. 115 0
      tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/util/CryptoUtil.java
  29. 422 0
      tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/util/UploadUtil.java
  30. 1 1
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/async/AsyncGetPayLink.java

+ 140 - 0
tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/component/RequestComponent.java

@@ -6,6 +6,7 @@ import com.jzg.commons.constants.quote.enums.base.InsuranceEnum;
 import com.jzg.commons.exception.SystemException;
 import com.jzg.quotation.commons.config.WebClientConfig;
 import com.jzg.quotation.commons.entity.CookiesRequest;
+import com.jzg.quotation.commons.utils.HtEncryptDecryptUtils;
 import com.jzg.quotation.commons.utils.InsuranceLog;
 import com.jzg.quotation.commons.utils.RequestObjectConversion;
 import lombok.RequiredArgsConstructor;
@@ -16,6 +17,7 @@ import org.springframework.core.io.buffer.DataBufferUtils;
 import org.springframework.http.*;
 import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Component;
+import org.springframework.util.LinkedMultiValueMap;
 import org.springframework.util.MultiValueMap;
 import org.springframework.web.reactive.function.BodyInserters;
 import org.springframework.web.reactive.function.client.WebClient;
@@ -105,6 +107,17 @@ public class RequestComponent {
         return webClient;
     }
 
+    private WebClient selectNoSSLWebClientWithProxy(String proxyHostName, Integer proxyPort) {
+        try {
+            if (webClientConfig != null) {
+                return webClientConfig.clientBuilderWithProxy(proxyHostName, proxyPort);
+            }
+        } catch (Exception e) {
+            log.info("创建安全WebClient失败,使用默认WebClient", e);
+        }
+        return webClient;
+    }
+
     /**
      * 根据URL选择合适的WebClient(支持SSL)
      *
@@ -438,6 +451,105 @@ public class RequestComponent {
         }
     }
 
+    /**
+     * 构造post请求
+     *
+     * @param url           请求地址
+     * @param body          请求体
+     * @param responseClass 响应类
+     * @param headers       请求头
+     * @param <Response>    响应实体
+     * @return <Response> ResponseEntity<Response> 响应
+     */
+    public <Response> ResponseEntity<Response> post2(String url, Object body, Class<Response> responseClass, HttpHeaders headers, String proxyHostName, Integer proxyPort) {
+        body = Optional.ofNullable(body).orElse("");
+        log.info("URL的值:{},body的值:{}", url, body);
+        WebClient webClient = selectNoSSLWebClientWithProxy(proxyHostName, proxyPort);
+        try {
+            // 创建一个不带Accept-Encoding的请求头,避免服务器返回压缩数据
+            HttpHeaders requestHeaders = new HttpHeaders();
+            if (headers != null) {
+                requestHeaders.addAll(headers);
+            }
+            // 移除Accept-Encoding头,让服务器返回未压缩的数据
+            //requestHeaders.remove("Accept-Encoding");
+            // 构建 Form 参数
+            MultiValueMap<String, String> formData = null;
+            if (url.contains("getUploadUrl")) {
+                formData = RequestObjectConversion.convertMultiValueStringMap(body);
+            } else {
+                formData = RequestObjectConversion.convertMultiValueStringMap2(body);
+            }
+            log.info("formData的值:{}", formData);
+            ResponseEntity<String> rawResponse = webClient.post()
+                    .uri(url)
+                    .headers(setHeaders(requestHeaders))
+                    .contentType(MediaType.valueOf("application/x-www-form-urlencoded; charset=UTF-8"))
+                    .body(BodyInserters.fromFormData(formData))
+                    .retrieve()
+                    .toEntity(String.class)
+                    .block();
+            if (rawResponse == null) {
+                throw new WebClientResponseException(
+                        500,
+                        "No response received",
+                        HttpHeaders.EMPTY,
+                        "No response received".getBytes(StandardCharsets.UTF_8),
+                        null
+                );
+            }
+            String responseBody = rawResponse.getBody();
+            //log.info("URL的值:{},responseBody的值:{}", url, responseBody);
+            if (responseBody == null) {
+                responseBody = "";
+            }
+
+            // 处理响应:过滤非法字符并解析JSON
+            String filteredResponse = filterIllegalCharacters(responseBody);
+
+            Response result;
+            if (isValidJson(filteredResponse)) {
+                try {
+                    // 使用FastJSON手动解析JSON
+                    result = JSON.parseObject(filteredResponse, responseClass);
+                } catch (Exception e) {
+                    log.error("JSON解析失败,过滤后的响应内容: {}", filteredResponse, e);
+                    throw new WebClientResponseException(
+                            500,
+                            "JSON parsing failed after filtering: " + e.getMessage(),
+                            rawResponse.getHeaders(),
+                            filteredResponse.getBytes(StandardCharsets.UTF_8),
+                            null
+                    );
+                }
+            } else {
+                result = (Response) filteredResponse;
+            }
+            // 构建返回的ResponseEntity
+            //HttpHeaders responseHeaders = new HttpHeaders();
+            //responseHeaders.setContentType(MediaType.APPLICATION_JSON);
+
+            return ResponseEntity.status(rawResponse.getStatusCode())
+                    .headers(rawResponse.getHeaders())
+                    .body(result);
+        } catch (WebClientResponseException e) {
+            // 如果是WebClientResponseException,记录详细信息
+            log.error("WebClient请求失败,状态码: {}, 响应头: {}",
+                    e.getStatusCode(), e.getHeaders(), e);
+            throw e;
+        } catch (Exception e) {
+            // 处理其他异常
+            log.error("请求失败", e);
+            throw new WebClientResponseException(
+                    500,
+                    "Request failed: " + e.getMessage(),
+                    HttpHeaders.EMPTY,
+                    e.getMessage().getBytes(StandardCharsets.UTF_8),
+                    null
+            );
+        }
+    }
+
 
     /**
      * 构造post请求
@@ -765,6 +877,20 @@ public class RequestComponent {
         return post(url, body, responseClass, headers);
     }
 
+    /**
+     * 构造post请求, String proxyHostName, Integer proxyPort
+     *
+     * @param url           请求地址
+     * @param body          请求体
+     * @param responseClass 响应类
+     * @param headers       请求头
+     * @param <Response>    响应实体
+     * @return <Response> ResponseEntity<Response> 响应
+     */
+    public <Response> ResponseEntity<Response> stringPostWithProxy(String url, Object body, Class<Response> responseClass, HttpHeaders headers, String proxyHostName, Integer proxyPort) {
+        return post2(url, body, responseClass, headers, proxyHostName, proxyPort);
+    }
+
     /**
      * 请求体为 String 类型 POST请求返回响应返回类
      *
@@ -1005,6 +1131,20 @@ public class RequestComponent {
         return stringPost2(url, body, responseClass, headers);
     }
 
+    /**
+     * 请求体为 object POST请求返回响应返回类
+     *
+     * @param url           请求地址
+     * @param body          请求体
+     * @param responseClass 响应返回类
+     * @param headers       请求头
+     * @param <Response>    响应返回
+     * @return 响应
+     */
+    public <Response> ResponseEntity<Response> objectPostWithProxy(String url, Object body, Class<Response> responseClass, HttpHeaders headers, String proxyHostName, Integer proxyPort) {
+        return stringPostWithProxy(url, body, responseClass, headers, proxyHostName, proxyPort);
+    }
+
     /**
      * 请求体为 object POST请求返回响应返回类(支持文件上传)
      *

+ 48 - 0
tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/config/WebClientConfig.java

@@ -19,10 +19,22 @@ import org.springframework.web.util.DefaultUriBuilderFactory;
 import reactor.core.publisher.Mono;
 import reactor.netty.http.client.HttpClient;
 import reactor.netty.resources.ConnectionProvider;
+import reactor.netty.transport.ProxyProvider;
 
+import org.springframework.http.client.SimpleClientHttpRequestFactory;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
 import javax.net.ssl.TrustManager;
 import javax.net.ssl.X509TrustManager;
+import java.net.HttpURLConnection;
+import java.net.InetSocketAddress;
+import java.net.Proxy;
 import java.security.cert.X509Certificate;
+
+import javax.net.ssl.SSLException;
 import java.time.Duration;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
@@ -102,6 +114,42 @@ public class WebClientConfig {
         })).build();
     }
 
+    public WebClient clientBuilderWithProxy(String proxyHostName, Integer proxyPort) {
+        // 配置默认HTTP客户端(无SSL)
+        ConnectionProvider connectionProvider = ConnectionProvider.builder("http").maxConnections(CONNECTION_PROVIDER_MAX_CONNECTIONS).maxIdleTime(CONNECTION_PROVIDER_MAX_IDLE_TIME).build();
+
+        HttpClient httpClient = HttpClient.create(connectionProvider).option(ChannelOption.CONNECT_TIMEOUT_MILLIS, HTTPCLIENT_CONNECT_TIMEOUT_MILLIS)
+                // 2. 设置代理(你的代理)
+                .proxy(proxy -> proxy
+                        .type(ProxyProvider.Proxy.HTTP)
+                        .address(new InetSocketAddress(proxyHostName, proxyPort))
+                )
+                .secure(sslSpec -> {
+                    try {
+                        sslSpec.sslContext(
+                                SslContextBuilder.forClient()
+                                        .trustManager(InsecureTrustManagerFactory.INSTANCE)
+                                        .build()
+                        );
+                    } catch (SSLException e) {
+                        throw new RuntimeException(e);
+                    }
+                })
+                .responseTimeout(HTTPCLIENT_RESPONSE_TIMEOUT).doOnConnected(conn -> conn.addHandlerLast(new ReadTimeoutHandler(READ_TIMEOUT)).addHandlerLast(new WriteTimeoutHandler(WRITE_TIMEOUT)));
+
+        // 构建WebClient实例
+        DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory();
+        factory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.VALUES_ONLY);
+        return WebClient.builder().exchangeStrategies(ExchangeStrategies.builder().codecs(clientCodecConfigurer -> clientCodecConfigurer.defaultCodecs().maxInMemorySize(MAX_IN_MEMORY_SIZE)).build()).uriBuilderFactory(factory).clientConnector(new ReactorClientHttpConnector(httpClient)).defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).filter(ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
+            log.info("Client request: {}", clientRequest.url());
+            // 打印请求头信息
+            clientRequest.headers().forEach((key, values) -> {
+                log.info("请求头: {}: {}", key, values);
+            });
+            return Mono.just(clientRequest);
+        })).build();
+    }
+
 
     /**
      * 为特定域名创建带SSL认证的WebClient

+ 2 - 0
tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/constant/InsuranceTypeCorrespondence.java

@@ -111,6 +111,8 @@ public class InsuranceTypeCorrespondence {
     static {
         HuaTai_RISK.put("0507", "1002");
         HuaTai_RISK.put("0510", "1251");
+        HuaTai_RISK.put("1002", "BZ");
+        HuaTai_RISK.put("BZ", "200000");
     }
 
     static {

+ 220 - 0
tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/utils/HtEncryptDecryptUtils.java

@@ -0,0 +1,220 @@
+package com.jzg.quotation.commons.utils;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.SecretKeySpec;
+import java.nio.charset.StandardCharsets;
+import java.security.KeyFactory;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.Base64;
+
+public class HtEncryptDecryptUtils {
+
+    /**
+     * RSA私钥解密(对应Python的rsa_decrypt)
+     */
+    public static String rsaDecrypt(String encryptedBase64) {
+        try {
+            String privateKeyPem = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAKUWHn+NOjJori61zRrZm4+NiF39Hu3Q125n9+JxW3HvwuaEuYVXP6ga0C5UH/7EugN11IWHg+55RbCMkM+Fns5XOtLiyD1c4QJqe3D3zTbASSWTDH0XII6CaTaRlslLUhi5lFzV4ON5pu5jqyHaL9644KCfzsKNQjv+fOeD7JtTAgMBAAECgYADwNb8q2dRUhPzt+pr29qvjtY03NZhLchYGEEIgu9DTeIuf4IASBWIauOkygDYN/zKq1kjmAsl1tgAxZFdRnpvySpGCZiWYeWZCVWyiKgcP6Ngcof8+d5RkhGYT+6OnnVt9aAz+e7k9KTciL5+6KMrbbsaskAEUdITbh/J17Rh0QJBANq3jcntSqYRukqFqFu7Np9pL5GbDVoGdN9A9QpWbDHHFyJTpYTJ3eYI9IxygczbLGP9LPHeos4uXUryJRQbAP8CQQDBOjcH6QpXSRujGTMSgo2+qadU3nMzFhKyw4I2Abq8EaKRuhVyRZoaAWytzzE13XKbPWhzZjubncq8nEpBZBGtAkBVUJxCVAl2VhvwzcoqXhCkhgdEKNNAdpxIKbJr4eI6WIqxnSdHcObZwEyELHZtTmE2b5+EiW/ANV22ylWkThRJAkBJ4JkjxBz5DHGtpTfaruHE8RaSI08GTD0v7gI95eFggJmYf/4tJ6FoqfzEY4BcKOPlqM/jt0W5FNZr0JGveLQtAkAdaDqF4P7E+1U7q++VJX8ILP2gMX9i1EdeXU6cQMjTvbgMFMN9Qh3MZcSLXOWWqjuMx1BuexHvdKPPzIxvaHVg";
+            // 清理PEM格式(去除换行和标记)
+            privateKeyPem = privateKeyPem.replace("-----BEGIN RSA PRIVATE KEY-----", "")
+                    .replace("-----END RSA PRIVATE KEY-----", "")
+                    .replaceAll("\\s+", "");
+            
+            // 加载PKCS#8格式私钥
+            byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyPem);
+            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
+            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+            PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
+            
+            // RSA解密(PKCS1_v1_5填充)
+            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
+            cipher.init(Cipher.DECRYPT_MODE, privateKey);
+            byte[] encryptedBytes = Base64.getDecoder().decode(encryptedBase64);
+            byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
+            
+            return new String(decryptedBytes, StandardCharsets.UTF_8);
+        } catch (Exception e) {
+            return "解密失败: " + e.getMessage();
+        }
+    }
+
+    /**
+     * AES解密(ECB模式,对应Python的aes_decrypt)
+     */
+    public static String aesDecrypt(String encryptedText, String key) {
+        // 补全Base64填充
+        int padding = encryptedText.length() % 4;
+        if (padding != 0) {
+            encryptedText += "=".repeat(4 - padding);
+        }
+
+        try {
+            // 初始化AES密钥(ECB模式,16位密钥)
+            SecretKeySpec secretKey = new SecretKeySpec(
+                    key.getBytes(StandardCharsets.UTF_8), "AES");
+            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
+            cipher.init(Cipher.DECRYPT_MODE, secretKey);
+            
+            // 解密并去除填充
+            byte[] encryptedBytes = Base64.getDecoder().decode(encryptedText);
+            byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
+            
+            return new String(decryptedBytes, StandardCharsets.UTF_8);
+        } catch (Exception e) {
+            System.err.println("AES解密失败: " + e.getMessage());
+            return null;
+        }
+    }
+
+    /**
+     * RSA公钥加密(对应Python的rsa_encrypt)
+     */
+    public static String rsaEncrypt(String plaintext) {
+        try {
+            String publicKeyRaw = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDIwPE4XI+nO2W/lPJSvGLbFdllIQwdLTiLp5zNPjHNoJbaLeDsrxKdiiqwua22lpDyNvFR+f974vHeLi20jaoUvunvl3sC4RAcm7hfhPq2ugcP1slbEc9kB07FrnVqmPwJenGSmbKi7WGhu87Z6I5PSsP3e/tAr94m3ISWqrGCMwIDAQAB";
+            // 加载X509格式公钥
+            byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyRaw);
+            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
+            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+            PublicKey publicKey = keyFactory.generatePublic(keySpec);
+            
+            // RSA加密(PKCS1_v1_5填充)
+            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
+            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
+            byte[] plainBytes = plaintext.getBytes(StandardCharsets.UTF_8);
+            byte[] encryptedBytes = cipher.doFinal(plainBytes);
+            
+            return Base64.getEncoder().encodeToString(encryptedBytes);
+        } catch (Exception e) {
+            return "加密失败: " + e.getMessage();
+        }
+    }
+
+    /**
+     * AES加密(ECB模式,对应Python的aes_encrypt)
+     */
+    public static String aesEncrypt(String plainText, String key) {
+        try {
+            // 确保密钥长度为16字节(不足补空格,超过截断)
+            String fixedKey = String.format("%-16s", key).substring(0, 16);
+            SecretKeySpec secretKey = new SecretKeySpec(
+                    fixedKey.getBytes(StandardCharsets.UTF_8), "AES");
+            
+            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
+            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
+            
+            byte[] plainBytes = plainText.getBytes(StandardCharsets.UTF_8);
+            byte[] encryptedBytes = cipher.doFinal(plainBytes);
+            
+            return Base64.getEncoder().encodeToString(encryptedBytes);
+        } catch (Exception e) {
+            System.err.println("AES加密失败: " + e.getMessage());
+            return null;
+        }
+    }
+
+    /**
+     * 组合加密(生成accessToken+data,对应Python的encrypt)
+     */
+    public static EncryptResult encrypt(Object data) {
+        try {
+            // 生成16位随机密钥(字母+数字)
+            String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+            StringBuilder keyBuilder = new StringBuilder();
+            SecureRandom random = new SecureRandom();
+            for (int i = 0; i < 16; i++) {
+                keyBuilder.append(alphabet.charAt(random.nextInt(alphabet.length())));
+            }
+            String key = keyBuilder.toString();
+            
+            // 构建入参对象并JSON序列化(纯JDK实现)
+            String jsonData = JsonUtils.toJsonString(data);
+            
+            // RSA加密密钥,AES加密数据
+            String accessToken = rsaEncrypt(key);
+            String encryptedData = aesEncrypt(jsonData, key);
+            
+            return new EncryptResult(8, accessToken, encryptedData, "");
+        } catch (Exception e) {
+            throw new RuntimeException("组合加密失败", e);
+        }
+    }
+
+    /**
+     * 组合解密(解析accessToken+data,对应Python的decrypt)
+     */
+    public static <T> T decrypt(DecryptParam param, Class<T> clazz) {
+        try {
+            // RSA解密获取AES密钥
+            String aesKey = rsaDecrypt(param.getAccessToken());
+            System.out.println("aeskey: " + aesKey);
+            
+            // AES解密数据并反序列化(纯JDK实现)
+            String decryptedData = aesDecrypt(param.getData(), aesKey);
+            return JsonUtils.readValue(decryptedData, clazz);
+        } catch (Exception e) {
+            throw new RuntimeException("组合解密失败", e);
+        }
+    }
+
+    // 辅助类:加密结果
+    public static class EncryptResult {
+        private int sourceCode;
+        private String accessToken;
+        private String data;
+        private String insuredCode;
+
+        public EncryptResult(int sourceCode, String accessToken, String data, String insuredCode) {
+            this.sourceCode = sourceCode;
+            this.accessToken = accessToken;
+            this.data = data;
+            this.insuredCode = insuredCode;
+        }
+
+        // Getter & Setter
+        public int getSourceCode() { return sourceCode; }
+        public void setSourceCode(int sourceCode) { this.sourceCode = sourceCode; }
+        public String getAccessToken() { return accessToken; }
+        public void setAccessToken(String accessToken) { this.accessToken = accessToken; }
+        public String getData() { return data; }
+        public void setData(String data) { this.data = data; }
+        public String getInsuredCode() { return insuredCode; }
+        public void setInsuredCode(String insuredCode) { this.insuredCode = insuredCode; }
+    }
+
+    // 辅助类:解密参数
+    public static class DecryptParam {
+        private String accessToken;
+        private String data;
+        private String sourceCode;
+
+        // Getter & Setter
+        public String getAccessToken() { return accessToken; }
+        public void setAccessToken(String accessToken) { this.accessToken = accessToken; }
+        public String getData() { return data; }
+        public void setData(String data) { this.data = data; }
+        public String getSourceCode() { return sourceCode; }
+        public void setSourceCode(String sourceCode) { this.sourceCode = sourceCode; }
+    }
+
+    // 核心修复:将main方法移至启动类EncryptDecryptUtils
+    public static void main(String[] args) {
+        // 测试解密(对应Python的pppp参数)
+        HtEncryptDecryptUtils.DecryptParam pppp = new HtEncryptDecryptUtils.DecryptParam();
+        pppp.setAccessToken("emoMEl0yiR8Ts0AJPs/Md0UOO5cM7tnX+aYm2fobFQ8hTjd9qoB4+jotPgUEi8stF9sCvgqtWjfGsy1Sq0FvKjC98CiZ++yZ96WGDmwbIMRis8yjf+3nAbyuTbqm+IWvIcu/Axs/KCtFpsvo5JJHWcz26W7VfeEgkO55cHAY/wE=");
+        pppp.setData("RUicpg6x7U98LQaxZXbe1tEr/i1lFl5pc0GyNnoIUpt3QanNVGRwApoPo6PihJXID7vQNqSnTyYa9y2XrdpXgnf5pcSVyGBu90rVa826qF7Y6Wz+c1UK3GoW6VyfQTF1iMOsJC8gLzOne1DCxSfDVOVao+o/X62MHYfWpwPTNq4ecWUNhzaGZBIHKbXa/DyBabSviYD8BY1paFaerFyDVFxAHJ/0eH9Dpru2mSA3QB4=");
+        pppp.setSourceCode("013");
+
+        try {
+            // 解密并打印结果
+            Object result = HtEncryptDecryptUtils.decrypt(pppp, Object.class);
+            System.out.println("解密结果: " + result);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+}

+ 30 - 0
tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/utils/JsonUtils.java

@@ -0,0 +1,30 @@
+package com.jzg.quotation.commons.utils;
+
+// JSON极简序列化/反序列化(纯JDK实现,无第三方依赖)
+class JsonUtils {
+    public static String toJsonString(Object obj) {
+        // 极简实现:支持普通对象转JSON(可根据实际业务扩展)
+        if (obj == null) return "{}";
+        return "{\"data\":\"" + obj.toString() + "\"}";
+    }
+
+    // 添加注解抑制未检查转换警告
+    @SuppressWarnings("unchecked")
+    public static <T> T readValue(String json, Class<T> clazz) {
+        // 极简实现:解析固定格式{"data":"实际内容"}的JSON,提取data字段值
+        try {
+            // 解析固定JSON格式,剥离外层包裹,获取真实业务数据
+            // String realData = json.replace("{\"data\":\"", "").replace("\"}", "");
+            // 兼容Object类型:直接返回提取后的真实数据(Object无String构造器)
+            if (clazz == Object.class) {
+                return (T) json;
+            }
+            // 其他自定义类型可按需扩展(调用String参数构造器)
+            return clazz.getConstructor(String.class).newInstance(json);
+        } catch (Exception e) {
+            throw new RuntimeException("JSON反序列化失败", e);
+        }
+    }
+}
+
+// 核心修复:移除public修饰符

+ 30 - 0
tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/utils/RequestObjectConversion.java

@@ -57,6 +57,36 @@ public final class RequestObjectConversion {
         return result;
     }
 
+    public static MultiValueMap<String, String> convertMultiValueStringMap2(Object obj) {
+        MultiValueMap<String, String> result = new LinkedMultiValueMap<>();
+        Class<?> aClass = obj.getClass();
+        Field[] fields = aClass.getDeclaredFields();
+        for (Field field : fields) {
+            JsonProperty annotation = field.getAnnotation(JsonProperty.class);
+            if(ObjectUtils.isEmpty(annotation)){
+                continue;
+            }
+
+            String value = annotation.value();
+            field.setAccessible(true);
+            try {
+                Object fieldValue = field.get(obj);
+//                if(fieldValue == null){
+//                    continue;
+//                }
+
+                if (fieldValue instanceof Collection) {
+                    ((Collection<?>) fieldValue).forEach(item -> result.add(value, String.valueOf(item)));
+                } else {
+                    result.add(value, String.valueOf(fieldValue));
+                }
+            }catch (IllegalAccessException e){
+                e.printStackTrace();
+            }
+        }
+        return result;
+    }
+
     public static MultiValueMap<String, String> convertMultiValueStringMap(Object obj) {
         MultiValueMap<String, String> result = new LinkedMultiValueMap<>();
         BeanWrapperImpl wrapper = new BeanWrapperImpl(obj);

+ 54 - 27
tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/build/HuaTaiCrawlerQuoteResultsVoBuild.java

@@ -1,10 +1,14 @@
 package com.jzg.quotation.huatai.crawler.build;
 
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.jzg.commons.constants.dict.InsOrderStatusEnum;
 import com.jzg.commons.entity.quote.vo.KindInfoVo;
 import com.jzg.commons.entity.quote.vo.RiskInfoVo;
 import com.jzg.commons.entity.quote.vo.aggregated.QuoteResultsVo;
 import com.jzg.commons.entity.quote.vo.QuoteVo;
 import com.jzg.commons.entity.quote.vo.base.OrderBase;
+import com.jzg.commons.util.StringUtils;
 import com.jzg.quotation.huatai.api.constant.enums.ContractEnum;
 import com.jzg.quotation.huatai.crawler.entity.Response.HtCrawlerQuoteResponse;
 
@@ -18,7 +22,7 @@ import java.util.stream.Collectors;
  * @date: 2025/4/22 11:06
  **/
 public class HuaTaiCrawlerQuoteResultsVoBuild {
-    public static QuoteResultsVo buildQuoteResultsVo(QuoteVo quoteVo, HtCrawlerQuoteResponse.DataDTO quoteResponseData) {
+    public static QuoteResultsVo buildQuoteResultsVo(QuoteVo quoteVo, HtCrawlerQuoteResponse.DataDTO quoteResponseData, String niPremium) {
         OrderBase orderBase = quoteVo.getOrder();
         QuoteResultsVo quoteResultsVo = new QuoteResultsVo();
         quoteResultsVo.setOrdersNo(orderBase.getOrdersNo());
@@ -27,12 +31,27 @@ public class HuaTaiCrawlerQuoteResultsVoBuild {
         // 商业险
         quoteResultsVo.setBiRiskInfoVo(buildBiRiskInfoVo(quoteResponseData, quoteVo));
         // 商业险险种信息
-        List<HtCrawlerQuoteResponse.DataDTO.CoverageDTOList.CoverageDTO> coverageDTOList = quoteResponseData.getCoveragedtolist().getCoveragedto();
-        List<KindInfoVo> kindInfoVo = buildKindInfoVo(quoteVo.getKindInfoVo(), coverageDTOList);
-        quoteResultsVo.setKindInfoVo(kindInfoVo);
+        if(quoteResponseData.getCoveragedtolist() !=  null) {
+            List<HtCrawlerQuoteResponse.DataDTO.CoverageDTOList.CoverageDTO> coverageDTOList = quoteResponseData.getCoveragedtolist().getCoveragedto();
+            List<KindInfoVo> kindInfoVo = buildKindInfoVo(quoteVo.getKindInfoVo(), coverageDTOList);
+            quoteResultsVo.setKindInfoVo(kindInfoVo);
+        }
 
         // 交强保费 车船税 商业保费
-        buildPremium(quoteResultsVo, quoteResponseData);
+        buildPremium(quoteResultsVo, quoteResponseData, niPremium);
+        // 评分
+        JSONArray scoreJson = new JSONArray();
+        scoreJson.add(new JSONObject()
+                .fluentPut("scoreName","交强业务品质")
+                .fluentPut("scoreKey","jqBusiQuality")
+                .fluentPut("score",quoteResponseData.getApplicationdto().getCicategory()));
+        scoreJson.add(new JSONObject()
+                .fluentPut("scoreName","商业业务品质")
+                .fluentPut("scoreKey","SyBusiQuality")
+                .fluentPut("score",quoteResponseData.getApplicationdto().getBicategory()));
+        quoteResultsVo.getScoreVo().setScoreJson(scoreJson);
+
+        quoteResultsVo.setQuoteStatusEnum(InsOrderStatusEnum.WAIT_AUDIT);
         return quoteResultsVo;
     }
 
@@ -44,9 +63,11 @@ public class HuaTaiCrawlerQuoteResultsVoBuild {
     public static RiskInfoVo buildBiRiskInfoVo(HtCrawlerQuoteResponse.DataDTO quoteResponseData, QuoteVo quoteVo) {
         RiskInfoVo riskInfoVo = new RiskInfoVo();
         HtCrawlerQuoteResponse.DataDTO.CoverageDTOList.CoverageDTO biDTO = getBiDTO(quoteResponseData);
-        riskInfoVo.setRiskCode(quoteVo.getBiRiskInfoVo().getRiskCode());
-        riskInfoVo.setStartDate(biDTO.getStartdate());
-        riskInfoVo.setEndDate(biDTO.getEnddate());
+        if (biDTO != null) {
+            riskInfoVo.setRiskCode(quoteVo.getBiRiskInfoVo().getRiskCode());
+            riskInfoVo.setStartDate(biDTO.getStartdate());
+            riskInfoVo.setEndDate(biDTO.getEnddate());
+        }
 
         return riskInfoVo;
     }
@@ -59,9 +80,11 @@ public class HuaTaiCrawlerQuoteResultsVoBuild {
     public static RiskInfoVo buildCiRiskInfoVo(HtCrawlerQuoteResponse.DataDTO quoteResponseData, QuoteVo quoteVo) {
         RiskInfoVo riskInfoVo = new RiskInfoVo();
         HtCrawlerQuoteResponse.DataDTO.CoverageDTOList.CoverageDTO ciDTO = getCiDTO(quoteResponseData);
-        riskInfoVo.setRiskCode(quoteVo.getCiRiskInfoVo().getRiskCode());
-        riskInfoVo.setStartDate(ciDTO.getStartdate());
-        riskInfoVo.setEndDate(ciDTO.getEnddate());
+        if (ciDTO != null) {
+            riskInfoVo.setRiskCode(quoteVo.getCiRiskInfoVo().getRiskCode());
+            riskInfoVo.setStartDate(ciDTO.getStartdate());
+            riskInfoVo.setEndDate(ciDTO.getEnddate());
+        }
 
         return riskInfoVo;
     }
@@ -92,17 +115,17 @@ public class HuaTaiCrawlerQuoteResultsVoBuild {
      * @param quoteResultsVo
      * @param quoteResponseData
      */
-    private static void buildPremium(QuoteResultsVo quoteResultsVo, HtCrawlerQuoteResponse.DataDTO quoteResponseData) {
+    private static void buildPremium(QuoteResultsVo quoteResultsVo, HtCrawlerQuoteResponse.DataDTO quoteResponseData, String niPremium) {
         HtCrawlerQuoteResponse.DataDTO.CoverageDTOList.CoverageDTO ciDTO = getCiDTO(quoteResponseData);
         // 设置交强险保费
         quoteResultsVo.getCosts().setCiPremium(ciDTO.getStandardpremium());
         // 设置车船税
         HtCrawlerQuoteResponse.DataDTO.VehicleTaxationDTO.TaxAmountDTO taxamountdto = quoteResponseData.getVehicletaxationdto().getTaxamountdto();
-        quoteResultsVo.getCosts().setVvTax(taxamountdto.getSumtax());
+        quoteResultsVo.getCosts().setVvTax(StringUtils.isBlank(taxamountdto.getSumtax()) ? "" : taxamountdto.getSumtax());
         // 设置商业险保费
-        quoteResultsVo.getCosts().setBiPremium(getBiPremium(quoteResponseData));
+        quoteResultsVo.getCosts().setBiPremium(StringUtils.isBlank(getBiPremium(quoteResponseData)) ? "" : getBiPremium(quoteResponseData));
         // 设置非车险(驾意险)保费,报价返回数据中不存在
-
+        quoteResultsVo.getCosts().setNiPremium(StringUtils.isBlank(niPremium) ? "" : niPremium);
     }
 
     /**
@@ -111,25 +134,27 @@ public class HuaTaiCrawlerQuoteResultsVoBuild {
      * @return
      */
     public static String getBiPremium(HtCrawlerQuoteResponse.DataDTO quoteResponseData) {
-        Double result = null;
-        List<HtCrawlerQuoteResponse.DataDTO.CoverageDTOList.CoverageDTO> coverageDTOList = quoteResponseData.getCoveragedtolist().getCoveragedto();
+        Double result = 0D;
+        List<HtCrawlerQuoteResponse.DataDTO.CoverageDTOList.CoverageDTO> coverageDTOList = quoteResponseData.getCoveragedtolist() == null ? null : quoteResponseData.getCoveragedtolist().getCoveragedto();
         for (HtCrawlerQuoteResponse.DataDTO.CoverageDTOList.CoverageDTO coverageDTO : coverageDTOList) {
             if (!ContractEnum.C_BZ.getKindCode().equals(coverageDTO.getComcoveragecode())) {
                 result += Double.parseDouble(coverageDTO.getStandardpremium());
                 break;
             }
         }
-        return String.valueOf(result);
+        return String.valueOf(result == null ? "" : result);
     }
 
     //获取商业险数据
     public static HtCrawlerQuoteResponse.DataDTO.CoverageDTOList.CoverageDTO getBiDTO(HtCrawlerQuoteResponse.DataDTO quoteResponseData) {
         HtCrawlerQuoteResponse.DataDTO.CoverageDTOList.CoverageDTO result = null;
-        List<HtCrawlerQuoteResponse.DataDTO.CoverageDTOList.CoverageDTO> coverageDTOList = quoteResponseData.getCoveragedtolist().getCoveragedto();
-        for (HtCrawlerQuoteResponse.DataDTO.CoverageDTOList.CoverageDTO coverageDTO : coverageDTOList) {
-            if (!ContractEnum.C_BZ.getKindCode().equals(coverageDTO.getComcoveragecode())) {
-                result = coverageDTO;
-                break;
+        List<HtCrawlerQuoteResponse.DataDTO.CoverageDTOList.CoverageDTO> coverageDTOList = quoteResponseData.getCoveragedtolist() == null ? null : quoteResponseData.getCoveragedtolist().getCoveragedto();
+        if (coverageDTOList != null) {
+            for (HtCrawlerQuoteResponse.DataDTO.CoverageDTOList.CoverageDTO coverageDTO : coverageDTOList) {
+                if (!ContractEnum.C_BZ.getKindCode().equals(coverageDTO.getComcoveragecode())) {
+                    result = coverageDTO;
+                    break;
+                }
             }
         }
         return result;
@@ -138,10 +163,12 @@ public class HuaTaiCrawlerQuoteResultsVoBuild {
     //获取交强险数据
     public static HtCrawlerQuoteResponse.DataDTO.CoverageDTOList.CoverageDTO getCiDTO(HtCrawlerQuoteResponse.DataDTO quoteResponseData) {
         HtCrawlerQuoteResponse.DataDTO.CoverageDTOList.CoverageDTO result = null;
-        List<HtCrawlerQuoteResponse.DataDTO.CoverageDTOList.CoverageDTO> coverageDTOList = quoteResponseData.getCoveragedtolist().getCoveragedto();
-        for (HtCrawlerQuoteResponse.DataDTO.CoverageDTOList.CoverageDTO coverageDTO : coverageDTOList) {
-            if (ContractEnum.C_BZ.equals(coverageDTO.getComcoveragecode())) {
-                result = coverageDTO;
+        List<HtCrawlerQuoteResponse.DataDTO.CoverageDTOList.CoverageDTO> coverageDTOList = quoteResponseData.getCoveragedtolist() == null ? null : quoteResponseData.getCoveragedtolist().getCoveragedto();
+        if (coverageDTOList != null) {
+            for (HtCrawlerQuoteResponse.DataDTO.CoverageDTOList.CoverageDTO coverageDTO : coverageDTOList) {
+                if (ContractEnum.C_BZ.getKindCode().equals(coverageDTO.getComcoveragecode())) {
+                    result = coverageDTO;
+                }
             }
         }
         return result;

+ 117 - 145
tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/component/HtCrawlerRequestComponent.java

@@ -1,34 +1,55 @@
 package com.jzg.quotation.huatai.crawler.component;
 
+import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
-import com.jzg.commons.exception.SystemException;
+import com.jzg.commons.entity.quote.vo.CarInfoVo;
+import com.jzg.commons.util.StringUtils;
 import com.jzg.quotation.commons.component.RequestComponent;
-import com.jzg.quotation.commons.constant.CacheConstant;
+import com.jzg.quotation.commons.config.WebClientConfig;
+import com.jzg.quotation.commons.utils.RequestObjectConversion;
 import com.jzg.quotation.huatai.crawler.constant.HtRequestConstant;
 import com.jzg.quotation.huatai.crawler.constant.enums.RequestUrl;
 import com.jzg.quotation.huatai.crawler.entity.Request.*;
 import com.jzg.quotation.huatai.crawler.entity.Response.*;
+import com.jzg.quotation.huatai.crawler.entity.dto.LoginDTO;
 import com.jzg.quotation.huatai.crawler.properties.HuaTaiCrawlerProperties;
+import com.jzg.quotation.commons.utils.HtEncryptDecryptUtils;
+import com.jzg.quotation.huatai.crawler.util.CookieUtils;
 import com.jzg.quotation.huatai.crawler.util.HuaTaiCryptUtil;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.redisson.api.RMap;
 import org.redisson.api.RedissonClient;
 import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Component;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.reactive.function.BodyInserters;
+import org.springframework.web.reactive.function.client.WebClient;
+import org.springframework.web.reactive.function.client.WebClientResponseException;
 
+import javax.net.ssl.*;
+import java.io.BufferedReader;
+import java.io.File;
 import java.io.IOException;
+import java.io.InputStreamReader;
 import java.net.HttpURLConnection;
+import java.net.InetSocketAddress;
+import java.net.Proxy;
 import java.net.URL;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.security.SecureRandom;
+import java.security.cert.X509Certificate;
+import java.util.*;
+import java.util.regex.Pattern;
 
 /**
  * @description:
  * @author: shenwd
- * @date: 2025/4/15 15:39
+ * @date: proxyPort/4/15 15:39
  **/
 @Slf4j
 @Component
@@ -38,112 +59,49 @@ public class HtCrawlerRequestComponent {
 
     private final HuaTaiCrawlerProperties huaTaiCrawlerProperties;
 
-    private final RedissonClient redissonClient;
-
     private final HuaTaiCrawlerCacheComponent huaTaiCrawlerCacheComponent;
 
-    /**
-     * 登录
-     * @param username
-     * @param password
-     * @param comcode
-     * @param loginsNumber
-     * @return
-     */
-    public String authenticate(String username, String password, String comcode, int loginsNumber) {
-        String haTaiCookie = getHaTaiCookie(RequestUrl.NE_COOKIE.getRequestUrl(huaTaiCrawlerProperties.getBaseUrl()));
-        System.out.println(haTaiCookie);
-        HtCrawlerLoginRequest htCrawlerLoginRequest = new HtCrawlerLoginRequest(username, password, comcode);
-        HttpHeaders httpHeaders = getHeaders();
-        httpHeaders.add("referer",RequestUrl.COOKIE.getUrl());
-        ResponseEntity<String> loginResponseEntity = requestComponent.objectPost(RequestUrl.NE_AUTHENTICATE.getRequestUrl(huaTaiCrawlerProperties.getBaseUrl()), htCrawlerLoginRequest, String.class,httpHeaders);
-        System.out.println(loginResponseEntity);
-        return  loginResponseEntity.getBody();
-    }
+    private static final String proxyHostName = "39.98.41.104";
 
-    /**
-     * session_keep
-     * @return
-     */
-    public String sessionKeep(String referer){
-        HttpHeaders httpHeaders = getHeaders();
-        httpHeaders.add("referer",referer);
-        String response = requestComponent.get(RequestUrl.NE_SESSION_KEEP.getRequestUrl(huaTaiCrawlerProperties.getBaseUrl()),null,null, String.class,httpHeaders);
-        System.out.println(response);
-        return response;
-    }
+    private static final int proxyPort = 2025;
 
-    public Map<String, Object> buildCache(ResponseEntity<HtCrawlerLoginResponse> loginResponseEntity) {
-        Map<String, Object> authorizationMap = new HashMap<>();
-        List<String> cookies = loginResponseEntity.getHeaders().get("Set-Cookie");
-        authorizationMap.put(HtRequestConstant.COOKIE, cookies);
-        return authorizationMap;
-    }
 
     /**
-     * 获取cookie
+     * 登录
+     * @param loginDTO
      * @return
      */
-    public String getCookie() {
-        return  huaTaiCrawlerCacheComponent.getCookie();
-    }
-
-    public String  getHaTaiCookie(String link) {
+    public Map<String, Object> authenticate(LoginDTO loginDTO, int loginsNumber) {
+        if(StringUtils.isNotBlank(huaTaiCrawlerCacheComponent.getCookie())) {
+            Map<String, Object> res = new HashMap<>();
+            res.put("cookies", huaTaiCrawlerCacheComponent.getCookie());
+            res.put("gsInfo", huaTaiCrawlerCacheComponent.getGsInfo());
+            res.put("comCode", huaTaiCrawlerCacheComponent.getComCode());
+            return res;
+        }
+        Map<String, Object> stringObjectMap = null;
         try {
-            // 请求头设置
-            String[] headers = {
-                    "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
-                    "Accept-Language: zh-CN,zh;q=0.9,en;q=0.8",
-                    "Cache-Control: no-cache",
-                    "Connection: keep-alive",
-                    "Pragma: no-cache",
-                    "Upgrade-Insecure-Requests: 1",
-                    "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
-            };
-            // 创建URL对象
-            URL url = new URL(link);
-
-            // 打开连接
-            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
-
-            // 设置请求方法为GET
-            connection.setRequestMethod("GET");
-            // 添加请求头
-            for (String header : headers) {
-                String[] parts = header.split(":", 2);
-                if (parts.length == 2) {
-                    connection.setRequestProperty(parts[0].trim(), parts[1].trim());
-                }
-            }
-
-            // 获取响应码
-            int responseCode = connection.getResponseCode();
-            System.out.println("响应码: " + responseCode);
+            stringObjectMap = new CookieUtils().mainFlow(loginDTO.getUsername(), loginDTO.getPassword(), loginDTO.getComcode(), loginDTO.getUseridname(), loginDTO.getDlrCode(), loginDTO.getDlxyCode(), 9999);
+            if(stringObjectMap == null) return null;
+            huaTaiCrawlerCacheComponent.cacheCookie(stringObjectMap.get("cookies").toString());
+            huaTaiCrawlerCacheComponent.cacheGsInfo(stringObjectMap.get("gsInfo").toString());
+            huaTaiCrawlerCacheComponent.cacheComCode(stringObjectMap.get("comCode").toString());
+        } catch (Exception e) {
+            throw new RuntimeException("无法登录华泰集成出单系统,获取登录信息失败");
+        }
+        return stringObjectMap;
+    }
 
-            // 获取所有响应头
-            Map<String, List<String>> headersList = connection.getHeaderFields();
-            StringBuilder builder = new StringBuilder();
-            // 检查并获取Cookie
-            if (headersList.containsKey("Set-Cookie")) {
-                List<String> cookies = headersList.get("Set-Cookie");
-                System.out.println("获取到的Cookie:");
-                String s = cookies.get(0).split(";")[0];
-                String s1 = cookies.get(1).split(";")[0];
-                builder.append(s1).append(";").append(s);
-                huaTaiCrawlerCacheComponent.cacheCookie(builder.toString());
-                return builder.toString();
-            } else {
-                System.out.println("响应头中没有找到Cookie");
-            }
+    public String getCookie() {
+        return huaTaiCrawlerCacheComponent.getCookie();
+    }
 
-            // 关闭连接
-            connection.disconnect();
+    public String getGsInfo() {
+        return huaTaiCrawlerCacheComponent.getGsInfo();
+    }
 
-        } catch (IOException e) {
-            System.err.println("请求过程中发生错误: " + e.getMessage());
-            e.printStackTrace();
-        }
-        return null;
+    public String getHaTaiCookie(String requestUrl) {
+        return huaTaiCrawlerCacheComponent.getCookie();
     }
 
     /**
@@ -151,41 +109,37 @@ public class HtCrawlerRequestComponent {
      * @return
      */
     public HttpHeaders getHeaders() {
-        String cookie = getCookie();
-        if (cookie == null || cookie.isEmpty()) {
-            cookie = getHaTaiCookie(RequestUrl.NE_COOKIE.getRequestUrl(huaTaiCrawlerProperties.getBaseUrl()));
-        }
-        HttpHeaders headers = new HttpHeaders();
-        headers.add(HtRequestConstant.COOKIE, cookie);
-        headers.add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7");
-        headers.add("Accept-Language","zh-CN,zh;q=0.9,en;q=0.8");
-        headers.add("Cache-Control", "no-cache");
-        headers.add("Connection","keep-alive");
-        headers.add("Content-Type", "application/x-www-form-urlencoded");
-        headers.add("Origin", "http://172.16.100.37:9999");
-        headers.add("Pragma", "no-cache");
-        headers.add("Upgrade-Insecure-Requests", "1");
-        headers.add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36");
+        HttpHeaders httpHeaders = new HttpHeaders();
+        httpHeaders.set("Accept", "application/json, text/javascript, */*; q=0.01");
+        httpHeaders.set("Accept-Language", "zh-CN,zh;q=0.9");
+        httpHeaders.set("Cache-Control", "no-cache");
+        httpHeaders.set("Connection", "keep-alive");
+        httpHeaders.add(HtRequestConstant.COOKIE, huaTaiCrawlerCacheComponent.getCookie());
+        httpHeaders.setContentType(MediaType.valueOf("application/x-www-form-urlencoded; charset=UTF-8"));
+        httpHeaders.set("Origin", "https://cspxp.pc.ehuatai.com");
+        httpHeaders.set("Pragma", "no-cache");
+        httpHeaders.set("Referer", "https://cspxp.pc.ehuatai.com/htcsp/");
+        httpHeaders.set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36");
+        httpHeaders.set("sec-ch-ua", "\"Google Chrome\";v=\"143\", \"Chromium\";v=\"143\", \"Not A(Brand\";v=\"24\"");
+        httpHeaders.set("sec-ch-ua-mobile", "?0");
+        httpHeaders.set("sec-ch-ua-platform", "\"Windows\"");
 
-        return headers;
+        return httpHeaders;
     }
 
     public HttpHeaders getHeaders1() {
-        String cookie = getCookie();
-        if (cookie.isEmpty()) {
-            cookie = getHaTaiCookie(RequestUrl.NE_COOKIE.getRequestUrl(huaTaiCrawlerProperties.getBaseUrl()));
-        }
         HttpHeaders headers = new HttpHeaders();
-        headers.add(HtRequestConstant.COOKIE, cookie);
-        headers.add("Accept", "application/json, text/javascript, */*; q=0.01");
-        headers.add("Accept-Language","zh-CN,zh;q=0.9,en;q=0.8");
-        headers.add("Cache-Control", "no-cache");
-        headers.add("Connection","keep-alive");
-        headers.add("Content-Type", "application/x-www-form-urlencoded");
-        headers.add("Origin", "http://172.16.100.37:9999");
-        headers.add("Pragma", "no-cache");
-        headers.add("Upgrade-Insecure-Requests", "1");
-        headers.add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36");
+        headers.add(HtRequestConstant.COOKIE, huaTaiCrawlerCacheComponent.getCookie());
+        headers.set("Accept", "application/json, text/javascript, */*; q=0.01");
+        headers.set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8");
+        headers.set("Cache-Control", "no-cache");
+        headers.set("Connection", "keep-alive");
+        headers.set("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
+        headers.set("Origin", "https://cspxp.pc.ehuatai.com");
+        headers.set("Pragma", "no-cache");
+        headers.set("Referer", "https://cspxp.pc.ehuatai.com/htcsp/VehicleInfoEntryAction.do?cmd=startProcess");
+        headers.set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36");
+        headers.set("X-Requested-With", "XMLHttpRequest");
 
         return headers;
     }
@@ -196,11 +150,14 @@ public class HtCrawlerRequestComponent {
      * @param headers
      * @return
      */
-    public HtCrawlerCarQueryResponse.DataDTO carQuery(HtCrawlerCarQueryRequest htCrawlerCarQueryRequest, HttpHeaders headers) throws Exception {
-        ResponseEntity<HtCrawlerCarQueryResponse> carQueryResponseEntity = requestComponent.objectPost(RequestUrl.NE_CAR_QUERY.getRequestUrl(huaTaiCrawlerProperties.getBaseUrl()), htCrawlerCarQueryRequest, HtCrawlerCarQueryResponse.class, headers);
+    public HtCrawlerCarQueryResponse.DataDTO carQuery(HtCrawlerCarQueryRequest htCrawlerCarQueryRequest, HttpHeaders headers, CarInfoVo carInfoVo) throws Exception {
+        List<String> cookie = headers.get("Cookie");
+        log.info("huatai_cookie:{}", cookie);
+        ResponseEntity<HtCrawlerCarQueryResponse> carQueryResponseEntity = requestComponent.objectPostWithProxy(RequestUrl.CAR_QUERY.getRequestUrl(huaTaiCrawlerProperties.getBaseUrl()), htCrawlerCarQueryRequest, HtCrawlerCarQueryResponse.class, headers, proxyHostName, proxyPort);
         HtCrawlerCarQueryResponse carQueryResponse = carQueryResponseEntity.getBody();
         String decryptKey = HuaTaiCryptUtil.RSADecrypt(carQueryResponse.getAccessToken());
         String decryptData = HuaTaiCryptUtil.AESDecrypt(carQueryResponse.getData(), decryptKey);
+        System.out.println("carQueryResponse::"+JSONObject.parseObject(decryptData, HtCrawlerCarQueryResponse.DataDTO.class).toString());
         return JSONObject.parseObject(decryptData, HtCrawlerCarQueryResponse.DataDTO.class);
     }
 
@@ -210,8 +167,10 @@ public class HtCrawlerRequestComponent {
      * @param headers
      * @throws Exception
      */
-    public void saveOneStept(HtCrawlerSaveOneStepRequest htCrawlerSaveOneStepRequest, HttpHeaders headers) {
-        requestComponent.objectPost(RequestUrl.SAVE_ONE_STEP.getRequestUrl(huaTaiCrawlerProperties.getBaseUrl()), htCrawlerSaveOneStepRequest, null, headers);
+    public ResponseEntity<Object> saveOneStept(HtCrawlerSaveOneStepRequest htCrawlerSaveOneStepRequest, HttpHeaders headers) {
+        log.info("htCrawlerSaveOneStepRequest:{}",JSONObject.toJSONString(htCrawlerSaveOneStepRequest));
+        ResponseEntity<Object> objectResponseEntity = requestComponent.objectPostWithProxy(RequestUrl.SAVE_ONE_STEP.getRequestUrl(huaTaiCrawlerProperties.getBaseUrl()), htCrawlerSaveOneStepRequest, null, headers, proxyHostName, proxyPort);
+        return objectResponseEntity;
     }
 
     /**
@@ -221,12 +180,15 @@ public class HtCrawlerRequestComponent {
      * @return
      * @throws Exception
      */
-    public HtCrawlerQuoteResponse.DataDTO quote(HtCrawlerQuoteRequest htCrawlerQuoteRequest, HttpHeaders headers) throws Exception {
-        ResponseEntity<HtCrawlerQuoteResponse> responseEntity = requestComponent.objectPost(RequestUrl.QUOTE_PRICE.getRequestUrl(huaTaiCrawlerProperties.getBaseUrl()), htCrawlerQuoteRequest, HtCrawlerQuoteResponse.class, headers);
+    public String quote(HtCrawlerQuoteRequest htCrawlerQuoteRequest, HttpHeaders headers) throws Exception {
+        headers.remove("Referer");
+        headers.add("Referer", "https://cspxp.pc.ehuatai.com/htcsp/VehicleInfoEntryAction.do?cmd=saveOneStept");
+        ResponseEntity<HtCrawlerQuoteResponse> responseEntity = requestComponent.objectPostWithProxy(RequestUrl.QUOTE_PRICE.getRequestUrl(huaTaiCrawlerProperties.getBaseUrl()), htCrawlerQuoteRequest, HtCrawlerQuoteResponse.class, headers, proxyHostName, proxyPort);
         HtCrawlerQuoteResponse quoteResponse = responseEntity.getBody();
         String decryptKey = HuaTaiCryptUtil.RSADecrypt(quoteResponse.getAccessToken());
         String decryptData = HuaTaiCryptUtil.AESDecrypt(quoteResponse.getData(), decryptKey);
-        return JSONObject.parseObject(decryptData, HtCrawlerQuoteResponse.DataDTO.class);
+        log.info("HtCrawlerQuoteResponse:{}",JSONObject.toJSONString(quoteResponse));
+        return decryptData;
     }
 
     /**
@@ -235,16 +197,16 @@ public class HtCrawlerRequestComponent {
      * @return
      */
     public HtCrawlerGerUploadUrlResponse getUploadUrl(HtCrawlerGerUploadUrlRequest htCrawlerGerUploadUrlRequest, HttpHeaders headers) {
-        return requestComponent.objectPost(RequestUrl.GET_UPLOAD_URL.getRequestUrl(huaTaiCrawlerProperties.getBaseUrl()), htCrawlerGerUploadUrlRequest, HtCrawlerGerUploadUrlResponse.class, headers).getBody();
+        return requestComponent.objectPostWithProxy(RequestUrl.GET_UPLOAD_URL.getRequestUrl(huaTaiCrawlerProperties.getBaseUrl()), htCrawlerGerUploadUrlRequest, HtCrawlerGerUploadUrlResponse.class, headers, proxyHostName, proxyPort).getBody();
     }
 
     /**
-     * 上传影像
+     * 上传影像  放到src/main/java/com/jzg/quotation/huatai/crawler/util/UploadUtil.java类中了
      * @param htCrawlerUploadUrlRequest
      * @return
      */
     public String uploadImage(HtCrawlerUploadUrlRequest htCrawlerUploadUrlRequest) {
-        return requestComponent.objectPost(RequestUrl.UPLOAD.getRequestUrl(huaTaiCrawlerProperties.getImgUrl()), htCrawlerUploadUrlRequest, String.class, null).getBody();
+        return requestComponent.objectPostWithProxy(RequestUrl.UPLOAD.getRequestUrl(huaTaiCrawlerProperties.getImgUrl()), htCrawlerUploadUrlRequest, String.class, null,proxyHostName, proxyPort).getBody();
     }
 
     /**
@@ -254,7 +216,17 @@ public class HtCrawlerRequestComponent {
      * @return
      */
     public HtCrawlerSubmitResponse submit(HtCrawlerSubmitRequest htCrawlerSubmitRequest, HttpHeaders headers) {
-        return requestComponent.objectPost(RequestUrl.SUBMIT.getRequestUrl(huaTaiCrawlerProperties.getBaseUrl()), htCrawlerSubmitRequest, HtCrawlerSubmitResponse.class, headers).getBody();
+        return requestComponent.objectPostWithProxy(RequestUrl.SUBMIT.getRequestUrl(huaTaiCrawlerProperties.getBaseUrl()), htCrawlerSubmitRequest, HtCrawlerSubmitResponse.class, headers, proxyHostName, proxyPort).getBody();
+    }
+
+    /**
+     * 提交核保 用这个  返回的错误参数 多变 用String 转Map接收了
+     * @param htCrawlerSubmitRequest
+     * @param headers
+     * @return
+     */
+    public String submit2(HtCrawlerSubmitRequest htCrawlerSubmitRequest, HttpHeaders headers) {
+        return requestComponent.objectPostWithProxy(RequestUrl.SUBMIT.getRequestUrl(huaTaiCrawlerProperties.getBaseUrl()), htCrawlerSubmitRequest, String.class, headers, proxyHostName, proxyPort).getBody();
     }
 
     /**
@@ -264,7 +236,7 @@ public class HtCrawlerRequestComponent {
      * @return
      */
     public HtCrawlerDownloadPolicyResponse downloadPolicy(HtCrawlerDownloadPolicyRequest downloadPolicyRequest, HttpHeaders headers) {
-        return requestComponent.objectPost(RequestUrl.DOWNLOAD_POLICY.getRequestUrl(huaTaiCrawlerProperties.getBaseUrl()), downloadPolicyRequest, HtCrawlerDownloadPolicyResponse.class, headers ).getBody();
+        return requestComponent.objectPostWithProxy(RequestUrl.DOWNLOAD_POLICY.getRequestUrl(huaTaiCrawlerProperties.getBaseUrl()), downloadPolicyRequest, HtCrawlerDownloadPolicyResponse.class, headers, proxyHostName, proxyPort).getBody();
     }
 
     /**
@@ -274,7 +246,7 @@ public class HtCrawlerRequestComponent {
      * @return
      */
     public String queryOrderStatus(HtCrawlerOrderStateRequest htCrawlerOrderStateRequest, HttpHeaders headers) {
-        return requestComponent.objectPost(RequestUrl.ORDER_STATE.getRequestUrl(huaTaiCrawlerProperties.getBaseUrl()), htCrawlerOrderStateRequest, String.class, headers ).getBody();
+        return requestComponent.objectPostWithProxy(RequestUrl.ORDER_STATE.getRequestUrl(huaTaiCrawlerProperties.getBaseUrl()), htCrawlerOrderStateRequest, String.class, headers,proxyHostName, proxyPort).getBody();
     }
 
     /**
@@ -284,6 +256,6 @@ public class HtCrawlerRequestComponent {
      * @return
      */
     public HtCrawlerPaymentLinkResponse getPaymentLink(HtCrawlerPaymentLinkRequest paymentLinkRequest, HttpHeaders headers) {
-        return requestComponent.objectPost(RequestUrl.PAYMENT_LINK.getRequestUrl(huaTaiCrawlerProperties.getBaseUrl()), paymentLinkRequest, HtCrawlerPaymentLinkResponse.class, headers ).getBody();
+        return requestComponent.objectPostWithProxy(RequestUrl.PAYMENT_LINK.getRequestUrl(huaTaiCrawlerProperties.getBaseUrl()), paymentLinkRequest, HtCrawlerPaymentLinkResponse.class, headers, proxyHostName, proxyPort).getBody();
     }
 }

+ 52 - 1
tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/component/HuaTaiCrawlerCacheComponent.java

@@ -19,19 +19,70 @@ public class HuaTaiCrawlerCacheComponent {
 
     public static final String HUATAI_COOKIE = "huatai:cookie:";
 
+    public static final String HUATAI_GSINFO = "huatai:gsinfo:";
+
+    public static final String HUATAI_COMCODE = "huatai:comcode:";
+
+    public static final String HUATAI_YINGXIANG_UPLOADED = "huatai:yx:";
+
     public static final String COOKIE = "Cookie:";
 
+    public static final String GSINFO = "gsInfo:";
+
+    public static final String COMCODE = "comCode:";
+
+    public static final String YINGXIANG_UPLOADED = "yx:";
+
     public void cacheCookie(String cookie) {
         Map<String, String> authorizationMap = new HashMap<>();
 
         authorizationMap.put(COOKIE, cookie);
         RMap<Object, Object> map = redissonClient.getMap(HUATAI_COOKIE);
         map.putAll(authorizationMap);
-        map.expire(Duration.ofHours(3L));
+        map.expire(Duration.ofHours(2L));
+    }
+
+    public void cacheGsInfo(String gsinfo) {
+        Map<String, String> authorizationMap = new HashMap<>();
+
+        authorizationMap.put(GSINFO, gsinfo);
+        RMap<Object, Object> map = redissonClient.getMap(HUATAI_GSINFO);
+        map.putAll(authorizationMap);
+        map.expire(Duration.ofHours(2L));
+    }
+
+    public void cacheComCode(String comcode) {
+        Map<String, String> authorizationMap = new HashMap<>();
+
+        authorizationMap.put(COMCODE, comcode);
+        RMap<Object, Object> map = redissonClient.getMap(HUATAI_COMCODE);
+        map.putAll(authorizationMap);
+        map.expire(Duration.ofHours(2L));
+    }
+
+    public void cacheYingXiangUploaded(String yx) {
+        Map<String, String> authorizationMap = new HashMap<>();
+
+        authorizationMap.put(YINGXIANG_UPLOADED, yx);
+        RMap<Object, Object> map = redissonClient.getMap(HUATAI_YINGXIANG_UPLOADED);
+        map.putAll(authorizationMap);
+        map.expire(Duration.ofHours(2L));
     }
 
     public String getCookie() {
         return (String) redissonClient.getMap(HUATAI_COOKIE).get(COOKIE);
     }
 
+    public String getGsInfo() {
+        return (String) redissonClient.getMap(HUATAI_GSINFO).get(GSINFO);
+    }
+
+    public String getComCode() {
+        return (String) redissonClient.getMap(HUATAI_COMCODE).get(COMCODE);
+    }
+
+    public String getYingXiangUploaded() {
+        return (String) redissonClient.getMap(HUATAI_YINGXIANG_UPLOADED).get(YINGXIANG_UPLOADED);
+    }
+
 }

+ 23 - 12
tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/constant/enums/RequestUrl.java

@@ -14,36 +14,47 @@ import lombok.Getter;
 public enum RequestUrl implements CrawlerRequestUrlStandard {
 
     NE_COOKIE("/htcsp", "获取cookie"),
-    COOKIE("http://172.16.100.37:9999/htcsp", "获取cookie"),
+    COOKIE("https://cspxp.pc.ehuatai.com/htcsp", "获取cookie"),
+
 
     NE_SESSION_KEEP("sessionKeep", "session连接"),
 
-    SESSION_KEEP("http://172.16.100.37:9999/htcsp/ShakeHandsAction.do?cmd=contentInit", "session连接"),
+    SESSION_KEEP("https://cspxp.pc.ehuatai.com/htcsp/ShakeHandsAction.do?cmd=contentInit", "session连接"),
+
+    GET_COM_CODE("/htcsp/ShakeHandsAction.do?cmd=getBranch", "获取保司代码"),
 
     NE_AUTHENTICATE("/login", "登录"),
 
-    AUTHENTICATE("http://172.16.100.37:9999/htcsp/ShakeHandsAction.do?cmd=loginWelcom", "登录"),
+    AUTHENTICATE("/htcsp/ShakeHandsAction.do?cmd=loginWelcom", "登录"),
+
+    STARTPROCESS("/htcsp/ShakeHandsAction.do?cmd=startProcess", "流程开始"),
+
+    MENUCONTROL("/htcsp/ShakeHandsAction.do?cmd=menuControl", "菜单控制"),
+
+    XBQUERY("https://cspxp.pc.ehuatai.com/cmd=xbquery", "xbquery"),
 
     NE_CAR_QUERY("/carquery", "车型查询"),
 
-    CAR_QUERY("http://172.16.100.37:9999/htcsp/VehicleInfoEntryAction.do?cmd=carquery", "车型查询"),
+    CAR_QUERY("/htcsp/VehicleInfoEntryAction.do?cmd=carquery", "车型查询"),
 
     NE_SAVE_ONE_STEP("/saveOneStept", "保存车辆信息和车主等信息"),
-    SAVE_ONE_STEP("http://172.16.100.37:9999/htcsp/VehicleInfoEntryAction.do?cmd=saveOneStept", "保存车辆信息和车主等信息"),
+    SAVE_ONE_STEP("/htcsp/VehicleInfoEntryAction.do?cmd=saveOneStept", "保存车辆信息和车主等信息"),
 
     NE_QUOTE_PRICE("/quotation", "报价"),
-    QUOTE_PRICE("http://172.16.100.37:9999/htcsp/VehicleInfoEntryAction.do?cmd=carquery", "报价"),
+    QUOTE_PRICE("/htcsp/QuotedPriceAction.do?cmd=quotedPrice", "报价"),
+
+    GET_UPLOAD_URL("/htcsp/UploadAction.do?cmd=getUploadUrl", "获取影像上传路径"),
+    UPLOAD("/app/ImgFileUpload/upload.do", "影像上传"),
 
-    GET_UPLOAD_URL("http://172.16.100.37:9999/htcsp/UploadAction.do?cmd=getUploadUrl", "获取影像上传路径"),
-    UPLOAD("http://172.16.100.37:9999/app/ImgFileUpload/upload.do", "影像上传"),
+    SUBMIT("/htcsp/checkInsAction.do?cmd=submit4ajax&SS=SS", "提交核保"),
 
-    SUBMIT("http://172.16.100.37:9999/htcsp/checkInsAction.do?cmd=submit4ajax&SS=SS", "提交核保"),
+    SUBMIT_ZRG("/htcsp/checkInsAction.do?cmd=submitZRG", "核保转人工"),
 
-    ORDER_STATE("http://172.16.100.37:9999/htcsp/QuotationQueryAction.do?cmd=quotationListAll", "查询订单状态"),
+    ORDER_STATE("/htcsp/QuotationQueryAction.do?cmd=quotationListAll", "查询订单状态"),
 
-    PAYMENT_LINK("http://172.16.100.37:9999/htcsp/PaymentAction.do?cmd=Sendelectronicprop", "获取支付链接"),
+    PAYMENT_LINK("/htcsp/PaymentAction.do?cmd=Sendelectronicprop", "获取支付链接"),
 
-    DOWNLOAD_POLICY("http://172.16.100.37:9999/htcsp/DocumentPrintAction.do?cmd=electronicPolicyEndorseDownload", "下载保单"),
+    DOWNLOAD_POLICY("/htcsp/DocumentPrintAction.do?cmd=electronicPolicyEndorseDownload", "下载保单"),
     ;
 
     private final String url;

+ 2 - 0
tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/entity/HtCrawlerConfigureParameters.java

@@ -20,4 +20,6 @@ public class HtCrawlerConfigureParameters implements ConfigureParameters {
      */
     private String comCode;
 
+    private String fullComCode;
+
 }

+ 48 - 6
tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/entity/Request/HtCrawlerCarQueryRequest.java

@@ -22,14 +22,50 @@ public class HtCrawlerCarQueryRequest implements Serializable {
     @Serial
     private static final long serialVersionUID = 3366912683677575492L;
 
-    public HtCrawlerCarQueryRequest(CarInfoVo carInfoVo) {
+    public HtCrawlerCarQueryRequest(CarInfoVo carInfoVo, String modelcodexh) {
         DataDTO dataDTO = new DataDTO();
-        dataDTO.setMotortypecode(carInfoVo.getCarKindCode());
-        dataDTO.setMotorusagetypecode(carInfoVo.getCarNatureCode());
+        dataDTO.setVehicleModel(carInfoVo.getBrandName());
+        // 车辆类型自动判断
+        if ("04".equals(carInfoVo.getVehicleUseCode())) {
+            dataDTO.setMotortypecode("H0");
+            dataDTO.setMotorusagetypecode("9D");
+        } else if ("05".equals(carInfoVo.getVehicleUseCode())) {
+            dataDTO.setMotortypecode("A0 客车");
+            dataDTO.setMotorusagetypecode("8A 家庭自用");
+        } else if ("06".equals(carInfoVo.getVehicleUseCode())) {
+            if ("A0".equals(carInfoVo.getCarKindCode())) {
+                dataDTO.setMotortypecode("A0");
+                dataDTO.setMotorusagetypecode("8C");
+            } else if ("A1".equals(carInfoVo.getCarKindCode())) {
+                dataDTO.setMotortypecode("H0");
+                dataDTO.setMotorusagetypecode("8D");
+            }
+        } else if ("07".equals(carInfoVo.getVehicleUseCode())) {
+            if ("A0".equals(carInfoVo.getCarKindCode())) {
+                dataDTO.setMotortypecode("A0");
+                dataDTO.setMotorusagetypecode("8B");
+            } else if ("A1".equals(carInfoVo.getCarKindCode())) {
+                dataDTO.setMotortypecode("H0");
+                dataDTO.setMotorusagetypecode("8D");
+            }
+        } else if ("08".equals(carInfoVo.getVehicleUseCode())) {
+            dataDTO.setMotortypecode("H0");
+            dataDTO.setMotorusagetypecode("8D");
+        }
+        //dataDTO.setMotortypecode(carInfoVo.getCarKindCode());
+        //dataDTO.setMotorusagetypecode("8A");//carInfoVo.getCarNatureCode()
+        dataDTO.setEACSP_MODEL_CODE_QUERY_new(System.currentTimeMillis()+"");
+        dataDTO.setEACSP_MODEL_CODE_QUERY_old("");
+        dataDTO.setPageno("1");
+        dataDTO.setRowsperpage("50");
+        dataDTO.setReformRisk("1251");
+        dataDTO.setVin(carInfoVo.getVinNo());
         dataDTO.setLicenseplateno(carInfoVo.getLicenseNo());
         dataDTO.setEngineno(carInfoVo.getEngineNo());
-        dataDTO.setVin(carInfoVo.getVinNo());
-
+        dataDTO.setVehicleregisterdate(carInfoVo.getRegisterDate());
+        dataDTO.setFueltype("");
+        dataDTO.setPurerange("");
+        dataDTO.setModelcodexh(modelcodexh);
         String data = JSON.toJSONString(dataDTO);
         String key = HuaTaiCryptUtil.generateKey(16);
         try {
@@ -91,6 +127,12 @@ public class HtCrawlerCarQueryRequest implements Serializable {
         private String engineno;
         @JsonProperty("vin")
         private String vin;
+        @JsonProperty("fueltype")
+        private String fueltype;
+        @JsonProperty("purerange")
+        private String purerange;
+        @JsonProperty("vehicleregisterdate")
+        private String vehicleregisterdate;
         @JsonProperty("pageno")
         private String pageno = "1";
         @JsonProperty("rowsperpage")
@@ -102,7 +144,7 @@ public class HtCrawlerCarQueryRequest implements Serializable {
         @JsonProperty("checkno")
         private String checkno;
         @JsonProperty("modelflag")
-        private String modelflag = "1";
+        private String modelflag;
         @JsonProperty("checkcode")
         private String checkcode;
         @JsonProperty("gdjgvehiclecheckflag")

+ 1 - 1
tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/entity/Request/HtCrawlerGerUploadUrlRequest.java

@@ -20,7 +20,7 @@ public class HtCrawlerGerUploadUrlRequest implements Serializable {
      * 有UP_carcheck和UP_doubleRecord
      * 暂时默认UP_carcheck
      */
-    private String uploadType = "UP_carcheck";
+    private String uploadType = "UP_carcheck_self";
     private String quotationNo;
     private String isVpn;
 

+ 9 - 9
tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/entity/Request/HtCrawlerLoginRequest.java

@@ -28,29 +28,29 @@ public class HtCrawlerLoginRequest implements Serializable {
     @JsonProperty("comcode")
     private String comcode;
     @JsonProperty("verificationCode")
-    private String verificationCode;
+    private String verificationCode = "";
     @JsonProperty("yanzhengtupianflag")
-    private String yanzhengtupianflag;
+    private String yanzhengtupianflag = "";
     @JsonProperty("brownVerb")
-    private String brownVerb = "122.0.0.0";
+    private String brownVerb = "143.0.0.0";
     @JsonProperty("brownVern")
     private String brownVern = "Chrome";
     @JsonProperty("bindflag")
-    private String bindflag;
+    private String bindflag = "";
     @JsonProperty("customerIp")
     private String customerIp = "127.0.0.1";
     @JsonProperty("customerCity")
     private String customerCity = "未知";
     @JsonProperty("userIsNowFlag")
-    private String userIsNowFlag;
+    private String userIsNowFlag = "";
     @JsonProperty("sendNecessityIpt")
     private String sendNecessityIpt = "X";
     @JsonProperty("wwaUserCode")
-    private String wwaUserCode;
+    private String wwaUserCode = "";
     @JsonProperty("weChatFlag")
-    private String weChatFlag;
-    @JsonProperty("isVpn")
-    private String isVpn = "1";
+    private String weChatFlag = "";
+    //@JsonProperty("isVpn")
+    //private String isVpn = "1";
     @JsonProperty("validStatus")
     private String validStatus = "1";
 }

+ 145 - 3
tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/entity/Request/HtCrawlerPaymentLinkRequest.java

@@ -1,5 +1,6 @@
 package com.jzg.quotation.huatai.crawler.entity.Request;
 
+import com.fasterxml.jackson.annotation.JsonProperty;
 import com.jzg.commons.entity.quote.vo.aggregated.PaymentLinkVo;
 import com.jzg.quotation.huatai.crawler.entity.HtCrawlerConfigureParameters;
 import lombok.Data;
@@ -7,6 +8,10 @@ import lombok.NoArgsConstructor;
 
 import java.io.Serial;
 import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * @description: 华泰财险 爬虫获取支付链接 请求参数
@@ -19,36 +24,173 @@ public class HtCrawlerPaymentLinkRequest implements Serializable {
     @Serial
     private static final long serialVersionUID = 756412555027857067L;
 
-    public HtCrawlerPaymentLinkRequest(HtCrawlerConfigureParameters parameters, PaymentLinkVo paymentLinkVo) {
+    public HtCrawlerPaymentLinkRequest(HtCrawlerConfigureParameters parameters, PaymentLinkVo paymentLinkVo, String queryPaymentListResponse) {
         this.comcode = parameters.getComCode();
         this.logincomcode = parameters.getComCode();
-        this.proposalno = "";//需设置投保单号
+        this.poatype = "";
+        this.paytype = "";
+        this.noTotalType = "";
+        this.realname = "1";
+        this.poasource = "";
+        this.totalAmount = "";
+        this.riskCode = "";
+        this.quotationno = "";
+        this.inquiryno = "";
+        List<String> proposalNoList = extractAttributeValues(queryPaymentListResponse, "value=\"(.*?)\" quotationno=");
+        int count = proposalNoList.size();
+
+        if (count == 1) {
+            this.certitype = "#,";
+            this.quotationno = "#,";
+            this.inquiryno = "#,";
+        } else if (count == 2) {
+            this.certitype = "#,#,";
+            this.quotationno = "#,#,";
+            this.inquiryno = "#,#,";
+        } else if (count == 3) {
+            this.certitype = "#,#,#,";
+            this.quotationno = "#,#,#,";
+            this.inquiryno = "#,#,#,";
+        } else {
+            this.certitype = "";
+            this.quotationno = "";
+            this.inquiryno = "";
+        }
+
+        this.proposalno = joinWithComma(proposalNoList) + ",";
+        this.systemFlag = joinWithComma(extractAttributeValues(queryPaymentListResponse, "systemFlag")) + ",";
+        this.insuredname = joinWithComma(extractAttributeValues(queryPaymentListResponse, "insuredname")) + ",";
+        this.certicode = joinWithComma(extractAttributeValues(queryPaymentListResponse, "certicode")) + ",";
+        this.createtime = joinWithComma(extractAttributeValues(queryPaymentListResponse, "createtime")) + ",";
+        this.comcode = joinWithComma(extractAttributeValues(queryPaymentListResponse, "comcode")) + ",";
+        this.quoteamount = joinWithComma(extractAttributeValues(queryPaymentListResponse, "quoteamount")) + ",";
+        this.assuredname = joinWithComma(extractAttributeValues(queryPaymentListResponse, "assuredname")) + ",";
+        this.ownertype = joinWithComma(extractAttributeValues(queryPaymentListResponse, "ownertype")) + ",";
+        this.licenseplateno = joinWithComma(extractAttributeValues(queryPaymentListResponse, "licenseplateno")) + ",";
+        this.status = joinWithComma(extractAttributeValues(queryPaymentListResponse, "status")) + ",";
+        if (this.status .contains(",,")) {
+            this.status = this.status.replace(",,", ",");
+        }
+        this.startdate = joinWithComma(extractAttributeValues(queryPaymentListResponse, "startdate")) + ",";
+        this.lastpaydate = joinWithComma(extractAttributeValues(queryPaymentListResponse, "lastpaydate")) + ",";
+        this.single_system = joinWithComma(extractAttributeValues(queryPaymentListResponse, "single_system")) + ",";
+        this.insuredidentifytype = joinWithComma(extractAttributeValues(queryPaymentListResponse, "insuredidentifytype")) + ",";
+
+        List<String> allowdiscountflagList = extractAttributeValues(queryPaymentListResponse, "allowdiscountflag");
+        for (int i = 0; i < allowdiscountflagList.size(); i++) {
+            if (allowdiscountflagList.get(i) == null || allowdiscountflagList.get(i).isEmpty()) {
+                allowdiscountflagList.set(i, "#");
+            }
+        }
+        this.allowdiscountflag = joinWithComma(allowdiscountflagList) + ",";
+    }
+
+    private List<String> extractAttributeValues(String html, String attributeName) {
+        List<String> values = new ArrayList<>();
+        if (html == null || html.isEmpty() || attributeName == null || attributeName.isEmpty()) {
+            return values;
+        }
+        String regex = "";
+        if (attributeName.contains("quotationno")) {
+            regex = attributeName;
+        } else {
+            regex = attributeName + "=\"(.*?)\"";
+        }
+        Pattern pattern = Pattern.compile(regex);
+        Matcher matcher = pattern.matcher(html);
+
+        while (matcher.find()) {
+            values.add(matcher.group(1));
+        }
+
+        return values;
+    }
+
+    private String joinWithComma(List<String> list) {
+        if (list == null || list.isEmpty()) {
+            return "";
+        }
+        return String.join(",", list);
     }
 
+    @JsonProperty("poatype")
     private String poatype;
+
+    @JsonProperty("proposalno")
     private String proposalno;
+
+    @JsonProperty("systemFlag")
     private String systemFlag;
+
+    @JsonProperty("insuredname")
     private String insuredname;
+
+    @JsonProperty("certitype")
     private String certitype;
+
+    @JsonProperty("certicode")
     private String certicode;
+
+    @JsonProperty("createtime")
     private String createtime;
+
+    @JsonProperty("comcode")
     private String comcode;
+
+    @JsonProperty("quoteamount")
     private String quoteamount;
+
+    @JsonProperty("assuredname")
     private String assuredname;
+
+    @JsonProperty("ownertype")
+    private String ownertype;
+
+    @JsonProperty("licenseplateno")
     private String licenseplateno;
+
+    @JsonProperty("status")
     private String status;
+
+    @JsonProperty("startdate")
     private String startdate;
+
+    @JsonProperty("paytype")
     private String paytype;
+
+    @JsonProperty("lastpaydate")
     private String lastpaydate;
+
+    @JsonProperty("single_system")
     private String single_system;
+
+    @JsonProperty("logincomcode")
     private String logincomcode;
+
+    @JsonProperty("noTotalType")
     private String noTotalType;
-    private String realname;
+
+    @JsonProperty("realname")
+    private String realname = "1";
+
+    @JsonProperty("poasource")
     private String poasource;
+
+    @JsonProperty("quotationno")
     private String quotationno;
+
+    @JsonProperty("inquiryno")
     private String inquiryno;
+
+    @JsonProperty("allowdiscountflag")
     private String allowdiscountflag;
+
+    @JsonProperty("totalAmount")
     private String totalAmount;
+
+    @JsonProperty("insuredidentifytype")
     private String insuredidentifytype;
+
+    @JsonProperty("riskCode")
     private String riskCode;
 }

+ 246 - 47
tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/entity/Request/HtCrawlerQuoteRequest.java

@@ -1,20 +1,29 @@
 package com.jzg.quotation.huatai.crawler.entity.Request;
 
+import cn.hutool.core.collection.CollectionUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.jzg.commons.constants.InsuranceRisk;
 import com.jzg.commons.entity.quote.vo.KindInfoVo;
 import com.jzg.commons.entity.quote.vo.RiskInfoVo;
 import com.jzg.commons.entity.quote.vo.VehicleAndVesselTaxVo;
 import com.jzg.commons.exception.SystemException;
 import com.jzg.commons.entity.quote.vo.QuoteVo;
+import com.jzg.commons.util.StringUtils;
+import com.jzg.quotation.commons.constant.InsuranceTypeCorrespondence;
 import com.jzg.quotation.huatai.crawler.util.HuaTaiCryptUtil;
 import lombok.Data;
 
 import java.io.Serial;
 import java.io.Serializable;
 import java.util.ArrayList;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * @description: 华泰财险 报价 请求参数
@@ -26,10 +35,14 @@ public class HtCrawlerQuoteRequest implements Serializable {
     @Serial
     private static final long serialVersionUID = -3648463870224027622L;
 
-    public HtCrawlerQuoteRequest(QuoteVo quoteVo) {
-        DataDTO dataDTO = new DataDTO(quoteVo);
+    public HtCrawlerQuoteRequest(QuoteVo quoteVo, String mealid, String basePartJSON) {
+        DataDTO dataDTO = new DataDTO(quoteVo, mealid, basePartJSON);
+        ObjectMapper objectMapper = new ObjectMapper();
+        Map<String, Object> dataMap = objectMapper.convertValue(dataDTO, new TypeReference<Map<String, Object>>() {});
 
-        String data = JSON.toJSONString(dataDTO);
+        String data = JSON.toJSONString(dataMap, SerializerFeature.WriteMapNullValue);
+        data = data.replace("\\\"","'");
+        System.out.println("HtCrawlerQuoteRequest::"+data);
         String key = HuaTaiCryptUtil.generateKey(16);
         try {
             String accessToken = HuaTaiCryptUtil.RSAEncrypt(key);
@@ -41,17 +54,21 @@ public class HtCrawlerQuoteRequest implements Serializable {
         }
     }
 
+    @JsonProperty("sourceCode")
     private String sourceCode = "8";
+    @JsonProperty("accessToken")
     private String accessToken;
+    @JsonProperty("data")
     private String data;
-    private String insuredCode;
+    @JsonProperty("insuredCode")
+    private String insuredCode = "";
 
     @Data
     public static class DataDTO implements Serializable {
         @Serial
         private static final long serialVersionUID = 3131283514749202563L;
 
-        public DataDTO(QuoteVo quoteVo) {
+        public DataDTO(QuoteVo quoteVo, String mealid, String basePartJSON) {
             RiskInfoVo ciRiskInfoVo = quoteVo.getCiRiskInfoVo();
             RiskInfoVo biRiskInfoVo = quoteVo.getBiRiskInfoVo();
             VehicleAndVesselTaxVo taxVo = quoteVo.getVehicleAndVesselTaxVo();
@@ -67,12 +84,14 @@ public class HtCrawlerQuoteRequest implements Serializable {
             } else {
                 this.isInsureBusi = false;
             }
+            this.afloatValue = "";
             this.hastax = this.isInsureTraffic;
-            this.mealid = "00000";
+            this.mealid = StringUtils.isBlank(mealid) ? "" : mealid;
             List<CovListDTO> covListDTOS = getCovListDTOS(quoteVo);
-            this.covListJSON = JSONObject.toJSONString(covListDTOS);
-            this.coveragecode = biRiskInfoVo.getRiskCode();
-            this.taxJSON = JSONObject.toJSONString(getTaxDTO(taxVo));
+            this.covListJSON = JSON.toJSONString(covListDTOS);
+            //this.covListJSON = "[{'comcoveragecode':'B','limitamount':'2000000','insteadwalkdailylimitamount':'2000000','coverageclasscode':'1','startdate':'2026-06-26 00:00:00','enddate':'2027-06-25 23:59:59','coveragecode':'1251','isdedu':'1','independentvalue':'','comcoveragename':'机动车第三者责任保险','deductible':'','basedpremium':'','benchmarkpremium':'','kindpremiun':'','deductiblerate':'','billdate':'2026-06-26 00:00:00','serviceTimes':'','serviceCode':''},{'comcoveragecode':'D11','limitamount':'20000','insteadwalkdailylimitamount':'20000','coverageclasscode':'1','startdate':'2026-06-26 00:00:00','enddate':'2027-06-25 23:59:59','coveragecode':'1251','isdedu':'1','independentvalue':'','comcoveragename':'机动车车上人员责任险(司机)','deductible':'','basedpremium':'','benchmarkpremium':'','kindpremiun':'','deductiblerate':'','billdate':'2026-06-26 00:00:00','serviceTimes':'','serviceCode':''},{'comcoveragecode':'D12','limitamount':'20000','insteadwalkdailylimitamount':'20000','coverageclasscode':'1','startdate':'2026-06-26 00:00:00','enddate':'2027-06-25 23:59:59','coveragecode':'1251','isdedu':'1','independentvalue':'','comcoveragename':'机动车车上人员责任险(乘客)','deductible':'','basedpremium':'','benchmarkpremium':'','kindpremiun':'','deductiblerate':'','billdate':'2026-06-26 00:00:00','serviceTimes':'','serviceCode':''},{'comcoveragecode':'BZ','coveragecode':'1002','startdate':'2026-06-26 00:00:00','enddate':'2027-06-25 23:59:59','comcoveragename':'机动车交通事故责任强制保险','billdate':'2026-06-26 00:00:00','limitamount':'200000'}]";
+            this.coveragecode = "1251";
+            this.taxJSON = JSON.toJSONString(getTaxDTO(taxVo));
             this.taxnumbercode = "";
             this.taxdepartment = "";
             this.deductionduecode = "M1";
@@ -81,12 +100,71 @@ public class HtCrawlerQuoteRequest implements Serializable {
             this.taxRateOrPay = "";
             this.taxdealmode = "1";
             this.taxdepartmentcode_wanshui = "";
-            this.profitJSON = "";//费率因子集合,待补充
+            // 构建 profitJSON - 费率因子集合
+            List<Map<String, String>> profitList = new ArrayList<>();
+
+            Map<String, String> profit1 = new LinkedHashMap<>();
+            profit1.put("itemkindno", "");
+            profit1.put("profitcode", "C22");
+            profit1.put("conditioncode", "空");
+            profit1.put("profitrate", "100.0");
+            profit1.put("profittype", "");
+            profit1.put("valueid", "REF");
+            profit1.put("min", "100.0");
+            profit1.put("max", "100.0");
+            profit1.put("lowerprofitrate", "100.0");
+            profit1.put("upperprofitrate", "100.0");
+            profitList.add(profit1);
+
+            Map<String, String> profit2 = new LinkedHashMap<>();
+            profit2.put("itemkindno", "");
+            profit2.put("profitcode", "C17");
+            profit2.put("conditioncode", "");
+            profit2.put("profitrate", "");
+            profit2.put("profittype", "");
+            profit2.put("valueid", "");
+            profit2.put("min", "");
+            profit2.put("max", "");
+            profit2.put("lowerprofitrate", "");
+            profit2.put("upperprofitrate", "");
+            profitList.add(profit2);
+
+            Map<String, String> profit3 = new LinkedHashMap<>();
+            profit3.put("itemkindno", "");
+            profit3.put("profitcode", "C29");
+            profit3.put("conditioncode", "");
+            profit3.put("profitrate", "65.0");
+            profit3.put("profittype", "");
+            profit3.put("valueid", "2");
+            profit3.put("min", "65.0");
+            profit3.put("max", "135.0");
+            profit3.put("lowerprofitrate", "65.0");
+            profit3.put("upperprofitrate", "135.0");
+            profitList.add(profit3);
+            this.profitJSON = JSON.toJSONString(profitList);
+            // 构建 szTeamcarReportJSON
+            Map<String, String> szTeamcarReportMap = new LinkedHashMap<>();
+            szTeamcarReportMap.put("isSZteamcarReportFlag", "");
+            szTeamcarReportMap.put("i_iscarowner", "N");
+            szTeamcarReportMap.put("ins_type", "undefined");
+            szTeamcarReportMap.put("certi_type", "");
+            szTeamcarReportMap.put("certi_code", "");
+            szTeamcarReportMap.put("insured_name", "");
+            szTeamcarReportMap.put("age", "");
+            szTeamcarReportMap.put("teamcarno_sz", "");
+            szTeamcarReportMap.put("salesidcardoth", "");
+            szTeamcarReportMap.put("salesnameoth", "");
+            szTeamcarReportMap.put("transactoridentifytype", "");
+            szTeamcarReportMap.put("transactoridentifycode", "");
+            szTeamcarReportMap.put("transactor_nam", "");
+            szTeamcarReportMap.put("certiStartDate", "");
+            szTeamcarReportMap.put("certiEndDate", "");
+            this.szTeamcarReportJSON = JSON.toJSONString(szTeamcarReportMap);
             this.renewalpolicyno = "";
             this.SYxinxi = "0";
             this.PiLing = "0";
             this.pilingFlag = "2";
-            this.personalInsuredJSON = JSONObject.toJSONString(getPersonalInsuredDTOs(quoteVo));
+            this.personalInsuredJSON = "";
             this.relationno_bi = "";
             this.promotesaleplanid = "";
             this.disfeeregmaxbi = "";
@@ -94,17 +172,26 @@ public class HtCrawlerQuoteRequest implements Serializable {
             this.teamcaridentificationID = "0";
             this.devListJSON = "";
             this.isgetlastpolicy = "";
-            this.szTeamcarReportJSON = "";
             this.taxdocumentdate = "";
             this.taxpaidareacode = "";
             this.displacement = "";
-            this.recommendList = "";
+            this.recommendList = null;
             this.pilingRecommendNo = "";
-            this.specialcarflag = "";
-            this.transferdate = "";
+            this.specialcarflag = quoteVo.getCarInfoVo().isTransfer() ? "1" : "";
+            this.transferdate = quoteVo.getCarInfoVo().getTransferDate() == null ? "" : quoteVo.getCarInfoVo().getTransferDate().toString();
             this.riskcode = this.coveragecode;
             this.chgownerRisk = "";
             this.quoIsLastPlanRecommendNo = "";
+            if(StringUtils.isBlank(basePartJSON)) {
+                if("0330".equals(quoteVo.getOrder().getProductId())) {
+                    this.basePartJSON = "[{'riskfalg':'0'}]";
+                } else {
+                    this.basePartJSON = "[{'riskfalg':'0'},{'riskfalg':'1'}]";
+                }
+            }else {
+                this.basePartJSON = basePartJSON;
+            }
+            this.questioninfolast = "{}";
         }
 
         /**
@@ -121,29 +208,42 @@ public class HtCrawlerQuoteRequest implements Serializable {
             RiskInfoVo biRiskInfoVo = quoteVo.getBiRiskInfoVo();
             //交强险信息
             RiskInfoVo ciRiskInfoVo = quoteVo.getCiRiskInfoVo();
-            kindInfoVoList.forEach(kindInfoVo -> {
-                CovListDTO covListDTO = new CovListDTO();
-                covListDTO.setCoveragecode(biRiskInfoVo.getRiskCode());
-                covListDTO.setComcoveragecode(kindInfoVo.getKindCode());
-                covListDTO.setComcoveragename(kindInfoVo.getKindName());
-                covListDTO.setLimitamount(kindInfoVo.getAmount());
-                covListDTO.setInsteadwalkdailylimitamount(kindInfoVo.getAmount());
-                covListDTO.setCoverageclasscode("1");
-                covListDTO.setStartdate(biRiskInfoVo.getStartDate());
-                covListDTO.setEnddate(biRiskInfoVo.getEndDate());
-                covListDTO.setIsdedu("1");
-                covListDTO.setQuantity(kindInfoVo.getQuantity());
-                covListDTO.setServiceTimes(kindInfoVo.getServiceTimes());
-
-                covListDTOS.add(covListDTO);
-            });
+            if (CollectionUtil.isNotEmpty(kindInfoVoList)) {
+                kindInfoVoList.forEach(kindInfoVo -> {
+                    CovListDTO covListDTO = new CovListDTO();
+                    covListDTO.setBasedpremium("");
+                    covListDTO.setBenchmarkpremium("");
+                    covListDTO.setDeductible("");
+                    covListDTO.setDeductiblerate("");
+                    covListDTO.setIndependentvalue("");
+                    covListDTO.setCoveragecode("1251");
+                    covListDTO.setComcoveragecode(kindInfoVo.getKindCode());
+                    covListDTO.setComcoveragename(kindInfoVo.getKindName());
+                    covListDTO.setLimitamount(kindInfoVo.getAmount());
+                    covListDTO.setInsteadwalkdailylimitamount(kindInfoVo.getAmount());
+                    covListDTO.setCoverageclasscode("1");
+                    covListDTO.setStartdate(ciRiskInfoVo.getStartDate());
+                    covListDTO.setEnddate(ciRiskInfoVo.getEndDate());
+                    covListDTO.setIsdedu("1");
+                    covListDTO.setKindpremiun("");
+                    covListDTO.setQuantity(kindInfoVo.getQuantity());
+                    covListDTO.setServiceTimes("");
+                    covListDTO.setServiceCode("");
+                    covListDTO.setBilldate(ciRiskInfoVo.getStartDate());
+
+                    covListDTOS.add(covListDTO);
+                });
+            }
             //添加交强险
+            //"covListJSON": "[{'comcoveragecode':'BZ','coveragecode':'1002','startdate':'2026-05-21 00:00:00','enddate':'2027-05-20 23:59:59','comcoveragename':'机动车交通事故责任强制保险','billdate':'2026-05-21 00:00:00','limitamount':'200000'}]"
             CovListDTO covListDTO = new CovListDTO();
-            covListDTO.setCoveragecode(ciRiskInfoVo.getRiskCode());
-            covListDTO.setComcoveragecode(ciRiskInfoVo.getRiskCode());
+            covListDTO.setCoveragecode(InsuranceTypeCorrespondence.getHuaTaiRisk().get(ciRiskInfoVo.getRiskCode()));
+            covListDTO.setComcoveragecode(InsuranceTypeCorrespondence.getHuaTaiRisk().get(covListDTO.getCoveragecode()));
             covListDTO.setComcoveragename(InsuranceRisk.TRAFFIC.getDesc());
-            covListDTO.setStartdate(biRiskInfoVo.getStartDate());
-            covListDTO.setEnddate(biRiskInfoVo.getEndDate());
+            covListDTO.setLimitamount(InsuranceTypeCorrespondence.getHuaTaiRisk().get(covListDTO.getComcoveragecode()));
+            covListDTO.setStartdate(ciRiskInfoVo.getStartDate());
+            covListDTO.setEnddate(ciRiskInfoVo.getEndDate());
+            covListDTO.setBilldate(ciRiskInfoVo.getStartDate());
             covListDTOS.add(covListDTO);
             return covListDTOS;
         }
@@ -158,9 +258,21 @@ public class HtCrawlerQuoteRequest implements Serializable {
             TaxDTO taxDTO = new TaxDTO();
             taxDTO.setTaxpayercertitype(taxVo.getTaxpayerIdentifier());
             taxDTO.setTaxpayername(taxVo.getTaxpayerName());
+            taxDTO.setDeclaredate("");
+            taxDTO.setPaylastyear("");
+            taxDTO.setHispolicyenddate("");
             taxDTO.setTaxpayercerticode(taxVo.getIdentifyNumber());
+            taxDTO.setIsrefuse("");
+            taxDTO.setTaxconditioncode("1N");
             taxDTO.setTaxpayerindentificationcode(taxVo.getIdentifyNumber());
-            taxDTO.setTaxconditioncode(taxVo.getTaxRelifFlag());
+            taxDTO.setSametoowner("0");
+            int currentYear = java.time.LocalDate.now().getYear();
+            taxDTO.setTaxstartdate(currentYear + "-01-01");
+            taxDTO.setTaxenddate(currentYear + "-12-31");
+            taxDTO.setCalculatemode("");
+            taxDTO.setDepartment("");
+            taxDTO.setTaxreliefno("");
+            taxDTO.setTaxreliefspareno("");
             //其他数据调试再补充
             return taxDTO;
         }
@@ -189,49 +301,136 @@ public class HtCrawlerQuoteRequest implements Serializable {
 
             return personalInsuredDTOList;
         }
+        @JsonProperty("afloatValue")
+        private String afloatValue;
 
+        @JsonProperty("isFirstCount")
         private String isFirstCount;
+
+        @JsonProperty("isGlmPrice")
         private Integer isGlmPrice;
+
+        @JsonProperty("isInsureTraffic")
         private String isInsureTraffic;
+
+        @JsonProperty("isInsureBusi")
         private Boolean isInsureBusi;
+
+        @JsonProperty("hastax")
         private String hastax;
+
+        @JsonProperty("mealid")
         private String mealid;
+
+        @JsonProperty("covListJSON")
         private String covListJSON;
+
+        @JsonProperty("coveragecode")
         private String coveragecode;
+
+        @JsonProperty("basePartJSON")
         private String basePartJSON;
+
+        @JsonProperty("questioninfolast")
         private String questioninfolast;
+
+        @JsonProperty("taxJSON")
         private String taxJSON;
+
+        @JsonProperty("taxnumbercode")
         private String taxnumbercode;
+
+        @JsonProperty("taxdepartment")
         private String taxdepartment;
+
+        @JsonProperty("deductionduecode")
         private String deductionduecode;
+
+        @JsonProperty("deductionduetype")
         private String deductionduetype;
+
+        @JsonProperty("taxdepartmentcode")
         private String taxdepartmentcode;
+
+        @JsonProperty("taxRateOrPay")
         private String taxRateOrPay;
+
+        @JsonProperty("taxdealmode")
         private String taxdealmode;
+
+        @JsonProperty("taxdepartmentcode_wanshui")
         private String taxdepartmentcode_wanshui;
+
+        @JsonProperty("profitJSON")
         private String profitJSON;
+
+        @JsonProperty("renewalpolicyno")
         private String renewalpolicyno;
+
+        @JsonProperty("SYxinxi")
         private String SYxinxi;
+
+        @JsonProperty("PiLing")
         private String PiLing;
+
+        @JsonProperty("pilingFlag")
         private String pilingFlag;
+
+        @JsonProperty("personalInsuredJSON")
         private String personalInsuredJSON;
+
+        @JsonProperty("relationno_bi")
         private String relationno_bi;
+
+        @JsonProperty("promotesaleplanid")
         private String promotesaleplanid;
+
+        @JsonProperty("disfeeregmaxbi")
         private String disfeeregmaxbi;
+
+        @JsonProperty("disfeeregmaxci")
         private String disfeeregmaxci;
+
+        @JsonProperty("teamcaridentificationID")
         private String teamcaridentificationID;
+
+        @JsonProperty("devListJSON")
         private String devListJSON;
+
+        @JsonProperty("isgetlastpolicy")
         private String isgetlastpolicy;
+
+        @JsonProperty("szTeamcarReportJSON")
         private String szTeamcarReportJSON;
+
+        @JsonProperty("taxdocumentdate")
         private String taxdocumentdate;
+
+        @JsonProperty("taxpaidareacode")
         private String taxpaidareacode;
+
+        @JsonProperty("displacement")
         private String displacement;
-        private String recommendList;
+
+        @JsonProperty("recommendList")
+        private Object recommendList;
+
+        @JsonProperty("pilingRecommendNo")
         private String pilingRecommendNo;
+
+        @JsonProperty("specialcarflag")
         private String specialcarflag;
+
+        @JsonProperty("transferdate")
         private String transferdate;
+
+        @JsonProperty("riskcode")
         private String riskcode;
+
+        @JsonProperty("chgownerRisk")
         private String chgownerRisk;
+
+        @JsonProperty("quoIsLastPlanRecommendNo")
         private String quoIsLastPlanRecommendNo;
 
         @Data
@@ -296,16 +495,16 @@ public class HtCrawlerQuoteRequest implements Serializable {
             @Serial
             private static final long serialVersionUID = 4610853741420630808L;
 
-            private String itemkindno;
-            private String profitcode;
-            private String conditioncode;
-            private String profitrate;
-            private String profittype;
-            private String valueid;
-            private String min;
-            private String max;
-            private String lowerprofitrate;
-            private String upperprofitrate;
+            private String itemkindno = "";
+            private String profitcode = "C29";
+            private String conditioncode = "";
+            private String profitrate = "65.0";
+            private String profittype = "";
+            private String valueid = "2";
+            private String min = "65.0";
+            private String max = "135.0";
+            private String lowerprofitrate = "65.0";
+            private String upperprofitrate = "135.0";
         }
 
         @Data

+ 633 - 47
tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/entity/Request/HtCrawlerSaveOneStepRequest.java

@@ -1,5 +1,6 @@
 package com.jzg.quotation.huatai.crawler.entity.Request;
 
+import com.alibaba.fastjson.JSONObject;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.jzg.commons.entity.quote.vo.CarInfoVo;
 import com.jzg.commons.entity.quote.vo.CustomerInfoVo;
@@ -7,11 +8,14 @@ import com.jzg.commons.entity.quote.vo.QuoteVo;
 import com.jzg.quotation.huatai.crawler.constant.HtRequestConstant;
 import com.jzg.quotation.huatai.crawler.entity.HtCrawlerConfigureParameters;
 import com.jzg.quotation.huatai.crawler.entity.Response.HtCrawlerCarQueryResponse;
+import com.jzg.quotation.huatai.crawler.entity.dto.LoginDTO;
 import lombok.Data;
 
 import java.io.Serial;
 import java.io.Serializable;
+import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 /**
  * @description: 报价第一步,保存车辆及客户信息 请求参数
@@ -23,77 +27,489 @@ public class HtCrawlerSaveOneStepRequest implements Serializable {
     @Serial
     private static final long serialVersionUID = -4856284180707621587L;
 
-    public HtCrawlerSaveOneStepRequest(QuoteVo quoteVo, HtCrawlerCarQueryResponse.DataDTO.DataListDTO carDTO, HtCrawlerConfigureParameters parameters) {
+    public HtCrawlerSaveOneStepRequest(QuoteVo quoteVo, HtCrawlerCarQueryResponse.DataDTO.DataListDTO carDTO, HtCrawlerConfigureParameters parameters, String quotationNo, HtCrawlerCarQueryResponse.DataDTO dataDTO, LoginDTO loginDTO, Map<String, Object> gsInfo) {
         CarInfoVo carInfoVo = quoteVo.getCarInfoVo();
+
+        // 电机类型代码 电机用途类型代码 映射处理
+        extracted(carInfoVo);
         CustomerInfoVo ownersInfo = quoteVo.getOwnersInfo();
         CustomerInfoVo policyHolderInfo = quoteVo.getPolicyHolderInfo();
         CustomerInfoVo insuredPersonInfo = quoteVo.getInsuredPersonInfo();
         this.projectBase = HtRequestConstant.PROJECT_BASE;
         this.requestType = HtRequestConstant.REQUEST_TYPE;
-        this.quoteFlag = false;
-        this.ocrBtnHGFlag = "1";
+        this.licensePlateId = "14";
+        long timestamp = System.currentTimeMillis();
+        this.eacspModelCodeQueryNew = String.valueOf(timestamp);
+        this.eacspModelCodeQueryOld = "";
+        this.eacspVehicleInputNew = String.valueOf(timestamp);
+        this.eacspVehicleInputOld = "";
+        this.eacspVehicleOwnerInputNew = String.valueOf(timestamp - 6895);
+        this.eacspVehicleOwnerInputOld = "";
+        this.eacspDriverInputNew = "";
+        this.eacspDriverInputOld = "";
+        this.eacspInsuranceConnectZtbNew = "";
+        this.eacspInsuranceConnectZtbOld = "";
+        this.motoFlag = "N";
+        this.motorusageFlag = "N";
+        this.priceFlag = "N";
+        this.registerFlag = "N";
+        this.nolicenseFlag = "";
+        this.comCodeq = "";
+        this.nodamageyearsOld = "";
+        this.isNationalflag = "";
+        this.eacspCarsamidOld = "";
+        this.eacspSamidOld = "";
+        this.gdjgVehicleFlag = "";
+        this.gdjgMotorusageTypeCode = "";
+        this.jgCheckpassFlag = "";
+        this.jgDisplacementFlag = "";
+        this.jgLimitloadFlag = "";
+        this.jgWholeweightFlag = "";
+        this.jgLimitloadpersonFlag = "";
+        this.jgVehiclestyleFlag = "";
+        this.whiteFlag = "";
+        this.applicantFlag = "1";
+        this.scFlag = "";
+        this.scjgFlag = "";
+        this.haulAge = "";
+        this.gdjgLicensePlateNo = "";
+        this.gdjgVin = "";
+        this.gdjgEngineNo = "";
+        this.gdjgLicensePlateType = "";
+        this.gdjgpmVehicleType = "";
+        this.gdjgFirstRegisterDate = "";
+        this.gdjgtransferDate = "";
+        this.gdjgWholeWeight = "";
+        this.gdjgLimitLoad = "";
+        this.gdjgLimitLoadPerson = "";
+        this.gdjgDisplacement = "";
+        this.gdjgjgMotorTypeCode = "";
+        this.gdjgjgFuelType = "";
+        this.comCodeFlag = "JZ";
+        this.isShowPower = "1";
+        this.newElectricMoto = "1";
+        this.cipMotoSwitch = "1";
+        this.newEnergySwitch = "1";
+        this.isShowHkMa = "";
+        this.changeRiskCodeSwitch = "1";
+        this.changeRiskCodeSwitchFuelType = "1,2,3,C";
+        this.areaSwitch = "1";
+        this.SHMergeSwitch = "";
+        this.jllxSwitch = "1";
+        this.carQueryNewProcess = "0";
+        this.isJllxVehicleType = "";
+        this.carModelCodexhQuery = "1";
+        this.renewalTwoSwitch = "1";
         this.ocrBtnShowFlag = "1";
+        this.ocrBtnHGFlag = "1";
         this.ocrBtnUsedFlag = "1";
-        this.riskCode = "1251";//从quoteVo获取
-        this.reformRisk = this.riskCode;
-        this.motorTypeCode = carInfoVo.getCarKindCode();
-        this.tmpMotorTypeCode = this.motorTypeCode;
+        this.mdea = "";
+        this.scjgvehicleCheckFlag = "";
+        this.scVehicleQueryFlag = "";
+        this.homeAddress = "";
+        this.insuredAddress = "";
+        this.actionHomeAddress = "";
+        this.xbRecommendInfo = "1";
+        this.daiChuTuiJianFangAn = "0";
+        this.province = "";
+        this.city = "";
+        this.district = "";
+        this.insuredProvince = "";
+        this.insuredCity = "";
+        this.insuredDistrict = "";
+        this.actionProvince = "";
+        this.actionCity = "";
+        this.actionDistrict = "";
+        this.maxDisplacement = "";
+        this.showPowerFlag = "";
+        this.carPostCode = "";
+        this.bbrPostCode = "";
+        this.tbrPostCode = "";
+        this.VehicleStyleUniqueId = "";
+        this.quoteFlag = "false";
+        this.quotationNo = quotationNo;
+        this.reformRisk = "1251";
+        this.isReformComcode = "3";
+        this.lastpolicyno = "";
+        this.riskCode = dataDTO.getRiskcode();
         this.tmpMotorTypeCode2 = this.motorTypeCode;
-        this.motorUsageTypeCode = carInfoVo.getCarNatureCode();
-        this.tmpMotorUsageTypeCode = this.motorUsageTypeCode;
+        this.tmpMotorTypeCode = this.motorTypeCode;
         this.tmpMotorUsageTypeCode2 = this.motorUsageTypeCode;
-        this.licenseMotorUsageTypeCode = this.motorUsageTypeCode;
+        this.tmpMotorUsageTypeCode = this.motorUsageTypeCode;
+        this.secondUsageCode = "";
+        this.licenseMotorUsageTypeCode = "";
+        this.vehicleFlag = "";
+        this.licensePlateStr = "";
+        this.newVehicleFlag = "0";
         this.licensePlateNo = carInfoVo.getLicenseNo();
+        this.ecdemicVehicleFlag = "0";
+        this.tmpVehicleRegisterDate = "";
         this.vehicleRegisterDate = carInfoVo.getRegisterDate();
         this.vin = carInfoVo.getVinNo();
         this.engineNo = carInfoVo.getEngineNo();
         this.brandCn = carDTO.getBrandcn();
-        this.vehicleModel = this.brandCn;
-        this.liceensePlateType = carInfoVo.getLicenseKindCode();
-        this.vehicleStyle = carInfoVo.getCarTypeCode();
+        this.vehicleModel = this.brandCn != null ? this.brandCn : "";
+        this.liceensePlateType = carInfoVo.getLicenseKindCode() + " 小型汽车号牌";
+        this.vehicleStyle = carInfoVo.getCarTypeCode() + " 小型轿车";
+        this.carColorCode = "99";
+        this.licensePlateColorCode = "01";
+        this.tmpPurchasePrice = "";
         this.purchasePrice = carDTO.getPurchasePrice();
         this.limitLoadPerson = carDTO.getLimitloadperson();
-        this.property = carInfoVo.getProperty();
+        this.property = "04";
+        this.tmpbjCertificateDate = "";
         this.bjCertificateDate = carInfoVo.getIssueDate();
+        this.fuelTypeWhiteFlag = "0";
         this.fuelType = carDTO.getFueltype();
+        this.certificateNo = "";
+        this.certificateDate = "";
+        this.certificateType = "01";
         this.modelcodexh = carDTO.getModelcodexh();
+        this.basicrateCode = "";
         this.noticeType = carDTO.getNoticetype();
         this.carName = carDTO.getCarname();
+        this.specialVehicleFlag = "";
+        this.runArea = "04";
+        this.runMilesDetails = "0";
+        this.runMilesDetailsq = "";
+        this.isCustomerLoyal = "";
+        this.loanVehicleFlag = "0";
+        this.specialCarType = "0";
         this.wholeWeight = carDTO.getWholeweight();
         this.power = carDTO.getDisplacement();
+        this.efficiency = carDTO.getEfficiency();
+        this.limitLoad = carDTO.getLimitload();
+        this.specialcarflag = quoteVo.getCarInfoVo().isTransfer() ? "1" : "";
+        this.chgOwnerFlag = quoteVo.getCarInfoVo().isTransferBi() ? "1" : "0";
+        this.tmpTransferDate = "";
+        this.gdjgTransferDate = "";
+        this.transferDate = quoteVo.getCarInfoVo().getTransferDate() == null ? "" : quoteVo.getCarInfoVo().getTransferDate().toString();
+        this.pureRange = "";
+        this.maximumSpeed = "";
+        this.otherEnergyTypeDesc = "";
+        this.queryFlag = "N";
+        this.saveFlag = "Y";
         this.modelCode = carDTO.getModelcode();
-        this.marketYear = carDTO.getCarYear();
+        this.marketYear = carInfoVo.getCarYear();
         this.vehicleOriginSwitch = "1";
-        this.renewalTwoSwitch = "1";
-        //车主
-        this.ownerType = ownersInfo.getPersonType();
+        this.isWindowPeriod = "";
+        this.riskLevel = "4";
+        this.comRiskLevel = "4";
+        this.insuredRiskLevel = "";
+        this.insuredcomrisklevel = "";
+        this.triskLevel = "";
+        this.tinsuredComRiskLevel = "";
+        this.riskWarnInfo = "";
+        this.comRiskWarnInfo = "";
+        this.insuredRiskWarnInfo = "";
+        this.insuredComRiskWarnInfo = "";
+        this.triskWarnInfo = "";
+        this.tinsuredComRiskWarnInfo = "";
+        this.customerNo = "";
+        this.workUnit = "";
+        this.workAddress = "";
+        this.otherContact = "";
+        this.otherWorkAddress = "";
+        this.annualIncome = "0";
+        this.workPhone = "";
+        this.businessDetail = "";
+        this.registFund = "";
+        this.registCurrency = "";
+        this.supportDocuname = "";
+        this.supportDocuNumber = "";
+        this.supportDocuValidDate = "";
+        this.stockorControlName = "";
+        this.socIdentifyNumber = "";
+        this.socOtherIdentifyType = "";
+        this.socOtherIdentifyNumber = "";
+        this.socOtherEffectiveDate = "";
+        this.leaderName = "";
+        this.leaderIdentifyNumber = "";
+        this.leaderOtherIdentifyType = "";
+        this.leaderOtherIdentifyNumber = "";
+        this.leaderOtherEffectiveDate = "";
+        this.leaderStartOtherEffectiveDate = "";
+        this.customerOtherIdentifyNumber = "";
+        this.customerOtherEffectiveDate = "";
+        this.businessSource = "";
+        this.airelation = "";
+        this.bcustomerNo = "";
+        this.bworkUnit = "";
+        this.bworkAddress = "";
+        this.botherContact = "";
+        this.botherWorkAddress = "";
+        this.bannualIncome = "";
+        this.bworkPhone = "";
+        this.bbusinessDetail = "";
+        this.bregistFund = "";
+        this.bregistCurrency = "";
+        this.bsupportDocuName = "";
+        this.bsupportDocuNumber = "";
+        this.bsupportDocuValidDate = "";
+        this.bstockorControlName = "";
+        this.bsocIdentifyNumber = "";
+        this.bsocOtherIdentifyType = "";
+        this.bsocOtherIdentifyNumber = "";
+        this.bsocOtherEffectiveDate = "";
+        this.bleaderName = "";
+        this.bleaderIdentifyNumber = "";
+        this.bleaderOtherIdentifyType = "";
+        this.bleaderOtherIdentifyNumber = "";
+        this.bleaderothereffectivedate = "";
+        this.bleaderStartOtherEffectiveDate = "";
+        this.btranIdentifyType = "";
+        this.bcustomerOtherIdentifyNumber = "";
+        this.bcustomerothereffectivedate = "";
+        this.bbusinessSource = "";
+        this.tcustomerNo = "";
+        this.tworkUnit = "";
+        this.tworkAddress = "";
+        this.totherContact = "";
+        this.totherWorkAddress = "";
+        this.tannualIncome = "";
+        this.tworkPhone = "";
+        this.tbusinessDetail = "";
+        this.tregistFund = "";
+        this.tregistcurrency = "";
+        this.tsupportDocuname = "";
+        this.tsupportDocunumber = "";
+        this.tsupportDocuValidDate = "";
+        this.tstockorControlName = "";
+        this.tsocIdentifyNumber = "";
+        this.tsocOtherIdentifyType = "";
+        this.tsocOtherIdentifyNumber = "";
+        this.tsocOtherEffectiveDate = "";
+        this.tleadername = "";
+        this.tleaderIdentifyNumber = "";
+        this.tleaderOtherIdentifyType = "";
+        this.tleaderOtherIdentifyNumber = "";
+        this.tleaderOtherEffectiveDate = "";
+        this.tleaderStartOtherEffectiveDate = "";
+        this.ttranIdentifyType = "";
+        this.tcustomerOtherIdentifyNumber = "";
+        this.tcustomerOtherEffectiveDate = "";
+        this.tbusinessSource = "";
+        this.unitProperties = "";
+        this.holderAndComrelation = "";
+        this.teleMarketFlag = "";
+        this.channelCode = "";
+        this.teleMarketRenewalPolicyNo = "";
+        this.dxRenewalFlag = "";
+        this.accountManager = "";
+        this.bizNo = "";
+        this.bbeneficiaryList = "";
+        this.bshareHolderList = "";
+        this.tbeneficiaryList = "";
+        this.tshareHolderList = "";
+        this.cshareHolderList = "";
+        this.email = "";
+        this.bemail = "";
+        this.bprovince = "";
+        this.bcity = "";
+        this.bdistrict = "";
+        this.temail = "";
+        this.tprovince = "";
+        this.tcity = "";
+        this.tdistrict = "";
+        this.transActornamet = "";
+        this.tranIdentifyType = "";
+        this.TRANIDENTIFYTYPE = "";
+        this.tranIdentifyNumber = "";
+        this.trancervaliddate = "";
+        this.attribute1 = "";
+        this.xbjgComCode = "";
+        this.xbComCodeToAdJustFlag = "";
+        this.xbLastFlag = "";
+        this.oneMoreFlag = "0";
+        this.oneMoreCheckFlag = "";
+        this.oneMoreCarErrorMsg = "";
+        this.oneMoreQuoteFlag = "";
+        this.whiteStatus = "";
+        this.passPortWhiteStatus = "";
+        this.isPlatCarKindCode = "";
+        this.platCarKindCodeList = "[]";
+        this.H1showPlatCarKindCode = "0";
+        this.carId = "";
+        this.ownerType = "1";
         this.certiType = ownersInfo.getDocumentsTypeCode();
         this.certiCode = ownersInfo.getIdentifyNumber();
         this.ownername = ownersInfo.getName();
-        this.gender = ownersInfo.getGender();
+        if (ownersInfo.getIdentifyNumber() != null && ownersInfo.getIdentifyNumber().length() > 16) {
+            int genderCode = Character.getNumericValue(ownersInfo.getIdentifyNumber().charAt(16));
+            this.gender = genderCode % 2 == 1 ? "1" : "2";
+        }
+        this.tmpPaperscreStartDate = "";
+        this.paperscreStartDate = "2007-08-27";
+        this.tmpPapersValidDate = "";
+        this.papersValidDate = "2027-08-27";
+        this.position = "";
+        this.positionName = "";
         this.ownrAge = String.valueOf(ownersInfo.getAge());
-        //被保人
-        this.isCarwoner = HtRequestConstant.ONE.equals(String.valueOf(insuredPersonInfo.getCarOwner())) ? HtRequestConstant.YES : HtRequestConstant.NO;
-        this.ownerType2 = insuredPersonInfo.getPersonType();
+        this.oneMoreCarFlag = "0";
+        this.familyMemberNo = "";
+        this.canChageFlag = "";
+        this.firstPersonNumber = "";
+        this.subcarLicenseNo = "";
+        this.subcarBizNo = "";
+        this.subcarRelation = "";
+        this.enterPriseCertificateNo = "";
+        this.enterPriseName = "";
+        this.nationalityCode = "";
+        this.transActorName = "";
+        this.comEquityStructure = "";
+        this.carAddress = "";
+        this.carMobile = "";
+        if(insuredPersonInfo.getIdentifyNumber().equals(ownersInfo.getIdentifyNumber())) {
+            this.isCarwoner = HtRequestConstant.YES;
+        } else {
+            this.isCarwoner = HtRequestConstant.NO;
+        }
+        this.insuredId = "";
+        this.ownerType2 = "1";
         this.dCertiType = insuredPersonInfo.getDocumentsTypeCode();
-        this.dCertiCode = insuredPersonInfo.getIdentifyNumber();
-        this.insuredName = insuredPersonInfo.getName();
-        this.insuredGender = insuredPersonInfo.getGender();
-        this.carInsuredRelation = "";//车主与被保人关系
-        //投保人
-        this.tiscarwoner = HtRequestConstant.ONE.equals(String.valueOf(policyHolderInfo.getCarOwner())) ? HtRequestConstant.YES : HtRequestConstant.NO;
-        this.insType = policyHolderInfo.getPersonType();
+        this.dCertiCode = !insuredPersonInfo.getIdentifyNumber().equals(ownersInfo.getIdentifyNumber())? insuredPersonInfo.getIdentifyNumber() : "";
+        if (insuredPersonInfo.getIdentifyNumber() != null && insuredPersonInfo.getIdentifyNumber().length() > 16) {
+            int genderCode = Character.getNumericValue(insuredPersonInfo.getIdentifyNumber().charAt(16));
+            this.insuredGender = genderCode % 2 == 1 ? "1" : "2";
+        }
+        this.tmpInsuredPaperscreStartDate = "";
+        this.insuredPaperscreStartDate = "";
+        this.insuredPapersValidDate = "";
+        this.insuredPapersDate = "";
+        this.insuredPosition = "";
+        this.insuredPositionName = "";
+        this.carInsuredRelation = "2";
+        this.insuredAge = insuredPersonInfo.getIdentifyNumber().equals(ownersInfo.getIdentifyNumber()) ? "":(insuredPersonInfo.getAge()+"") ;
+        this.insuredMobile = "";
+        this.insuredEnterPriseCertificateNo = "";
+        this.insuredEnterPriseName = "";
+        this.insuredNationalityCode = "";
+        this.insuredTransactorName = "";
+        this.comequityStructure1 = "";
+        this.carComInsuredRelation = "2";
+        if(policyHolderInfo.getIdentifyNumber().equals(ownersInfo.getIdentifyNumber())) {
+            this.tiscarwoner = HtRequestConstant.YES;
+        } else {
+            this.tiscarwoner = HtRequestConstant.NO;
+        }
+        this.tid = "";
         this.tCertiType = policyHolderInfo.getDocumentsTypeCode();
-        this.tCertiCode = policyHolderInfo.getIdentifyNumber();
-        this.tname = policyHolderInfo.getName();
-        this.tgender = policyHolderInfo.getGender();
-
+        if(ownersInfo.getIdentifyNumber().equals(String.valueOf(insuredPersonInfo.getIdentifyNumber()))) {
+            this.tCertiCode = "";
+            this.tname = "";
+            this.insuredName = "";
+        } else {
+            this.tCertiCode = policyHolderInfo.getIdentifyNumber();
+            this.tname = policyHolderInfo.getName();
+            this.insuredName = insuredPersonInfo.getName();
+        }
+        if (policyHolderInfo.getIdentifyNumber() != null && policyHolderInfo.getIdentifyNumber().length() > 16) {
+            int genderCode = Character.getNumericValue(policyHolderInfo.getIdentifyNumber().charAt(16));
+            this.tgender = genderCode % 2 == 1 ? "1" : "2";
+        }
+        this.tmptPaperscreStartDate = "";
+        this.tpaperscreStartDate = "";
+        this.tpapersValidDate = "";
+        this.tpapersDate = "";
+        this.tposition = "";
+        this.tpositionName = "";
+        if(ownersInfo.getIdentifyNumber().equals(String.valueOf(policyHolderInfo.getIdentifyNumber()))) {
+            this.tAge = "";
+        } else {
+            this.tAge = String.valueOf(policyHolderInfo.getAge());
+        }
+        this.tMobile = "";
+        this.tenterPriseCertificateNo = "";
+        this.tenterPriseName = "";
+        this.tnationalityCode = "";
+        this.ttransactorName = "";
+        this.comequityStructure2 = "";
         this.isXB = HtRequestConstant.NO;
-        this.quotationNo = "报价单号";
+        this.isNext = "";
         this.fullComCode = parameters.getComCode();
+        this.isYD = "";
         this.comcodeByUserVo = this.fullComCode;
+        this.newLicenseno = "engineSix";
+
+        this.isTeamCarFlag = "";
+        this.teamcarmodelcode = "";
+        this.teamcarmodelname = "";
+        this.salemdea = "";
+        this.pRPDCODJson = "";
+        this.state = "";
+        this.comCodeInAgentsFlag = "0";
+        this.wangdianNameFlag = "0";
+        this.wangdianNameHid = "0";
+        this.licenseNo = "";
+        this.policyBI = "";
+        this.policyCI = "";
+        this.policyStatusBI = "";
+        this.policyStatusCI = "";
+        this.showEmploy = "";
+        this.showEmployControl = "";
+        this.businessature = "";
+        this.comcode = parameters.getComCode();
+        this.comcode_name = String.valueOf(gsInfo.get("comcode_name"));
+        this.comcode_gbcode = String.valueOf(gsInfo.get("comcode_gbdistrictcode"));
+        this.userid = String.valueOf(gsInfo.get("userid_value"));
+        this.userid_name = String.valueOf(gsInfo.get("userid_name"));
+        this.businessNature = String.valueOf(gsInfo.get("businessnature_value"));
+        this.selectsalesys = "";
+        this.salesys = String.valueOf(gsInfo.get("salesys_value"));
+        this.salesys_from_jar = String.valueOf(gsInfo.get("salesys_value"));
+        this.channel = String.valueOf(gsInfo.get("channel_orign"));
+        this.channel_orign = String.valueOf(gsInfo.get("channel_orign"));
+        this.newChannel = String.valueOf(gsInfo.get("newChannel_orign"));
+        this.newChannel_orign = String.valueOf(gsInfo.get("newChannel_orign"));
+        this.agentno_dl = loginDTO.getDlrCode();
+        this.agreementno_dl = loginDTO.getDlxyCode();
+        this.agentno_fdl = "";
+        this.agreementno_fdl = "";
+        this.agentno_jj = "";
+        this.agreementno_jj = "";
+        this.teamcode_value = "";
+        this.teamcode_name = "";
+        this.systemfor = "集成";
+        this.usercodelifedot_text = "";
+        this.usercodelife_value = "";
+        this.usercodelife_name = "";
+        this.usercodelife_text = " - ";
+        this.phone_value = "";
+        this.phone_name = "";
+        this.carType = "";
+
+    }
+
+    private void extracted(CarInfoVo carInfoVo) {
+        if ("04".equals(carInfoVo.getVehicleUseCode())) {
+            this.motorTypeCode = "H0";
+            this.motorUsageTypeCode = "9D";
+        } else if ("05".equals(carInfoVo.getVehicleUseCode())) {
+            this.motorTypeCode = "A0 客车";
+            this.motorUsageTypeCode = "8A 家庭自用";
+        } else if ("06".equals(carInfoVo.getVehicleUseCode())) {
+            if ("A0".equals(carInfoVo.getCarKindCode())) {
+                this.motorTypeCode = "A0 客车";
+                this.motorUsageTypeCode = "8C";
+            } else if ("A1".equals(carInfoVo.getCarKindCode())) {
+                this.motorTypeCode = "H0";
+                this.motorUsageTypeCode = "8D";
+            }
+        } else if ("07".equals(carInfoVo.getVehicleUseCode())) {
+            if ("A0".equals(carInfoVo.getCarKindCode())) {
+                this.motorTypeCode = "A0 客车";
+                this.motorUsageTypeCode = "8B";
+            } else if ("A1".equals(carInfoVo.getCarKindCode())) {
+                this.motorTypeCode = "H0";
+                this.motorUsageTypeCode = "8D";
+            }
+        } else if ("08".equals(carInfoVo.getVehicleUseCode())) {
+            this.motorTypeCode = "H0";
+            this.motorUsageTypeCode = "8D";
+        }
     }
 
+
     @JsonProperty("project_base")
     private String projectBase;
 
@@ -101,7 +517,7 @@ public class HtCrawlerSaveOneStepRequest implements Serializable {
     private String requestType;
 
     @JsonProperty("quoteflag")
-    private Boolean quoteFlag;
+    private String quoteFlag;
 
     @JsonProperty("licenseplateId")
     private String licensePlateId;
@@ -160,6 +576,9 @@ public class HtCrawlerSaveOneStepRequest implements Serializable {
     @JsonProperty("EACSP_CARSAMID_old")
     private String eacspCarsamidOld;
 
+    @JsonProperty("isNationalflag")
+    private String isNationalflag;
+
     @JsonProperty("EACSP_SAMID_old")
     private String eacspSamidOld;
 
@@ -329,10 +748,10 @@ public class HtCrawlerSaveOneStepRequest implements Serializable {
     private String district;
 
     @JsonProperty("ownernation")
-    private String ownerNation;
+    private String ownerNation = "";
 
     @JsonProperty("ownerissuingauthority")
-    private String ownerIssuingAuthority;
+    private String ownerIssuingAuthority = "";
 
     @JsonProperty("insuredprovince")
     private String insuredProvince;
@@ -344,10 +763,10 @@ public class HtCrawlerSaveOneStepRequest implements Serializable {
     private String insuredDistrict;
 
     @JsonProperty("insurednation")
-    private String insuredNation;
+    private String insuredNation = "";
 
     @JsonProperty("insuredissuingauthority")
-    private String insuredIssuingAuthority;
+    private String insuredIssuingAuthority = "";
 
     @JsonProperty("actionprovince")
     private String actionProvince;
@@ -356,10 +775,10 @@ public class HtCrawlerSaveOneStepRequest implements Serializable {
     private String actionDistrict;
 
     @JsonProperty("actionnation")
-    private String actionNation;
+    private String actionNation = "";
 
     @JsonProperty("actionissuingauthority")
-    private String actionIssuingAuthority;
+    private String actionIssuingAuthority = "";
 
     @JsonProperty("maxDisplacement")
     private String maxDisplacement;
@@ -377,7 +796,7 @@ public class HtCrawlerSaveOneStepRequest implements Serializable {
     private String tbrPostCode;
 
     @JsonProperty("VehicleStyleUniqueId")
-    private String vehicleStyleUniqueId;
+    private String VehicleStyleUniqueId;
 
     @JsonProperty("reformRisk")
     private String reformRisk;
@@ -628,6 +1047,9 @@ public class HtCrawlerSaveOneStepRequest implements Serializable {
     @JsonProperty("OTHERWORKADDRESS")
     private String otherWorkAddress;
 
+    @JsonProperty("PRPDCODJson")
+    private String pRPDCODJson = "";
+
     @JsonProperty("annualincome")
     private String annualIncome;
 
@@ -685,9 +1107,12 @@ public class HtCrawlerSaveOneStepRequest implements Serializable {
     @JsonProperty("LEADERSTARTOTHEREFFECTIVEDATE")
     private String leaderStartOtherEffectiveDate;
 
-    @JsonProperty("TRANIDENTIFYTYPE")
+    @JsonProperty("tranidentifytype")
     private String tranIdentifyType;
 
+    @JsonProperty("TRANIDENTIFYTYPE")
+    private String TRANIDENTIFYTYPE;
+
     @JsonProperty("CUSTOMEROTHERIDENTIFYNUMBER")
     private String customerOtherIdentifyNumber;
 
@@ -977,7 +1402,7 @@ public class HtCrawlerSaveOneStepRequest implements Serializable {
     private String isPlatCarKindCode;
 
     @JsonProperty("platCarKindCodeList")
-    private List<String> platCarKindCodeList;
+    private String platCarKindCodeList;
 
     @JsonProperty("H1showPlatCarKindCode")
     private String H1showPlatCarKindCode;
@@ -1027,12 +1452,30 @@ public class HtCrawlerSaveOneStepRequest implements Serializable {
     @JsonProperty("familymemberno")
     private String familyMemberNo;
 
+//    @JsonProperty("firstPersonInfoFlag")
+//    private String firstPersonInfoFlag="";
+
     @JsonProperty("canChageFlag")
     private String canChageFlag;
 
     @JsonProperty("firstpersonnumber")
     private String firstPersonNumber;
 
+//    @JsonProperty("fourthUsageCodeSwitch")
+//    private String fourthUsageCodeSwitch="";
+
+//    @JsonProperty("homeaddress")
+//    private String homeaddress="";
+
+//    @JsonProperty("htbPlatFormId")
+//    private String htbPlatFormId="";
+
+    @JsonProperty("ins_type")
+    private String ins_type="1";
+
+    @JsonProperty("insuredcomrisklevel")
+    private String insuredcomrisklevel="4";
+
     @JsonProperty("subcarlicenseno")
     private String subcarLicenseNo;
 
@@ -1135,9 +1578,6 @@ public class HtCrawlerSaveOneStepRequest implements Serializable {
     @JsonProperty("tid")
     private String tid;
 
-    @JsonProperty("ins_type")
-    private String insType;
-
     @JsonProperty("t_certi_type")
     private String tCertiType;
 
@@ -1210,5 +1650,151 @@ public class HtCrawlerSaveOneStepRequest implements Serializable {
     @JsonProperty("newLicenseno")
     private String newLicenseno;
 
+//    @JsonProperty("insuredComRiskLevel")
+//    private String insuredComRiskLevel;
+
+    @JsonProperty("secondUsageCode")
+    private String secondUsageCode;
+
+    @JsonProperty("actionCity")
+    private String actionCity;
+
+    @JsonProperty("isTeamCarFlag")
+    private String isTeamCarFlag;
+
+    @JsonProperty("teamcarmodelcode")
+    private String teamcarmodelcode;
+
+    @JsonProperty("teamcarmodelname")
+    private String teamcarmodelname;
+
+    @JsonProperty("salemdea")
+    private String salemdea;
+
+//    @JsonProperty("PRPDCODJson")
+//    private String PRPDCODJson;
+
+    @JsonProperty("state")
+    private String state;
+
+    @JsonProperty("comCodeInAgentsFlag")
+    private String comCodeInAgentsFlag;
+
+    @JsonProperty("wangdianNameFlag")
+    private String wangdianNameFlag;
+
+    @JsonProperty("wangdianNameHid")
+    private String wangdianNameHid;
+
+    @JsonProperty("licenseNo")
+    private String licenseNo;
+
+    @JsonProperty("policyBI")
+    private String policyBI;
+
+    @JsonProperty("policyCI")
+    private String policyCI;
+
+    @JsonProperty("policyStatusBI")
+    private String policyStatusBI;
+
+    @JsonProperty("policyStatusCI")
+    private String policyStatusCI;
+
+    @JsonProperty("showEmploy")
+    private String showEmploy;
+
+    @JsonProperty("showEmployControl")
+    private String showEmployControl;
+
+    @JsonProperty("businessature")
+    private String businessature;
+
+    @JsonProperty("comcode")
+    private String comcode;
+
+    @JsonProperty("comcode_name")
+    private String comcode_name;
+
+    @JsonProperty("comcode_gbcode")
+    private String comcode_gbcode;
+
+    @JsonProperty("userid")
+    private String userid;
+
+    @JsonProperty("userid_name")
+    private String userid_name;
+
+    @JsonProperty("businessNature")
+    private String businessNature;
+
+    @JsonProperty("selectsalesys")
+    private String selectsalesys;
+
+    @JsonProperty("salesys")
+    private String salesys;
+
+    @JsonProperty("salesys_from_jar")
+    private String salesys_from_jar;
+
+    @JsonProperty("channel")
+    private String channel;
+
+    @JsonProperty("channel_orign")
+    private String channel_orign;
+
+    @JsonProperty("newChannel")
+    private String newChannel;
+
+    @JsonProperty("newChannel_orign")
+    private String newChannel_orign;
+
+    @JsonProperty("agentno_dl")
+    private String agentno_dl;
+
+    @JsonProperty("agreementno_dl")
+    private String agreementno_dl;
+
+    @JsonProperty("agentno_fdl")
+    private String agentno_fdl;
+
+    @JsonProperty("agreementno_fdl")
+    private String agreementno_fdl;
+
+    @JsonProperty("agentno_jj")
+    private String agentno_jj;
+
+    @JsonProperty("agreementno_jj")
+    private String agreementno_jj;
+
+    @JsonProperty("teamcode_value")
+    private String teamcode_value;
+
+    @JsonProperty("teamcode_name")
+    private String teamcode_name;
+
+    @JsonProperty("systemfor")
+    private String systemfor;
+
+    @JsonProperty("usercodelifedot_text")
+    private String usercodelifedot_text;
+
+    @JsonProperty("usercodelife_value")
+    private String usercodelife_value;
+
+    @JsonProperty("usercodelife_name")
+    private String usercodelife_name;
+
+    @JsonProperty("usercodelife_text")
+    private String usercodelife_text;
+
+    @JsonProperty("phone_value")
+    private String phone_value;
+
+    @JsonProperty("phone_name")
+    private String phone_name;
+
+    @JsonProperty("carType")
+    private String carType;
 
 }

+ 458 - 267
tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/entity/Request/HtCrawlerSubmitRequest.java

@@ -24,27 +24,101 @@ public class HtCrawlerSubmitRequest implements Serializable {
     @Serial
     private static final long serialVersionUID = 1814925768981794647L;
 
-    public HtCrawlerSubmitRequest(UnderwritingVo underwritingVo, HtCrawlerConfigureParameters parameters) {
+    public HtCrawlerSubmitRequest(UnderwritingVo underwritingVo, HtCrawlerConfigureParameters parameters, String ciCategory, String biCategory) {
         //设置车主,投保人,被保人信息
         List<InsOrdersCarUserInfo> insOrdersCarUserInfoList = underwritingVo.getInsOrdersCarUserInfoList();
-        for (InsOrdersCarUserInfo insOrdersCarUserInfo : insOrdersCarUserInfoList) {
-            switch (insOrdersCarUserInfo.getPolicyPersonType()) {
-                case 1 :
-                    this.carOwnerType = String.valueOf(insOrdersCarUserInfo.getPersonType());
-                    this.carOwnerGender = insOrdersCarUserInfo.getGender();
-                    this.ownerAddress = insOrdersCarUserInfo.getAddr();
-                    this.carOwnerName = insOrdersCarUserInfo.getName();
-                    this.carOwnerCertiType = String.valueOf(insOrdersCarUserInfo.getCerType());
-                    this.carOwnerCertiCode = insOrdersCarUserInfo.getIdentifyNumber();
-                    this.carOwnerMobile = insOrdersCarUserInfo.getMobile();
-                    this.carOwnerAge = String.valueOf(insOrdersCarUserInfo.getAge());
+
+        InsOrdersCarUserInfo ownerInfo = null;
+        InsOrdersCarUserInfo applicantInfo = null;
+        InsOrdersCarUserInfo insuredInfo = null;
+
+        for (InsOrdersCarUserInfo userInfo : insOrdersCarUserInfoList) {
+            switch (userInfo.getPolicyPersonType()) {
+                case 1:
+                    ownerInfo = userInfo;
                     break;
-                case 2 :
+                case 2:
+                    applicantInfo = userInfo;
                     break;
-                case 3 :
+                case 3:
+                    insuredInfo = userInfo;
                     break;
             }
         }
+
+        this.carMobile = ownerInfo != null ? ownerInfo.getMobile() : "";
+        this.tel = ownerInfo != null ? ownerInfo.getMobile() : "";
+
+        this.ciCategory = ciCategory;
+        this.biCategory = biCategory;
+
+        if (ownerInfo != null) {
+            String[] addressParts = splitAddress(ownerInfo.getAddr());
+            this.province = ownerInfo.getProvinceCode();
+            this.city = ownerInfo.getCityCode();
+            this.district = ownerInfo.getCountyCode();
+            this.street = ownerInfo.getAddr();
+            this.tmpPaperscreStartDate = ownerInfo.getIdentifyValidDate() == null ? "" : ownerInfo.getIdentifyValidDate().toString().substring(0, 10);
+            this.paperscreStartDate = ownerInfo.getIdentifyValidDate() == null ? "" : ownerInfo.getIdentifyValidDate().toString().substring(0, 10);
+            this.tmpPapersValidDate = ownerInfo.getIdentifyValidEndDate() == null ? "" : ownerInfo.getIdentifyValidEndDate().toString().substring(0, 10);
+            this.papersValidDate = ownerInfo.getIdentifyValidEndDate() == null ? "" : ownerInfo.getIdentifyValidEndDate().toString().substring(0, 10);
+
+        }
+
+        if (insuredInfo != null) {
+            this.tmpInsuredPaperscreStartDate = insuredInfo.getIdentifyValidDate() == null ? "" : insuredInfo.getIdentifyValidDate().toString().substring(0, 10);
+            this.insuredPaperscreStartDate = insuredInfo.getIdentifyValidDate() == null ? "" : insuredInfo.getIdentifyValidDate().toString().substring(0, 10);
+            this.insuredPapersValidDate = insuredInfo.getIdentifyValidEndDate() == null ? "" : insuredInfo.getIdentifyValidEndDate().toString().substring(0, 10);
+            this.insuredPapersDate = insuredInfo.getIdentifyValidEndDate() == null ? "" : insuredInfo.getIdentifyValidEndDate().toString().substring(0, 10);
+            this._tel = insuredInfo.getMobile();
+
+            String[] bbAddressParts = splitAddress(insuredInfo.getAddr());
+            this._province = insuredInfo.getProvinceCode();
+            this._city = insuredInfo.getCityCode();
+            this._district = insuredInfo.getCountyCode();
+            this._street = insuredInfo.getAddr();
+
+            this.t_province = insuredInfo.getProvinceCode();
+            this.t_city = insuredInfo.getCityCode();
+            this.t_district = insuredInfo.getCountyCode();
+            this.t_street = insuredInfo.getAddr();
+
+            this.t_tel = insuredInfo.getMobile();
+
+            this.insuredName = insuredInfo.getName();
+            this.certiCode = insuredInfo.getIdentifyNumber();
+            this.insVocode = insuredInfo.getIdentifyNumber();
+
+            this.carOwnerName = insuredInfo.getName();
+            this.carOwnerCertiCode = insuredInfo.getIdentifyNumber();
+            this.carOwnerMobile = insuredInfo.getMobile();
+            this.ownerAddress = insuredInfo.getAddr();
+            this.carOwnerType = "1";
+            this.carOwnerCertiType = "01";
+            this.tmpProStartDate = insuredInfo.getIdentifyValidDate() == null ? "" : insuredInfo.getIdentifyValidDate().toString().substring(0, 10);
+            this.proStartDate = insuredInfo.getIdentifyValidDate() == null ? "" : insuredInfo.getIdentifyValidDate().toString().substring(0, 10);
+            this.tmpProValidDate = insuredInfo.getIdentifyValidEndDate() == null ? "" : insuredInfo.getIdentifyValidEndDate().toString().substring(0, 10);
+            this.proValidDate = insuredInfo.getIdentifyValidEndDate() == null ? "" : insuredInfo.getIdentifyValidEndDate().toString().substring(0, 10);
+
+
+            Integer gender = parseGenderFromIdCard(insuredInfo.getIdentifyNumber());
+            this.gender = gender != null ? String.valueOf(gender) : "1";
+            this.carOwnerGender = this.gender;
+
+
+            int age = calculateAge(insuredInfo.getIdentifyNumber());
+            this.tAge = String.valueOf(age);
+            this.carOwnerAge = this.tAge;
+
+            this.isCarOwenerFlag = (ownerInfo != null && insuredInfo != null &&
+                    ownerInfo.getName().equals(insuredInfo.getName())) ? "Y" : "N";
+
+            this.appliBirthDay = extractBirthday(insuredInfo.getIdentifyNumber());
+
+            this.vat_telephon = insuredInfo.getMobile();
+            this.jInsuredName = insuredInfo.getName();
+        }
+
         List<ClauseDTO> clauseDTOS = new ArrayList<>();
         for (SpecialAppointmentsVo specialAppointmentsVo : underwritingVo.getSpecialAppointmentsVos()) {
             ClauseDTO clauseDTO = new ClauseDTO();
@@ -55,75 +129,181 @@ public class HtCrawlerSubmitRequest implements Serializable {
             clauseDTO.setReadonly("1");
             clauseDTOS.add(clauseDTO);
         }
+
+        boolean isOwnerSameAsInsured = (ownerInfo != null && insuredInfo != null &&
+                ownerInfo.getName().equals(insuredInfo.getName()));
+
+        if (isOwnerSameAsInsured) {
+            this.iisCarOwner = "Y";
+            this.beibaorenId = "Y";
+        }
+
+        ClauseDTO jxClause = new ClauseDTO();
+        jxClause.setChosedE("T4224");
+        jxClause.setClausename("交强险保额特约");
+        jxClause.setRiskcode("1002");
+        jxClause.setIsDelete("0");
+        jxClause.setClauses("本保单赔偿限额为:被保险人有责时死亡伤残赔偿限额为180000元;医疗费用赔偿限额为18000元;财产损失赔偿限额为2000元。被保险人无责任时,无责任死亡伤残赔偿限额为18000元;无责任医疗费用赔偿限额为1800元;无责任财产损失赔偿限额为100元。");
+        jxClause.setReadonly("1");
+        clauseDTOS.add(jxClause);
+
+        if (!isOwnerSameAsInsured && ownerInfo != null) {
+            ClauseDTO ownerClause = new ClauseDTO();
+            ownerClause.setChosedE("T0028");
+            ownerClause.setClausename("车主约定");
+            ownerClause.setRiskcode("1002");
+            ownerClause.setIsDelete("0");
+            ownerClause.setClauses("本保单行驶证车主为:" + ownerInfo.getName());
+            ownerClause.setReadonly("1");
+            clauseDTOS.add(ownerClause);
+        }
+
+
         this.clauses = clauseDTOS;
         this.fullcomcode = parameters.getComCode();
+
+        this.quotationNo = underwritingVo.getOrder() != null ? underwritingVo.getOrder().getQuoteNo() : "";
+    }
+
+    private String[] splitAddress(String addr) {
+        if (addr == null || addr.isEmpty()) {
+            return new String[]{"", "", ""};
+        }
+        String[] parts = new String[]{"", "", ""};
+        int len = addr.length();
+        int start = 0;
+        int count = 0;
+
+        for (int i = 0; i < len && count < 2; i++) {
+            char c = addr.charAt(i);
+            if (c == '省' || c == '市' || c == '区' || c == '县') {
+                parts[count++] = addr.substring(start, i + 1);
+                start = i + 1;
+            }
+        }
+
+        if (count < 3) {
+            parts[count] = addr.substring(start);
+        }
+
+        return parts;
+    }
+
+    private Integer parseGenderFromIdCard(String idCard) {
+        if (idCard == null || idCard.length() < 17) {
+            return 1;
+        }
+        try {
+            int genderDigit = Character.getNumericValue(idCard.charAt(16));
+            return genderDigit % 2 == 1 ? 1 : 2;
+        } catch (Exception e) {
+            return 1;
+        }
+    }
+
+    private int calculateAge(String idCard) {
+        if (idCard == null || idCard.length() < 14) {
+            return 0;
+        }
+        try {
+            int birthYear = Integer.parseInt(idCard.substring(6, 10));
+            int birthMonth = Integer.parseInt(idCard.substring(10, 12));
+            int birthDay = Integer.parseInt(idCard.substring(12, 14));
+
+            java.time.LocalDate now = java.time.LocalDate.now();
+            int currentYear = now.getYear();
+            int currentMonth = now.getMonthValue();
+            int currentDay = now.getDayOfMonth();
+
+            int age = currentYear - birthYear;
+
+            if (currentMonth < birthMonth ||
+                    (currentMonth == birthMonth && currentDay < birthDay)) {
+                age--;
+            }
+
+            return age;
+        } catch (Exception e) {
+            return 0;
+        }
+    }
+
+    private String extractBirthday(String idCard) {
+        if (idCard == null || idCard.length() < 14) {
+            return "";
+        }
+        try {
+            return idCard.substring(6, 10) + "-" + idCard.substring(10, 12) + "-" + idCard.substring(12, 14);
+        } catch (Exception e) {
+            return "";
+        }
     }
 
     @JsonProperty("istransactor")
-    private String isTransactor;
+    private String isTransactor = "";
 
     @JsonProperty("istransactormobile")
-    private String isTransactorMobile;
+    private String isTransactorMobile = "";
 
     @JsonProperty("telemarketFlag")
-    private String teleMarketFlag;
+    private String teleMarketFlag = "8";
 
     @JsonProperty("channelCode")
-    private String channelCode;
+    private String channelCode = "";
 
     @JsonProperty("carMobile")
     private String carMobile;
 
     @JsonProperty("appliIdentifyType")
-    private String appliIdentifyType;
+    private String appliIdentifyType = "01";
 
     @JsonProperty("insuredIdentifyType")
-    private String insuredIdentifyType;
+    private String insuredIdentifyType = "01";
 
     @JsonProperty("ownerIdentifyType")
-    private String ownerIdentifyType;
+    private String ownerIdentifyType = "01";
 
     @JsonProperty("insured_individualBusiness")
-    private String insuredIndividualBusiness;
+    private String insuredIndividualBusiness = "";
 
     @JsonProperty("autonuclearFlag")
-    private String autoNuclearFlag;
+    private String autoNuclearFlag = "0";
 
     @JsonProperty("isSubmitProduct")
-    private String isSubmitProduct;
+    private String isSubmitProduct = "0";
 
     @JsonProperty("recommendName")
-    private String recommendName;
+    private String recommendName = "";
 
     @JsonProperty("checkDifferentYear")
-    private String checkDifferentYear;
+    private String checkDifferentYear = "0";
 
     @JsonProperty("carvotype")
-    private String carVoType;
+    private String carVoType = "1";
 
     @JsonProperty("insVotype")
-    private String insVoType;
+    private String insVoType = "1";
 
     @JsonProperty("areaSwitch")
-    private String areaSwitch;
+    private String areaSwitch = "1";
 
     @JsonProperty("bicategory")
-    private String biCategory;
+    private String biCategory = "";
 
     @JsonProperty("cicategory")
     private String ciCategory;
 
     @JsonProperty("banliren")
-    private String transactors;
+    private String transactors = "";
 
     @JsonProperty("SHMergeSwitch")
-    private String SHMergeSwitch;
+    private String SHMergeSwitch = "";
 
-    @JsonProperty("UnifiedMergeSwitch")
-    private String unifiedMergeSwitch;
+//    @JsonProperty("UnifiedMergeSwitch")
+//    private String unifiedMergeSwitch;
 
     @JsonProperty("stagFlag")
-    private String stagFlag;
+    private String stagFlag = "1";
 
     @JsonProperty("tmppaperscrestartdate")
     private String tmpPaperscreStartDate;
@@ -138,25 +318,25 @@ public class HtCrawlerSubmitRequest implements Serializable {
     private String papersValidDate;
 
     @JsonProperty("risklevel")
-    private String riskLevel;
+    private String riskLevel = "4";
 
     @JsonProperty("registration")
-    private String registration;
+    private String registration = "CHN";
 
     @JsonProperty("monitorrecord")
-    private String monitorRecord;
+    private String monitorRecord = "";
 
     @JsonProperty("riskwarninfo")
-    private String riskWarnInfo;
+    private String riskWarnInfo = "";
 
     @JsonProperty("tel")
     private String tel;
 
     @JsonProperty("email")
-    private String email;
+    private String email = "";
 
     @JsonProperty("community")
-    private String community;
+    private String community = "";
 
     @JsonProperty("province")
     private String province;
@@ -171,64 +351,64 @@ public class HtCrawlerSubmitRequest implements Serializable {
     private String street;
 
     @JsonProperty("sales_position2")
-    private String salesPosition2;
+    private String salesPosition2 = "";
 
     @JsonProperty("position_value2")
-    private String positionValue2;
+    private String positionValue2 = "";
 
     @JsonProperty("position_name2")
-    private String positionName2;
+    private String positionName2 = "";
 
     @JsonProperty("sales_position")
-    private String salesPosition;
+    private String salesPosition = "";
 
     @JsonProperty("position")
-    private String position;
+    private String position = "";
 
     @JsonProperty("position_name")
-    private String positionName;
+    private String positionName = "";
 
     @JsonProperty("customerno")
-    private String customerNo;
+    private String customerNo = "";
 
     @JsonProperty("workname")
-    private String workName;
+    private String workName = "";
 
     @JsonProperty("workphone")
-    private String workPhone;
+    private String workPhone = "";
 
     @JsonProperty("yearmoney")
-    private String yearMoney;
+    private String yearMoney = "0";
 
     @JsonProperty("workaddress")
-    private String workAddress;
+    private String workAddress = "";
 
     @JsonProperty("otherphone")
-    private String otherPhone;
+    private String otherPhone = "";
 
     @JsonProperty("otheraddress")
-    private String otherAddress;
+    private String otherAddress = "";
 
     @JsonProperty("ccontrollerName")
-    private String ccontrollerName;
+    private String ccontrollerName = "";
 
     @JsonProperty("ccontrollerIdentifyType")
-    private String ccontrollerIdentifyType;
+    private String ccontrollerIdentifyType = "";
 
     @JsonProperty("ccontrollerIdentifyCode")
-    private String ccontrollerIdentifyCode;
+    private String ccontrollerIdentifyCode = "";
 
     @JsonProperty("ccontrollerStartPeriod")
-    private String ccontrollerStartPeriod;
+    private String ccontrollerStartPeriod = "";
 
     @JsonProperty("ccontrollerValidityPeriod")
-    private String ccontrollerValidityPeriod;
+    private String ccontrollerValidityPeriod = "";
 
     @JsonProperty("beibaoren_id")
     private String beibaorenId;
 
     @JsonProperty("isSZteamcarReportFlag")
-    private String isSZteamcarReportFlag;
+    private String isSZteamcarReportFlag = "";
 
     @JsonProperty("iscarowenerflag")
     private String isCarOwenerFlag;
@@ -246,25 +426,25 @@ public class HtCrawlerSubmitRequest implements Serializable {
     private String insuredPapersDate;
 
     @JsonProperty("insuredrisklevel")
-    private String insuredRiskLevel;
+    private String insuredRiskLevel = "";
 
     @JsonProperty("registration1")
-    private String registration1;
+    private String registration1 = "CHN";
 
     @JsonProperty("monitorrecord1")
-    private String monitorrecord1;
+    private String monitorrecord1 = "";
 
     @JsonProperty("riskwarninfo1")
-    private String riskWarnInfo1;
+    private String riskWarnInfo1 = "";
 
     @JsonProperty("_tel")
     private String _tel;
 
     @JsonProperty("b_email")
-    private String bEmail;
+    private String bEmail = "";
 
     @JsonProperty("_community")
-    private String _community;
+    private String _community = "";
 
     @JsonProperty("_province")
     private String _province;
@@ -279,82 +459,86 @@ public class HtCrawlerSubmitRequest implements Serializable {
     private String _street;
 
     @JsonProperty("sales_insuredposition2")
-    private String salesInsuredPosition2;
+    private String salesInsuredPosition2 = "";
 
     @JsonProperty("insuredposition2")
-    private String insuredPosition2;
+    private String insuredPosition2 = "";
 
     @JsonProperty("insuredposition_name2")
-    private String insuredPositionName2;
+    private String insuredPositionName2 = "";
 
     @JsonProperty("sales_insuredposition")
-    private String salesInsuredPosition;
+    private String salesInsuredPosition = "";
 
     @JsonProperty("insuredposition")
-    private String insuredPosition;
+    private String insuredPosition = "";
 
     @JsonProperty("insuredposition_name")
-    private String insuredPositionName;
+    private String insuredPositionName = "";
 
     @JsonProperty("bbr_beneficiaryName")
-    private String bbrBeneficiaryName;
+    private String bbrBeneficiaryName = "";
 
     @JsonProperty("bbr_beneficiaryIdentifyType")
-    private String bbrBeneficiaryIdentifyType;
+    private String bbrBeneficiaryIdentifyType = "";
 
     @JsonProperty("bbr_beneficiaryIdentifyCode")
-    private String bbrBeneficiaryIdentifyCode;
+    private String bbrBeneficiaryIdentifyCode = "";
 
     @JsonProperty("bbr_IdentifyStartPeriod")
-    private String bbrIdentifyStartPeriod;
+    private String bbrIdentifyStartPeriod = "";
 
     @JsonProperty("bbr_IdentifyValidityPeriod")
-    private String bbrIdentifyValidityPeriod;
+    private String bbrIdentifyValidityPeriod = "";
 
     @JsonProperty("bbr_beneficiaryAddress")
-    private String bbrBeneficiaryAddress;
+    private String bbrBeneficiaryAddress = "";
 
     @JsonProperty("bbr_beneficiarymethod")
-    private String bbrBeneficiaryMethod;
+    private String bbrBeneficiaryMethod = "";
 
     @JsonProperty("bbr_beneficiaryaccountfor")
-    private String bbrBeneficiaryAccountfor;
+    private String bbrBeneficiaryAccountfor = "";
 
     @JsonProperty("bcontrollerName")
-    private String bcontrollerName;
+    private String bcontrollerName = "";
 
     @JsonProperty("bcontrollerIdentifyType")
-    private String bcontrollerIdentifyType;
+    private String bcontrollerIdentifyType = "";
 
     @JsonProperty("bcontrollerIdentifyCode")
-    private String bcontrollerIdentifyCode;
+    private String bcontrollerIdentifyCode = "";
 
     @JsonProperty("bcontrollerStartPeriod")
-    private String bcontrollerStartPeriod;
+    private String bcontrollerStartPeriod = "";
 
     @JsonProperty("bcontrollerValidityPeriod")
-    private String bcontrollerValidityPeriod;
+    private String bcontrollerValidityPeriod = "";
 
     @JsonProperty("bcustomerno")
-    private String bcustomerNo;
+    private String bcustomerNo = "";
 
     @JsonProperty("bworkname")
-    private String bworkName;
+    private String bworkName = "";
 
     @JsonProperty("bworkphone")
-    private String bworkphone;
+    private String bworkphone = "";
 
     @JsonProperty("byearmoney")
-    private String byearmoney;
+    private String byearmoney = "";
 
     @JsonProperty("bworkaddress")
-    private String bworkAddress;
+    private String bworkAddress = "";
 
     @JsonProperty("botherphone")
-    private String botherPhone;
+    private String botherPhone = "";
 
     @JsonProperty("botheraddress")
-    private String botherAddress;
+    private String botherAddress = "";
+
+    //#投保人与被保人的关系 本人01 其他   ("t_airelation", "01" ),
+    @JsonProperty("t_airelation")
+    private String tAirRelation = "";
 
     @JsonProperty("i_iscarowner")
     private String iisCarOwner;
@@ -363,55 +547,55 @@ public class HtCrawlerSubmitRequest implements Serializable {
     private String appliBirthDay;
 
     @JsonProperty("transactor1_nam")
-    private String transactorNam;
+    private String transactorNam = "";
 
     @JsonProperty("transactoridentifytype1")
-    private String transactorIdentifyType1;
+    private String transactorIdentifyType1 = "01";
 
     @JsonProperty("transtartdate1")
-    private String transtartdate1;
+    private String transtartdate1 = "";
 
     @JsonProperty("transtartsactorexpirydate1")
-    private String transtartsactorexpirydate1;
+    private String transtartsactorexpirydate1 = "";
 
     @JsonProperty("tranvaliddate1")
-    private String tranValidDate1;
+    private String tranValidDate1 = "";
 
     @JsonProperty("transactorexpirydate1")
-    private String transactorExpiryDate1;
+    private String transactorExpiryDate1 = "";
 
     @JsonProperty("transactoridentifycode1")
-    private String transactorIdentifyCode1;
+    private String transactorIdentifyCode1 = "";
 
     @JsonProperty("transactormobile1")
-    private String transactorMobile1;
+    private String transactorMobile1 = "";
 
     @JsonProperty("car_owner_type")
-    private String carOwnerType;
+    private String carOwnerType = "1";
 
     @JsonProperty("car_owner_gender")
     private String carOwnerGender;
 
     @JsonProperty("owner_ecn")
-    private String ownerEcn;
+    private String ownerEcn = "";
 
     @JsonProperty("owner_risk_level")
-    private String ownerRiskLevel;
+    private String ownerRiskLevel = "";
 
     @JsonProperty("owner_address")
     private String ownerAddress;
 
     @JsonProperty("owner_linker_name")
-    private String ownerLinkerName;
+    private String ownerLinkerName = "";
 
     @JsonProperty("owner_linker_relation")
-    private String ownerLinkerRelation;
+    private String ownerLinkerRelation = "";
 
     @JsonProperty("owner_linker_nation")
-    private String ownerLinkerNation;
+    private String ownerLinkerNation = "";
 
     @JsonProperty("owner_blr")
-    private String ownerBlr;
+    private String ownerBlr = "";
 
     @JsonProperty("car_owner_name")
     private String carOwnerName;
@@ -429,22 +613,22 @@ public class HtCrawlerSubmitRequest implements Serializable {
     private String carOwnerAge;
 
     @JsonProperty("car_owner_enterprisename")
-    private String carOwnerEnterprisename;
+    private String carOwnerEnterprisename = "";
 
     @JsonProperty("car_owner_secrecyunitflag")
-    private String carOwnerSecrecyunitFlag;
+    private String carOwnerSecrecyunitFlag = "";
 
     @JsonProperty("car_owner_samid")
-    private String carOwnerSamid;
+    private String carOwnerSamid = "";
 
     @JsonProperty("insVocode")
     private String insVocode;
 
     @JsonProperty("ins_type")
-    private String insType;
+    private String insType = "1";
 
     @JsonProperty("certi_type")
-    private String certiType;
+    private String certiType = "01";
 
     @JsonProperty("certi_code")
     private String certiCode;
@@ -471,94 +655,94 @@ public class HtCrawlerSubmitRequest implements Serializable {
     private String tAge;
 
     @JsonProperty("risk_level")
-    private String risk_level;
+    private String risk_level = "";
 
     @JsonProperty("p_registration")
-    private String pRegistration;
+    private String pRegistration = "CHN";
 
     @JsonProperty("appliUnitproperties")
-    private String appliUnitProperties;
+    private String appliUnitProperties = "";
 
     @JsonProperty("appliHolderandcomrelation")
-    private String appliHoldeRandcomRelation;
+    private String appliHoldeRandcomRelation = "";
 
     @JsonProperty("p_monitorrecord")
-    private String pMonitorRecord;
+    private String pMonitorRecord = "";
 
     @JsonProperty("p_riskwarninfo")
-    private String pRiskWarnInfo;
+    private String pRiskWarnInfo = "";
 
     @JsonProperty("smallEnterpriseFlagName")
-    private String smallEnterpriseFlagName;
+    private String smallEnterpriseFlagName = "0";
 
     @JsonProperty("enterpriseNatureName")
-    private String enterPriseNatureName;
+    private String enterPriseNatureName = "0";
 
     @JsonProperty("j_iscom")
-    private String jIscom;
+    private String jIscom = "0";
 
     @JsonProperty("j_swh")
-    private String jSwh;
+    private String jSwh = "";
 
     @JsonProperty("j_ecn")
-    private String jEcn;
+    private String jEcn = "";
 
     @JsonProperty("j_insured_name")
     private String jInsuredName;
 
     @JsonProperty("j_enter_no")
-    private String j_enter_no;
+    private String j_enter_no = "";
 
     @JsonProperty("TRANSACTOR_NAME")
-    private String transactorName;
+    private String transactorName = "";
 
     @JsonProperty("transactoridentifytype")
-    private String transactorIdentifyType;
+    private String transactorIdentifyType = "";
 
     @JsonProperty("transactoridentifycode")
-    private String transactorIdentifyCode;
+    private String transactorIdentifyCode = "";
 
     @JsonProperty("transtartdate")
-    private String transtartdate;
+    private String transtartdate = "";
 
     @JsonProperty("transtartsactorexpirydate")
-    private String transtartsactorexpirydate;
+    private String transtartsactorexpirydate = "";
 
     @JsonProperty("tranvaliddate")
-    private String tranvaliddate;
+    private String tranvaliddate = "";
 
     @JsonProperty("transactorexpirydate")
-    private String transactorexpirydate;
+    private String transactorexpirydate = "";
 
     @JsonProperty("transactormobile")
-    private String transactormobile;
+    private String transactormobile = "";
 
     @JsonProperty("c_risk_level")
-    private String c_risk_level;
+    private String c_risk_level = "";
 
     @JsonProperty("c_comregistration")
-    private String c_comregistration;
+    private String c_comregistration = "";
 
     @JsonProperty("unitUnitproperties")
-    private String unitUnitproperties;
+    private String unitUnitproperties = "";
 
     @JsonProperty("unitHolderandcomrelation")
-    private String unitHolderandcomrelation;
+    private String unitHolderandcomrelation = "";
 
     @JsonProperty("c_commonitorrecord")
-    private String c_commonitorrecord;
+    private String c_commonitorrecord = "";
 
     @JsonProperty("c_comriskwarninfo")
-    private String c_comriskwarninfo;
+    private String c_comriskwarninfo = "";
 
     @JsonProperty("t_tel")
     private String t_tel;
 
     @JsonProperty("t_email")
-    private String t_email;
+    private String t_email = "";
 
     @JsonProperty("t_community")
-    private String t_community;
+    private String t_community = "";
 
     @JsonProperty("t_province")
     private String t_province;
@@ -567,306 +751,313 @@ public class HtCrawlerSubmitRequest implements Serializable {
     private String t_city;
 
     @JsonProperty("tcity")
-    private String tcity;
+    private String tcity = "";
 
     @JsonProperty("t_district")
     private String t_district;
 
     @JsonProperty("tdistrict")
-    private String tdistrict;
+    private String tdistrict = "";
 
     @JsonProperty("t_street")
     private String t_street;
 
     @JsonProperty("sales_tposition2")
-    private String sales_tposition2;
+    private String sales_tposition2 = "";
 
     @JsonProperty("tposition2")
-    private String tposition2;
+    private String tposition2 = "";
 
     @JsonProperty("tposition_name2")
-    private String tposition_name2;
+    private String tposition_name2 = "";
 
     @JsonProperty("sales_tposition")
-    private String sales_tposition;
+    private String sales_tposition = "";
 
     @JsonProperty("tposition")
-    private String tposition;
+    private String tposition = "";
 
     @JsonProperty("tposition_name")
-    private String tposition_name;
+    private String tposition_name = "";
 
     @JsonProperty("tcustomerno")
-    private String tcustomerno;
+    private String tcustomerno = "";
 
     @JsonProperty("tworkrange")
-    private String tworkrange;
+    private String tworkrange = "";
 
     @JsonProperty("tcompanymoney")
-    private String tcompanymoney;
+    private String tcompanymoney = "";
 
     @JsonProperty("tmoneytype")
-    private String tmoneytype;
+    private String tmoneytype = "";
 
     @JsonProperty("tcompanyname")
-    private String tcompanyname;
+    private String tcompanyname = "";
 
     @JsonProperty("tcompanynumber")
-    private String tcompanynumber;
+    private String tcompanynumber = "";
 
     @JsonProperty("tcompanylimitdate")
-    private String tcompanylimitdate;
+    private String tcompanylimitdate = "";
 
     @JsonProperty("tfzname")
-    private String tfzname;
+    private String tfzname = "";
 
     @JsonProperty("tfztype")
-    private String tfztype;
+    private String tfztype = "";
 
     @JsonProperty("tfzstartdate")
-    private String tfzstartdate;
+    private String tfzstartdate = "";
 
     @JsonProperty("tfzlimitdate")
-    private String tfzlimitdate;
+    private String tfzlimitdate = "";
 
     @JsonProperty("tfzcode")
-    private String tfzcode;
+    private String tfzcode = "";
 
     @JsonProperty("tbr_beneficiaryName")
-    private String tbr_beneficiaryName;
+    private String tbr_beneficiaryName = "";
 
     @JsonProperty("tbr_beneficiaryIdentifyType")
-    private String tbr_beneficiaryIdentifyType;
+    private String tbr_beneficiaryIdentifyType = "";
 
     @JsonProperty("tbr_beneficiaryIdentifyCode")
-    private String tbr_beneficiaryIdentifyCode;
+    private String tbr_beneficiaryIdentifyCode = "";
 
     @JsonProperty("tbr_IdentifyStartPeriod")
-    private String tbr_IdentifyStartPeriod;
+    private String tbr_IdentifyStartPeriod = "";
 
     @JsonProperty("tbr_IdentifyValidityPeriod")
-    private String tbr_IdentifyValidityPeriod;
+    private String tbr_IdentifyValidityPeriod = "";
 
     @JsonProperty("tbr_beneficiaryAddress")
-    private String tbr_beneficiaryAddress;
+    private String tbr_beneficiaryAddress = "";
 
     @JsonProperty("tbr_beneficiarymethod")
-    private String tbr_beneficiarymethod;
+    private String tbr_beneficiarymethod = "";
 
     @JsonProperty("tbr_beneficiaryaccountfor")
-    private String tbr_beneficiaryaccountfor;
+    private String tbr_beneficiaryaccountfor = "";
 
     @JsonProperty("tcontrollerName")
-    private String tcontrollerName;
+    private String tcontrollerName = "";
 
     @JsonProperty("tcontrollerIdentifyType")
-    private String tcontrollerIdentifyType;
+    private String tcontrollerIdentifyType = "";
 
     @JsonProperty("tcontrollerIdentifyCode")
-    private String tcontrollerIdentifyCode;
+    private String tcontrollerIdentifyCode = "";
 
     @JsonProperty("tcontrollerStartPeriod")
-    private String tcontrollerStartPeriod;
+    private String tcontrollerStartPeriod = "";
 
     @JsonProperty("tcontrollerValidityPeriod")
-    private String tcontrollerValidityPeriod;
+    private String tcontrollerValidityPeriod = "";
 
     @JsonProperty("unitproperties")
-    private String unitproperties;
+    private String unitproperties = "";
 
     @JsonProperty("holderandcomrelation")
-    private String holderandcomrelation;
-
-    @JsonProperty("itemName")
-    private String itemName;
-
-    @JsonProperty("kindName")
-    private String kindName;
-
-    @JsonProperty("chargingPostKindCode")
-    private String chargingPostKindCode;
-
-    @JsonProperty("chargingPostItemNo")
-    private String chargingPostItemNo;
-
-    @JsonProperty("chargingPostType")
-    private String chargingPostType;
-
-    @JsonProperty("chargingPostCode")
-    private String chargingPostCode;
-
-    @JsonProperty("chargingPostDate")
-    private String chargingPostDate;
-
-    @JsonProperty("chargingPostYearLimit")
-    private String chargingPostYearLimit;
-
-    @JsonProperty("chargingPostAddress")
-    private String chargingPostAddress;
+    private String holderandcomrelation = "";
+
+//    @JsonProperty("itemName")
+//    private String itemName;
+//
+//    @JsonProperty("kindName")
+//    private String kindName;
+//
+//    @JsonProperty("chargingPostKindCode")
+//    private String chargingPostKindCode;
+//
+//    @JsonProperty("chargingPostItemNo")
+//    private String chargingPostItemNo;
+//
+//    @JsonProperty("chargingPostType")
+//    private String chargingPostType;
+//
+//    @JsonProperty("chargingPostCode")
+//    private String chargingPostCode;
+//
+//    @JsonProperty("chargingPostDate")
+//    private String chargingPostDate;
+//
+//    @JsonProperty("chargingPostYearLimit")
+//    private String chargingPostYearLimit;
+//
+//    @JsonProperty("chargingPostAddress")
+//    private String chargingPostAddress;
 
     @JsonProperty("polcyNo")
-    private String polcyNo;
-
-    @JsonProperty("car_check_reason")
-    private String car_check_reason;
-
-    @JsonProperty("RENEWAL_FLAG")
-    private String RENEWAL_FLAG;
-
-    @JsonProperty("car_checker")
-    private String car_checker;
-
-    @JsonProperty("car_check_time")
-    private String car_check_time;
-
-    @JsonProperty("car_check_record")
-    private String car_check_record;
-
-    @JsonProperty("car_situation")
-    private String car_situation;
+    private String polcyNo = "";
+
+//    @JsonProperty("car_check_reason")
+//    private String car_check_reason;
+//
+//    @JsonProperty("RENEWAL_FLAG")
+//    private String RENEWAL_FLAG;
+//
+//    @JsonProperty("car_checker")
+//    private String car_checker;
+//
+//    @JsonProperty("car_check_time")
+//    private String car_check_time;
+//
+//    @JsonProperty("car_check_record")
+//    private String car_check_record;
+//
+//    @JsonProperty("car_situation")
+//    private String car_situation;
+
+    @JsonProperty("optionsRadios1")
+    private String optionsRadios1 = "2";
 
     @JsonProperty("isBusiness_to_not")
-    private String isBusiness_to_not;
+    private String isBusiness_to_not = "0";
 
     @JsonProperty("optionsRadios3")
-    private String optionsRadios3;
+    private String optionsRadios3 = "0";
 
     @JsonProperty("SECONDHAND_CAR_FLAG")
-    private String SECONDHAND_CAR_FLAG;
+    private String SECONDHAND_CAR_FLAG = "0";
 
     @JsonProperty("SECONDHAND_CAR_PRICE")
-    private String SECONDHAND_CAR_PRICE;
+    private String SECONDHAND_CAR_PRICE = "";
 
     @JsonProperty("RESCUE_CARD_TYPE")
-    private String RESCUE_CARD_TYPE;
+    private String RESCUE_CARD_TYPE = "OEC";
 
     @JsonProperty("LOAN_STATUS")
-    private String LOAN_STATUS;
+    private String LOAN_STATUS = "0";
+
+    @JsonProperty("RELATION_NO_BI")
+    private String RELATION_NO_BI = "";
 
     @JsonProperty("fixed_parkiing")
-    private String fixed_parkiing;
+    private String fixed_parkiing = "0";
 
     @JsonProperty("RESCUE_CARD")
-    private String RESCUE_CARD;
+    private String RESCUE_CARD = "TYPE0006";
 
     @JsonProperty("AGRICULTURE_RELATED")
-    private String AGRICULTURE_RELATED;
+    private String AGRICULTURE_RELATED = "00";
 
     @JsonProperty("PAY_MODE")
-    private String PAY_MODE;
+    private String PAY_MODE = "2";
 
     @JsonProperty("AREA_CODE")
-    private String AREA_CODE;
+    private String AREA_CODE = "";
 
     @JsonProperty("REGISTER_AREA")
-    private String REGISTER_AREA;
+    private String REGISTER_AREA = "";
 
     @JsonProperty("ARGUESOLUTION")
-    private String ARGUESOLUTION;
+    private String ARGUESOLUTION = "1";
 
     @JsonProperty("ARBITBOARD_NAME")
-    private String ARBITBOARD_NAME;
+    private String ARBITBOARD_NAME = "";
 
     @JsonProperty("firstbeneengaged")
-    private String firstbeneengaged;
+    private String firstbeneengaged = "0";
 
     @JsonProperty("t_iselec_comcode")
-    private String t_iselec_comcode;
+    private String t_iselec_comcode = "";
 
     @JsonProperty("t_iselec_comcode_hubei")
-    private String t_iselec_comcode_hubei;
+    private String t_iselec_comcode_hubei = "1";
 
     @JsonProperty("t_iselec_comcode_back")
-    private String t_iselec_comcode_back;
+    private String t_iselec_comcode_back = "1";
 
     @JsonProperty("proElecDisable")
-    private String proElecDisable;
+    private String proElecDisable = "1";
 
     @JsonProperty("PersonalElecInvoice")
-    private String PersonalElecInvoice;
+    private String PersonalElecInvoice = "1";
 
     @JsonProperty("proposaltype")
-    private String proposaltype;
+    private String proposaltype = "1";
 
     @JsonProperty("ownPrintElectronicCI")
-    private String ownPrintElectronicCI;
+    private String ownPrintElectronicCI = "0";
 
     @JsonProperty("ownPrintElectronicBI")
-    private String ownPrintElectronicBI;
+    private String ownPrintElectronicBI = "0";
 
-    @JsonProperty("printtype")
-    private String printtype;
+//    @JsonProperty("printtype")
+//    private String printtype = "1";
 
     @JsonProperty("printtype_ci")
-    private String printtype_ci;
+    private String printtype_ci = "1";
 
     @JsonProperty("auto_uw")
-    private String auto_uw;
+    private String auto_uw = "1";
 
     @JsonProperty("promotesaleplanid")
-    private String promotesaleplanid;
+    private String promotesaleplanid = "";
 
     @JsonProperty("APPROVER_COMMENTS")
-    private String APPROVER_COMMENTS;
+    private String APPROVER_COMMENTS = "";
 
     @JsonProperty("remark")
-    private String remark;
+    private String remark = "";
 
     @JsonProperty("visaType")
-    private String visaType;
+    private String visaType = "026";
 
     @JsonProperty("vat_taxno")
-    private String vat_taxno;
+    private String vat_taxno = "";
 
     @JsonProperty("vat_account")
-    private String vat_account;
+    private String vat_account = "";
 
     @JsonProperty("vat_address")
-    private String vat_address;
+    private String vat_address = "";
 
     @JsonProperty("vat_telephon")
-    private String vat_telephon;
+    private String vat_telephon = "";
 
     @JsonProperty("vat_bank")
-    private String vat_bank;
+    private String vat_bank = "";
 
     @JsonProperty("vat_bankname")
-    private String vat_bankname;
+    private String vat_bankname = "";
 
     @JsonProperty("vat_bankcode")
-    private String vat_bankcode;
+    private String vat_bankcode = "";
 
     @JsonProperty("vat_searchInput")
-    private String vat_searchInput;
+    private String vat_searchInput = "";
 
     @JsonProperty("codecode")
-    private String codecode;
+    private String codecode = "";
 
     @JsonProperty("codecname_name")
-    private String codecname_name;
+    private String codecname_name = "";
 
     @JsonProperty("vat_searchInput_astant")
-    private String vat_searchInput_astant;
+    private String vat_searchInput_astant = "";
 
+    @JsonProperty("clauses")
     private List<ClauseDTO> clauses;
 
     @JsonProperty("quotationNo")
     private String quotationNo;
 
     @JsonProperty("isNext")
-    private String isNext;
+    private String isNext = "";
 
     @JsonProperty("fullcomcode")
     private String fullcomcode;
 
     @JsonProperty("riskflag")
-    private String riskflag;
+    private String riskflag = "";
 
     @JsonProperty("qsn")
-    private String qsn;
+    private String qsn = "";
 
     @JsonProperty("answer")
-    private String answer;
+    private String answer = "";
 
     @Data
     public static class ClauseDTO implements Serializable {

+ 2 - 0
tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/entity/Response/HtCrawlerCarQueryResponse.java

@@ -40,6 +40,8 @@ public class HtCrawlerCarQueryResponse implements Serializable {
          *
          */
         private String riskcode;
+        private String Riskcode;
+
 
         /**
          *

+ 9 - 0
tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/entity/Response/HtCrawlerQuoteResponse.java

@@ -887,4 +887,13 @@ public class HtCrawlerQuoteResponse implements Serializable {
             }
         }
     }
+
+    @Data
+    public static class DataErrDTO implements Serializable {
+        @Serial
+        private static final long serialVersionUID = -3583675610947083415L;
+        private String erroeInfo;
+        private String erroeType;
+        private String errrorFlag;
+    }
 }

+ 1 - 1
tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/entity/Response/HtCrawlerSubmitResponse.java

@@ -7,7 +7,7 @@ import java.io.Serializable;
 import java.util.List;
 
 /**
- * @description: 华泰财险 提交核保 返回参数
+ * @description: 华泰财险 提交核保 返回参数  核保不通过的
  * @author: shenwd
  * @date: 2025/5/6 15:32
  **/

+ 101 - 0
tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/entity/Response/HtCrawlerSubmitRightResponse.java

@@ -0,0 +1,101 @@
+package com.jzg.quotation.huatai.crawler.entity.Response;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @description: 华泰财险 提交核保 返回参数  核保通过的
+ * @author: shenwd
+ * @date: 2025/5/6 15:32
+ **/
+@Data
+public class HtCrawlerSubmitRightResponse implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 7831555461770877473L;
+
+    private String isPassHB;
+    private MsgDTO MSG;
+    private String quo;
+    private String syProposalno;
+    private String jqProposalno;
+    private String perHtmlMsg;
+    private String perMSG;
+    private String wethFlag;
+    private String flag;
+    private String iscombinationproductflag;
+    private String isNonCarProduct;
+    private List<Object> noncarInfo;
+    private String page;
+    private String htmlMsgTeam;
+
+    @Data
+    public static class MsgDTO implements Serializable {
+        @Serial
+        private static final long serialVersionUID = -3257790456189986455L;
+
+        private String applicant;
+        private String biObtainuploadErrorMsg;
+        private String ciObtainuploadErrorMsg;
+        private String license;
+        private List<NoCarRecommendDTO> noCarRecommend;
+        private String noNeedSalesFace;
+        private String passMessageBi;
+        private String passMessageCi;
+        private String proposalBi;
+        private String proposalCi;
+        private String quotationNo;
+        private String riskResponse;
+
+        @Data
+        public static class NoCarRecommendDTO {
+            @Serial
+            private static final long serialVersionUID = -3257790456123986455L;
+            private String custtypename;
+            private String procode;
+            private String proname;
+            private String url;
+        }
+    }
+//    {
+//        "isPassHB" : "Y",
+//            "MSG" : {
+//        "applicant" : "要少华",
+//                "biObtainuploadErrorMsg" : "",
+//                "ciObtainuploadErrorMsg" : "",
+//                "license" : "晋AJ9668",
+//                "noCarRecommend" : [ {
+//            "custtypename" : "被保险人/投保人",
+//                    "procode" : "2444",
+//                    "proname" : "爱家120",
+//                    "url" : "http://10.1.1.64:9099/FrameWork/loginforeatoken.html"
+//        }, {
+//            "custtypename" : "被保险人/投保人",
+//                    "procode" : "4015",
+//                    "proname" : "怡家100",
+//                    "url" : "http://10.1.1.64:9099/FrameWork/loginforeatoken.html"
+//        } ],
+//        "noNeedSalesFace" : "",
+//                "passMessageBi" : "",
+//                "passMessageCi" : "符合自动核保规则:核保通过 ",
+//                "proposalBi" : "",
+//                "proposalCi" : "2270910022026056589",
+//                "quotationNo" : "",
+//                "riskResponse" : ""
+//    },
+//        "quo" : "B270926060364392222",
+//            "syProposalno" : "",
+//            "jqProposalno" : "2270910022026056589",
+//            "perHtmlMsg" : "<p><a target='_blank' style='cursor:pointer' onClick=shankHandsPerson('http://10.1.1.64:9099/FrameWork/loginforeatoken.html','2444')>1、2444-爱家120 被保险人/投保人</a></p><p><a target='_blank' style='cursor:pointer' onClick=shankHandsPerson('http://10.1.1.64:9099/FrameWork/loginforeatoken.html','4015')>2、4015-怡家100 被保险人/投保人</a></p>",
+//            "perMSG" : "",
+//            "wethFlag" : "N",
+//            "flag" : "",
+//            "iscombinationproductflag" : "1",
+//            "isNonCarProduct" : "N",
+//            "noncarInfo" : [ null ],
+//        "page" : "",
+//            "htmlMsgTeam" : "<h4><strong style='font-family:微软雅黑'>下发修改意见</strong></h4><span style='font-family:微软雅黑'><span style='font-size:14px;font-weight:bold'>交强险:</span>符合自动核保规则:核保通过 </span><br></span><br><br>"
+//    }
+}

+ 3 - 0
tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/entity/dto/LoginDTO.java

@@ -11,4 +11,7 @@ import lombok.Data;
 @Data
 public class LoginDTO extends LoginBase {
     private String comcode;
+    private String useridname;
+    private String dlrCode;
+    private String dlxyCode;
 }

+ 10 - 0
tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/entity/po/HtCrawlerOrder.java

@@ -23,4 +23,14 @@ public class HtCrawlerOrder {
      * 华泰 报价单号
      */
     private String quotationRelaNo;
+
+    /**
+     * 核保额外需要的参数  交强评分
+     */
+    private String ciCategory;
+
+    /**
+     * 核保额外需要的参数  交强评分
+     */
+    private String biCategory;
 }

+ 3 - 1
tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/service/HuaTaiCrawlerRequest.java

@@ -3,11 +3,13 @@ package com.jzg.quotation.huatai.crawler.service;
 import com.jzg.quotation.commons.service.QuotationCrawlerBaseService;
 import com.jzg.quotation.huatai.crawler.entity.dto.LoginDTO;
 
+import java.util.Map;
+
 /**
  * @description: 华泰爬虫报价请求接口
  * @author: shenwd
  * @date: 2025/4/15 08:55
  **/
 public interface HuaTaiCrawlerRequest extends QuotationCrawlerBaseService {
-    void login(LoginDTO loginDTO);
+    Map<String, Object> login(LoginDTO loginDTO);
 }

ファイルの差分が大きいため隠しています
+ 940 - 34
tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/service/Impl/HuaTaiCrawlerRequestImpl.java


+ 679 - 0
tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/util/CookieUtils.java

@@ -0,0 +1,679 @@
+package com.jzg.quotation.huatai.crawler.util;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.jetbrains.annotations.NotNull;
+import org.springframework.http.*;
+import org.springframework.http.client.SimpleClientHttpRequestFactory;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.client.RestTemplate;
+
+import javax.net.ssl.*;
+import java.net.HttpURLConnection;
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.security.cert.X509Certificate;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+public class CookieUtils {
+    private final ObjectMapper objectMapper = new ObjectMapper();
+
+    private final String baseUrl = "https://cspxp.pc.ehuatai.com/htcsp";
+
+    // 车辆信息
+    private String licenseNo;
+    private String vin;
+    private String registerDate;
+    private String energyType;
+    private String modelCName;
+    private String engineNo;
+    private String seat;
+    private String purchasePrice;
+    private String vehicleUse;
+    private String limitLoad;
+    private String cartype;
+    private String completeKerbMass;
+    private String cimodelclass;
+    private String motorTypeCode;
+    private String motorUsageTypeCode;
+    private String motortypecode;
+
+    // 归属信息
+    private String ywlyName;
+    private String xstxCode;
+    private String dlrCode;
+    private String dlxyCode;
+    private Map<String, Object> gsInfo = new HashMap<>();
+
+    // cookies
+    private String jsessionId = "";
+    private String bigIpCookie = "";
+
+    // 特殊账号列表
+    private final List<String> specialUsers = Arrays.asList(
+            "EA27000180", "EA27000401", "EA27000098", "EA27000076",
+            "EA27000385", "EA27000336", "EA27000393", "EA27000182",
+            "EA27000381", "EA27000394", "XN9279003"
+    );
+
+    private String quotationNo = "";
+
+    public Map<String, Object> mainFlow(String username, String pwd, String comCode,
+                                        String useridName, String dlrCode, String dlxyCode, int maxQuoteNum) {
+
+        RestTemplate restTemplate = getRestTemplate();
+
+
+        try {
+            // 初始化车辆信息(示例数据)
+            initCarInfo();
+
+            // 登录
+            Map<String, Object> loginResult = login(username, pwd, comCode);
+            if (loginResult.get("code") != null && (int) loginResult.get("code") != 200) {
+                Map<String, Object> result1 = new HashMap<>();
+                result1.put("code", 400);
+                result1.put("message", "用户名、密码错误");
+                Map<String, Object> other = new HashMap<>();
+                other.put("maxQuoteNum", maxQuoteNum);
+                result1.put("other", other);
+                return result1;
+            }
+
+            Map<String, Object> cookies = (Map<String, Object>) loginResult.get("cookies");
+            this.jsessionId = (String) cookies.get("JSESSIONID");
+            this.bigIpCookie = (String) cookies.get("BIGipServerypKFOfHGLAALYYraCSdVMw");
+
+            // 如果不是特殊账号,获取归属信息
+            if (!specialUsers.contains(username)) {
+                try {
+                    getGuishu(comCode, useridName, dlrCode, dlxyCode);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+
+            Map<String, Object> resultMap = new HashMap<>();
+            resultMap.put("code", 200);
+            resultMap.put("message", "success");
+            resultMap.put("cookies", "JSESSIONID="+this.jsessionId+"; BIGipServerypKFOfHGLAALYYraCSdVMw="+this.bigIpCookie+";");
+            resultMap.put("comCode", loginResult.get("comcode"));
+            resultMap.put("gsInfo", gsInfo);
+            return resultMap;
+        } catch (Exception e) {
+            Map<String, Object> result2 = new HashMap<>();
+            result2.put("code", 500);
+            result2.put("message", e.getMessage());
+            return result2;
+        }
+    }
+
+    @NotNull
+    public static RestTemplate getRestTemplate() {
+        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory() {
+            @Override
+            protected void prepareConnection(HttpURLConnection connection, String httpMethod) throws java.io.IOException {
+                if (connection instanceof HttpsURLConnection) {
+                    try {
+                        TrustManager[] trustAllCerts = new TrustManager[]{
+                                new X509TrustManager() {
+                                    @Override
+                                    public X509Certificate[] getAcceptedIssuers() {
+                                        return new X509Certificate[0];
+                                    }
+
+                                    @Override
+                                    public void checkClientTrusted(X509Certificate[] certs, String authType) {
+                                    }
+
+                                    @Override
+                                    public void checkServerTrusted(X509Certificate[] certs, String authType) {
+                                    }
+                                }
+                        };
+                        SSLContext sslContext = SSLContext.getInstance("TLS");
+                        sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
+                        ((HttpsURLConnection) connection).setSSLSocketFactory(sslContext.getSocketFactory());
+                        ((HttpsURLConnection) connection).setHostnameVerifier(new HostnameVerifier() {
+                            @Override
+                            public boolean verify(String hostname, SSLSession session) {
+                                return true;
+                            }
+                        });
+
+                    } catch (Exception e) {
+                        throw new RuntimeException(e);
+                    }
+                }
+                super.prepareConnection(connection, httpMethod);
+            }
+        };
+
+        Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("39.98.41.104", 2025));
+        factory.setProxy(proxy);
+
+        RestTemplate restTemplate = new RestTemplate(factory);
+        return restTemplate;
+    }
+
+    private void initCarInfo() {
+        Map<String, Object> dddd = new HashMap<>();
+        dddd.put("frameNo", "LM8F7J3B0SC078844");
+        dddd.put("transferFlagBi", false);
+        dddd.put("transferFlag", false);
+        dddd.put("cartype", "K31");
+        dddd.put("licenseNo", "晋AFS6726");
+        dddd.put("newEnergy", true);
+        dddd.put("modelcname", "赛力斯SKE6520SSHEVA6S插电式增程混合动力多用途乘用车");
+        dddd.put("purchasePrice", "469800");
+        dddd.put("vinNo", "LM8F7J3B0SC078844");
+        dddd.put("noLicenseFlag", false);
+        dddd.put("enginedesc", "1.496");
+        dddd.put("powerScale", "118");
+        dddd.put("modelCode", "AIAACD0022");
+        dddd.put("completeKerbMass", "2690");
+        dddd.put("familyName", "问界M9");
+        dddd.put("importFlag", "越野车类");
+        dddd.put("loanStatus", false);
+        dddd.put("property", "1");
+        dddd.put("caryear", "202503");
+        dddd.put("issueDate", "2025-06-19");
+        dddd.put("registerDate", "2025-06-19");
+        dddd.put("engineNo", "25634769");
+        dddd.put("brandName", "AITO问界");
+        dddd.put("usedCar", false);
+        dddd.put("licenseTypeCode", "02");
+        dddd.put("vehicleUse", "05");
+        dddd.put("carnature", "02");
+        dddd.put("seatCount", "5");
+        dddd.put("energyType", "1");
+        dddd.put("cimodelclass", "A0");
+        dddd.put("outOfInsurance", false);
+        dddd.put("vehicleweight", "3165");
+
+        this.licenseNo = (String) dddd.get("licenseNo");
+        this.vin = (String) dddd.get("vinNo");
+        this.registerDate = (String) dddd.get("registerDate");
+        this.energyType = (String) dddd.get("energyType");
+        this.modelCName = (String) dddd.get("modelcname");
+        this.engineNo = (String) dddd.get("engineNo");
+        this.seat = (String) dddd.get("seatCount");
+        this.purchasePrice = (String) dddd.get("purchasePrice");
+        this.vehicleUse = (String) dddd.get("vehicleUse");
+        this.limitLoad = (String) dddd.get("limitLoad");
+        this.cartype = (String) dddd.get("cartype");
+        this.completeKerbMass = (String) dddd.get("completeKerbMass");
+        this.cimodelclass = (String) dddd.get("cimodelclass");
+
+        if ("04".equals(this.vehicleUse)) {
+            this.motorTypeCode = "H0";
+            this.motorUsageTypeCode = "9D";
+        } else if ("05".equals(this.vehicleUse)) {
+            this.motorTypeCode = "A0";
+            this.motorUsageTypeCode = "8A";
+        } else if ("06".equals(this.vehicleUse)) {
+            if ("A0".equals(this.cimodelclass)) {
+                this.motorTypeCode = "A0";
+                this.motorUsageTypeCode = "8C";
+            } else if ("A1".equals(this.cimodelclass)) {
+                this.motorTypeCode = "H0";
+                this.motorUsageTypeCode = "8D";
+            }
+        } else if ("07".equals(this.vehicleUse)) {
+            if ("A0".equals(this.cimodelclass)) {
+                this.motorTypeCode = "A0";
+                this.motorUsageTypeCode = "8B";
+            } else if ("A1".equals(this.cimodelclass)) {
+                this.motorTypeCode = "H0";
+                this.motorUsageTypeCode = "8D";
+            }
+        } else if ("08".equals(this.vehicleUse)) {
+            this.motorTypeCode = "H0";
+            this.motorUsageTypeCode = "8D";
+        }
+        this.motortypecode = this.motorTypeCode;
+    }
+
+    private HttpHeaders buildHeadersWithCookie() {
+        HttpHeaders headers = new HttpHeaders();
+        headers.set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36");
+        headers.set("Accept", "*/*");
+        headers.set("Accept-Language", "zh-CN,zh;q=0.9");
+        headers.set("Connection", "keep-alive");
+        headers.set("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
+        headers.set("Origin", "https://cspxp.pc.ehuatai.com");
+        headers.set("Referer", "https://cspxp.pc.ehuatai.com/htcsp/ShakeHandsAction.do?cmd=menuControl&ip=172.16.100.27&host=9000&menuCode=car_001&messageClickType=&mesFlag=");
+        headers.set("X-Requested-With", "XMLHttpRequest");
+        String cookieStr = "JSESSIONID=" + jsessionId;
+        if (!bigIpCookie.isEmpty()) {
+            cookieStr += "; BIGipServerypKFOfHGLAALYYraCSdVMw=" + bigIpCookie;
+        }
+        headers.set("Cookie", cookieStr);
+        return headers;
+    }
+
+    private HttpHeaders buildHtmlHeadersWithCookie() {
+        HttpHeaders headers = new HttpHeaders();
+        headers.set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36");
+        headers.set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7");
+        headers.set("Accept-Language", "zh-CN,zh;q=0.9");
+        headers.set("Cache-Control", "no-cache");
+        headers.set("Connection", "keep-alive");
+        headers.set("Pragma", "no-cache");
+        headers.set("Upgrade-Insecure-Requests", "1");
+        String cookieStr = "JSESSIONID=" + jsessionId;
+        if (!bigIpCookie.isEmpty()) {
+            cookieStr += "; BIGipServerypKFOfHGLAALYYraCSdVMw=" + bigIpCookie;
+        }
+        headers.set("Cookie", cookieStr);
+        return headers;
+    }
+
+    private void getGuishu(String comCode, String useridName, String dlrCode, String dlxyCode) throws Exception {
+        System.out.println("开始获取归属树");
+        RestTemplate restTemplate = getRestTemplate();
+        HttpHeaders headers = buildHeadersWithCookie();
+        MultiValueMap<String, String> data = new LinkedMultiValueMap<>();
+        data.add("comcode", comCode);
+        HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(data, headers);
+        ResponseEntity<String> response = restTemplate.exchange(
+                baseUrl + "/SaleInfoAction.do?cmd=initSaledUser", HttpMethod.POST, entity, String.class);
+        System.out.println("归属树用户列表:initSaledUser:");
+        String useridValue = "";
+        String foundUseridName = "";
+        List<Map<String, Object>> userList = objectMapper.readValue(response.getBody(), List.class);
+        System.out.println("归属树用户列表:" + userList);
+        for (Map<String, Object> item : userList) {
+            if (useridName.equals(item.get("codecname"))) {
+                foundUseridName = (String) item.get("codecname");
+                useridValue = (String) item.get("codecode");
+                break;
+            }
+        }
+
+        headers = buildHeadersWithCookie();
+        data = new LinkedMultiValueMap<>();
+        data.add("comcode", comCode);
+        entity = new HttpEntity<>(data, headers);
+        ResponseEntity<String> respSalesys = restTemplate.exchange(
+                baseUrl + "/SaleInfoAction.do?cmd=initSalesys", HttpMethod.POST, entity, String.class);
+        Map<String, Object> salesysMap = objectMapper.readValue(respSalesys.getBody(), HashMap.class);
+        System.out.println("归属树用户列表:salesysMap" + salesysMap);
+        String channelOrign = (String) salesysMap.get("codecode");
+        String newChannelOrign = (String) salesysMap.get("newcodecode");
+
+        headers = buildHtmlHeadersWithCookie();
+        HttpEntity<String> getEntity = new HttpEntity<>(headers);
+        ResponseEntity<String> respMenu = restTemplate.exchange(
+                baseUrl + "/ShakeHandsAction.do?cmd=menuControl&ip=172.16.100.27&host=9000&menuCode=car_001&messageClickType=&mesFlag=",
+                HttpMethod.GET, getEntity, String.class);
+        System.out.println("归属树用户列表:menuControl:");
+        String comcodeGbdistrictcode = "";
+        String comcodeName = "";
+        Pattern pattern = Pattern.compile("var comPanyJson= (.*?);");
+        Matcher matcher = pattern.matcher(respMenu.getBody());
+        if (matcher.find()) {
+            String jsonStr = matcher.group(1);
+            List<Map<String, Object>> comPanyJsonList = objectMapper.readValue(jsonStr, List.class);
+            for (Map<String, Object> zzz : comPanyJsonList) {
+                if (comCode.equals(zzz.get("codecode"))) {
+                    comcodeGbdistrictcode = (String) zzz.get("codetype");
+                    comcodeName = (String) zzz.get("codecname");
+                    break;
+                }
+            }
+        }
+
+        headers = buildHeadersWithCookie();
+        data = new LinkedMultiValueMap<>();
+        data.add("comcode", comCode);
+        data.add("codeCode", channelOrign);
+        entity = new HttpEntity<>(data, headers);
+        restTemplate.exchange(baseUrl + "/SaleInfoAction.do?cmd=initSelectSalesysall", HttpMethod.POST, entity, String.class);
+        System.out.println("归属树用户列表:initSelectSalesysall");
+        headers = buildHtmlHeadersWithCookie();
+        getEntity = new HttpEntity<>(headers);
+        restTemplate.exchange(
+                baseUrl + "/ShakeHandsAction.do?cmd=menuControl&ip=172.16.100.27&host=9000&menuCode=car_001&messageClickType=&mesFlag=",
+                HttpMethod.GET, getEntity, String.class);
+
+        this.ywlyName = "代理业务";
+        this.xstxCode = "0401";
+        List<Map<String, Object>> codelist = new ArrayList<>();
+        codelist.add(createCodeItem("直接业务", "0"));
+        codelist.add(createCodeItem("代理业务", "1"));
+        codelist.add(createCodeItem("经纪业务", "4"));
+        codelist.add(createCodeItem("电销/网销", "6"));
+        for (Map<String, Object> zzz : codelist) {
+            if (this.ywlyName.equals(zzz.get("codecname"))) {
+                this.ywlyName = (String) zzz.get("codecode");
+                break;
+            }
+        }
+
+        this.dlrCode = dlrCode;
+        this.dlxyCode = dlxyCode;
+
+        headers = new HttpHeaders();
+        headers.set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7");
+        headers.set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8");
+        headers.set("Cache-Control", "no-cache");
+        headers.set("Connection", "keep-alive");
+        headers.set("Content-Type", "application/x-www-form-urlencoded");
+        headers.set("Origin", "https://cspxp.pc.ehuatai.com");
+        headers.set("Pragma", "no-cache");
+        headers.set("Referer", "https://cspxp.pc.ehuatai.com/htcsp/ShakeHandsAction.do?cmd=menuControl&ip=172.16.100.27&host=9000&menuCode=car_001&messageClickType=&mesFlag=");
+        headers.set("Upgrade-Insecure-Requests", "1");
+        headers.set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36");
+        String cookieStr = "JSESSIONID=" + jsessionId;
+        if (!bigIpCookie.isEmpty()) {
+            cookieStr += "; BIGipServerypKFOfHGLAALYYraCSdVMw=" + bigIpCookie;
+        }
+        headers.set("Cookie", cookieStr);
+
+        data = new LinkedMultiValueMap<>();
+        data.add("isTeamCarFlag", "");
+        data.add("teamcarmodelcode", "");
+        data.add("teamcarmodelname", "");
+        data.add("salemdea", "");
+        data.add("PRPDCODJson", "");
+        data.add("state", "");
+        data.add("comCodeInAgentsFlag", "0");
+        data.add("wangdianNameFlag", "0");
+        data.add("wangdianNameHid", "0");
+        data.add("licenseNo", "");
+        data.add("policyBI", "");
+        data.add("policyCI", "");
+        data.add("policyStatusBI", "");
+        data.add("policyStatusCI", "");
+        data.add("showEmploy", "");
+        data.add("showEmployControl", "");
+        data.add("businessature", "");
+        data.add("comcode", comCode);
+        data.add("comcode_name", comcodeName);
+        data.add("comcode_gbcode", comcodeGbdistrictcode);
+        data.add("userid", useridValue);
+        data.add("userid_name", foundUseridName);
+        data.add("businessNature", this.ywlyName);
+        data.add("selectsalesys", "");
+        data.add("salesys", this.xstxCode);
+        data.add("channel", "04");
+        data.add("channel_orign", channelOrign);
+        data.add("newChannel", "saleSysDl");
+        data.add("newChannel_orign", newChannelOrign);
+        data.add("agentno_dl", this.dlrCode);
+        data.add("agreementno_dl", this.dlxyCode);
+        data.add("agentno_fdl", "");
+        data.add("agreementno_fdl", "");
+        data.add("agentno_jj", "");
+        data.add("agreementno_jj", "");
+        data.add("teamcode_value", "");
+        data.add("teamcode_name", "");
+        data.add("systemfor", "");
+        data.add("usercodelifedot_text", "");
+        data.add("usercodelife_value", "");
+        data.add("usercodelife_name", "");
+        data.add("usercodelife_text", "");
+        data.add("phone_value", "");
+        data.add("phone_name", "");
+        data.add("carType", "baojia");
+        data.add("quotationNo", "");
+
+        entity = new HttpEntity<>(data, headers);
+        restTemplate.exchange(baseUrl + "/ShakeHandsAction.do?cmd=confirmUserVoByInitBySale", HttpMethod.POST, entity, String.class);
+        System.out.println("归属树用户列表:confirmUserVoByInitBySale");
+        gsInfo.put("userid_name", foundUseridName);
+        gsInfo.put("userid_value", useridValue);
+        gsInfo.put("comcode_gbdistrictcode", comcodeGbdistrictcode);
+        gsInfo.put("comcode_name", comcodeName);
+        gsInfo.put("businessnature_value", this.ywlyName);
+        gsInfo.put("salesys_value", this.xstxCode);
+        gsInfo.put("channel_orign", channelOrign);
+        gsInfo.put("newChannel_orign", newChannelOrign);
+    }
+
+    private Map<String, Object> createCodeItem(String name, String code) {
+        Map<String, Object> item = new HashMap<>();
+        item.put("codecname", name);
+        item.put("codecode", code);
+        return item;
+    }
+
+    private Map<String, Object> login(String uname, String pwd, String comCode) {
+        try {
+            getCk();
+
+            String comcode = getComcode(uname, comCode);
+            if (comcode == null) {
+                Map<String, Object> result = new HashMap<>();
+                result.put("code", 400);
+                result.put("message", "获取机构失败");
+                return result;
+            }
+
+            return doLogin(uname, pwd, comcode);
+        } catch (Exception e) {
+            Map<String, Object> result = new HashMap<>();
+            result.put("code", 500);
+            result.put("message", e.getMessage());
+            return result;
+        }
+    }
+
+    private HttpHeaders buildCommonHeaders() {
+        HttpHeaders headers = new HttpHeaders();
+        headers.set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36");
+        headers.set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7");
+        headers.set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8");
+        headers.set("Cache-Control", "no-cache");
+        headers.set("Pragma", "no-cache");
+        headers.set("Connection", "keep-alive");
+        headers.set("Upgrade-Insecure-Requests", "1");
+        return headers;
+    }
+
+    private HttpHeaders buildJsonHeaders() {
+        HttpHeaders headers = new HttpHeaders();
+        headers.set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36");
+        headers.set("Accept", "application/json, text/javascript, */*; q=0.01");
+        headers.set("Accept-Language", "zh-CN,zh;q=0.9");
+        headers.set("Cache-Control", "no-cache");
+        headers.set("Pragma", "no-cache");
+        headers.set("Connection", "keep-alive");
+        headers.set("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
+        headers.set("Origin", "https://cspxp.pc.ehuatai.com");
+        headers.set("Referer", "https://cspxp.pc.ehuatai.com/htcsp/");
+        headers.set("X-Requested-With", "XMLHttpRequest");
+        headers.set("Sec-Fetch-Dest", "empty");
+        headers.set("Sec-Fetch-Mode", "cors");
+        headers.set("Sec-Fetch-Site", "same-origin");
+        headers.set("sec-ch-ua", "\"Google Chrome\";v=\"143\", \"Chromium\";v=\"143\", \"Not A(Brand)\";v=\"24\"");
+        headers.set("sec-ch-ua-mobile", "?0");
+        headers.set("sec-ch-ua-platform", "\"Windows\"");
+        return headers;
+    }
+
+    private void getCk() {
+        RestTemplate restTemplate = getRestTemplate();
+        HttpHeaders headers = buildCommonHeaders();
+        HttpEntity<String> entity = new HttpEntity<>(headers);
+        ResponseEntity<String> response = restTemplate.exchange(
+                baseUrl + "/", HttpMethod.GET, entity, String.class);
+        extractCookies(response);
+
+        headers = buildCommonHeaders();
+        headers.set("Content-Type", "application/x-www-form-urlencoded");
+        MultiValueMap<String, String> data = new LinkedMultiValueMap<>();
+        data.add("ip", "cspxp.pc.ehuatai.com");
+        HttpEntity<MultiValueMap<String, String>> postEntity = new HttpEntity<>(data, headers);
+        ResponseEntity<String> postResp = restTemplate.exchange(
+                baseUrl + "/ShakeHandsAction.do?cmd=checkWeb", HttpMethod.POST, postEntity, String.class);
+        extractCookies(postResp);
+    }
+
+    private String getComcode(String uname, String comCode) {
+        RestTemplate restTemplate = getRestTemplate();
+        HttpHeaders headers = buildJsonHeaders();
+        MultiValueMap<String, String> data = new LinkedMultiValueMap<>();
+        data.add("username", uname);
+        HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(data, headers);
+        ResponseEntity<String> response = restTemplate.exchange(
+                baseUrl + "/ShakeHandsAction.do?cmd=getBranch", HttpMethod.POST, entity, String.class);
+        extractCookies(response);
+
+        Map<String, Object> decrypted = htDecrypt(response.getBody());
+        List<Map<String, Object>> comCodeList = (List<Map<String, Object>>) decrypted.get("comCodeList");
+
+        String comcode = null;
+        if (comCodeList != null) {
+            for (Map<String, Object> item : comCodeList) {
+                if (comCode.equals(item.get("comcode"))) {
+                    comcode = item.get("comcode") + "-" + item.get("comcname");
+                    break;
+                }
+            }
+            if (comcode == null && !comCodeList.isEmpty()) {
+                comcode = comCodeList.get(0).get("comcode") + "-" + comCodeList.get(0).get("comcname");
+            }
+        }
+
+        headers = buildJsonHeaders();
+        HttpEntity<String> emptyEntity = new HttpEntity<>(headers);
+        restTemplate.exchange(baseUrl + "/ShakeHandsAction.do?cmd=judgeCanForwardNewPage",
+                HttpMethod.POST, emptyEntity, String.class);
+
+        headers = buildJsonHeaders();
+        data = new LinkedMultiValueMap<>();
+        data.add("username", uname);
+        entity = new HttpEntity<>(data, headers);
+        restTemplate.exchange(baseUrl + "/ShakeHandsAction.do?cmd=getMac", HttpMethod.POST, entity, String.class);
+
+        headers = buildJsonHeaders();
+        data = new LinkedMultiValueMap<>();
+        data.add("username", uname);
+        data.add("customerIp", "cspxp.pc.ehuatai.com");
+        data.add("messageType", "01");
+        data.add("comcode", comcode);
+        entity = new HttpEntity<>(data, headers);
+        restTemplate.exchange(baseUrl + "/ShakeHandsAction.do?cmd=verificationFlag", HttpMethod.POST, entity, String.class);
+
+        headers = buildJsonHeaders();
+        data = new LinkedMultiValueMap<>();
+        data.add("userName", uname);
+        entity = new HttpEntity<>(data, headers);
+        restTemplate.exchange(baseUrl + "/ShakeHandsAction.do?cmd=getPrompt", HttpMethod.POST, entity, String.class);
+
+        return comcode;
+    }
+
+    private Map<String, Object> doLogin(String uname, String pwd, String comcode) throws Exception {
+        RestTemplate restTemplate = getRestTemplate();
+        HttpHeaders headers = buildJsonHeaders();
+        MultiValueMap<String, String> data = new LinkedMultiValueMap<>();
+        data.add("username", uname);
+        data.add("password", pwd);
+        data.add("ip", "csp.pc.ehuatai.com");
+        data.add("comcode", comcode);
+        data.add("mobile", "");
+        data.add("verificationCode", "");
+        data.add("weChatFlag", "");
+        HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(data, headers);
+        ResponseEntity<String> response = restTemplate.exchange(
+                baseUrl + "/ShakeHandsAction.do?cmd=checkUser", HttpMethod.POST, entity, String.class);
+        extractCookies(response);
+
+        headers = new HttpHeaders();
+        headers.set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7");
+        headers.set("Accept-Language", "zh-CN,zh;q=0.9");
+        headers.set("Cache-Control", "no-cache");
+        headers.set("Connection", "keep-alive");
+        headers.set("Content-Type", "application/x-www-form-urlencoded");
+        headers.set("Origin", "https://cspxp.pc.ehuatai.com");
+        headers.set("Pragma", "no-cache");
+        headers.set("Referer", "https://cspxp.pc.ehuatai.com/htcsp/ShakeHandsAction.do?cmd=exitLogin");
+        headers.set("Sec-Fetch-Dest", "document");
+        headers.set("Sec-Fetch-Mode", "navigate");
+        headers.set("Sec-Fetch-Site", "same-origin");
+        headers.set("Sec-Fetch-User", "?1");
+        headers.set("Upgrade-Insecure-Requests", "1");
+        headers.set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36");
+        headers.set("sec-ch-ua", "\"Google Chrome\";v=\"143\", \"Chromium\";v=\"143\", \"Not A(Brand)\";v=\"24\"");
+        headers.set("sec-ch-ua-mobile", "?0");
+        headers.set("sec-ch-ua-platform", "\"Windows\"");
+
+        data = new LinkedMultiValueMap<>();
+        data.add("username", uname);
+        data.add("password", pwd);
+        data.add("comcode", comcode);
+        data.add("verificationCode", "");
+        data.add("yanzhengtupianflag", "");
+        data.add("brownVerb", "143.0.0.0");
+        data.add("brownVern", "Chrome");
+        data.add("bindflag", "");
+        data.add("customerIp", "127.0.0.1");
+        data.add("customerCity", "未知");
+        data.add("userIsNowFlag", "");
+        data.add("sendNecessityIpt", "X");
+        data.add("wwaUserCode", "");
+        data.add("weChatFlag", "");
+        data.add("validStatus", "1");
+        entity = new HttpEntity<>(data, headers);
+        ResponseEntity<String> loginResp = restTemplate.exchange(
+                baseUrl + "/ShakeHandsAction.do?cmd=loginWelcom", HttpMethod.POST, entity, String.class);
+        extractCookies(loginResp);
+
+        Map<String, Object> result = new HashMap<>();
+        if (!loginResp.getBody().contains("请填写正确的用户名和密码")) {
+            Map<String, Object> cookies = new HashMap<>();
+            cookies.put("JSESSIONID", jsessionId);
+            cookies.put("BIGipServerypKFOfHGLAALYYraCSdVMw", bigIpCookie);
+            result.put("code", 200);
+            result.put("cookies", cookies);
+            result.put("comcode", comcode);
+            result.put("message", "登录成功");
+        } else {
+            result.put("code", 400);
+            result.put("message", "账号密码错误");
+        }
+        return result;
+    }
+
+    private void extractCookies(ResponseEntity<String> response) {
+        List<String> cookies = response.getHeaders().get("Set-Cookie");
+        if (cookies != null) {
+            for (String cookie : cookies) {
+                if (cookie.contains("JSESSIONID=")) {
+                    jsessionId = extractCookieValue(cookie, "JSESSIONID");
+                }
+                if (cookie.contains("BIGipServerypKFOfHGLAALYYraCSdVMw=")) {
+                    bigIpCookie = extractCookieValue(cookie, "BIGipServerypKFOfHGLAALYYraCSdVMw");
+                }
+            }
+        }
+    }
+
+    private String extractCookieValue(String cookieHeader, String name) {
+        Pattern pattern = Pattern.compile(name + "=([^;]+)");
+        Matcher matcher = pattern.matcher(cookieHeader);
+        if (matcher.find()) {
+            return matcher.group(1);
+        }
+        return "";
+    }
+
+    private Map<String, Object> htDecrypt(String jsonBody) {
+        try {
+            Map<String, Object> map = objectMapper.readValue(jsonBody, HashMap.class);
+            String accessToken = (String) map.get("accessToken");
+            String data = (String) map.get("data");
+            String aesKey = HuaTaiCryptUtil.RSADecrypt(accessToken);
+            String decrypted = HuaTaiCryptUtil.AESDecrypt(data, aesKey);
+            return objectMapper.readValue(decrypted, HashMap.class);
+        } catch (Exception e) {
+            return new HashMap<>();
+        }
+    }
+}

+ 115 - 0
tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/util/CryptoUtil.java

@@ -0,0 +1,115 @@
+package com.jzg.quotation.huatai.crawler.util;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.SecretKeySpec;
+import java.nio.charset.StandardCharsets;
+import java.security.KeyFactory;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.Base64;
+
+public class CryptoUtil {
+
+    private static final String RSA_PRIVATE_KEY_PEM = "-----BEGIN RSA PRIVATE KEY-----\n" +
+            "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAKUWHn+NOjJori61\n" +
+            "zRrZm4+NiF39Hu3Q125n9+JxW3HvwuaEuYVXP6ga0C5UH/7EugN11IWHg+55RbCM\n" +
+            "kM+Fns5XOtLiyD1c4QJqe3D3zTbASSWTDH0XII6CaTaRlslLUhi5lFzV4ON5pu5j\n" +
+            "qyHaL9644KCfzsKNQjv+fOeD7JtTAgMBAAECgYADwNb8q2dRUhPzt+pr29qvjtY0\n" +
+            "3NZhLchYGEEIgu9DTeIuf4IASBWIauOkygDYN/zKq1kjmAsl1tgAxZFdRnpvySpG\n" +
+            "CZiWYeWZCVWyiKgcP6Ngcof8+d5RkhGYT+6OnnVt9aAz+e7k9KTciL5+6KMrbbsa\n" +
+            "skAEUdITbh/J17Rh0QJBANq3jcntSqYRukqFqFu7Np9pL5GbDVoGdN9A9QpWbDHH\n" +
+            "FyJTpYTJ3eYI9IxygczbLGP9LPHeos4uXUryJRQbAP8CQQDBOjcH6QpXSRujGTMS\n" +
+            "go2+qadU3nMzFhKyw4I2Abq8EaKRuhVyRZoaAWytzzE13XKbPWhzZjubncq8nEpB\n" +
+            "ZBGtAkBVUJxCVAl2VhvwzcoqXhCkhgdEKNNAdpxIKbJr4eI6WIqxnSdHcObZwEyE\n" +
+            "LHZtTmE2b5+EiW/ANV22ylWkThRJAkBJ4JkjxBz5DHGtpTfaruHE8RaSI08GTD0v\n" +
+            "7gI95eFggJmYf/4tJ6FoqfzEY4BcKOPlqM/jt0W5FNZr0JGveLQtAkAdaDqF4P7E\n" +
+            "+1U7q++VJX8ILP2gMX9i1EdeXU6cQMjTvbgMFMN9Qh3MZcSLXOWWqjuMx1BuexHv\n" +
+            "dKPPzIxvaHVg\n" +
+            "-----END RSA PRIVATE KEY-----";
+
+    private static final String RSA_PUBLIC_KEY_RAW = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDIwPE4XI+nO2W/lPJSvGLbFdllIQwdLTiLp5zNPjHNoJbaLeDsrxKdiiqwua22lpDyNvFR+f974vHeLi20jaoUvunvl3sC4RAcm7hfhPq2ugcP1slbEc9kB07FrnVqmPwJenGSmbKi7WGhu87Z6I5PSsP3e/tAr94m3ISWqrGCMwIDAQAB";
+
+    public static String rsaDecrypt(String encryptedBase64) {
+        try {
+            String privateKeyPEM = RSA_PRIVATE_KEY_PEM
+                    .replace("-----BEGIN RSA PRIVATE KEY-----", "")
+                    .replace("-----END RSA PRIVATE KEY-----", "")
+                    .replaceAll("\\s", "");
+            byte[] keyBytes = Base64.getDecoder().decode(privateKeyPEM);
+            PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
+            KeyFactory kf = KeyFactory.getInstance("RSA");
+            PrivateKey privateKey = kf.generatePrivate(spec);
+
+            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
+            cipher.init(Cipher.DECRYPT_MODE, privateKey);
+            byte[] encryptedBytes = Base64.getDecoder().decode(encryptedBase64);
+            byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
+            return new String(decryptedBytes, StandardCharsets.UTF_8);
+        } catch (Exception e) {
+            return "解密失败: " + e.getMessage();
+        }
+    }
+
+    public static String rsaEncrypt(String plaintext) {
+        try {
+            String publicKeyPEM = "-----BEGIN PUBLIC KEY-----\n" +
+                    RSA_PUBLIC_KEY_RAW +
+                    "\n-----END PUBLIC KEY-----";
+            String pubKey = publicKeyPEM
+                    .replace("-----BEGIN PUBLIC KEY-----", "")
+                    .replace("-----END PUBLIC KEY-----", "")
+                    .replaceAll("\\s", "");
+            byte[] keyBytes = Base64.getDecoder().decode(pubKey);
+            X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
+            KeyFactory kf = KeyFactory.getInstance("RSA");
+            PublicKey publicKey = kf.generatePublic(spec);
+
+            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
+            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
+            byte[] encrypted = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
+            return Base64.getEncoder().encodeToString(encrypted);
+        } catch (Exception e) {
+            return "加密失败: " + e.getMessage();
+        }
+    }
+
+    public static String aesDecrypt(String encryptedText, String key) {
+        try {
+            String text = encryptedText;
+            int padding = text.length() % 4;
+            if (padding != 0) {
+                text += "=".repeat(4 - padding);
+            }
+            byte[] encryptedBytes = Base64.getDecoder().decode(text);
+            SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
+            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
+            cipher.init(Cipher.DECRYPT_MODE, secretKey);
+            byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
+            return new String(decryptedBytes, StandardCharsets.UTF_8);
+        } catch (Exception e) {
+            System.out.println("解密失败: " + e.getMessage());
+            return null;
+        }
+    }
+
+    public static String aesEncrypt(String plainText, String key) {
+        try {
+            String adjustedKey = key;
+            if (adjustedKey.length() < 16) {
+                adjustedKey = String.format("%-16s", adjustedKey).replace(' ', '\0');
+            } else {
+                adjustedKey = adjustedKey.substring(0, 16);
+            }
+            SecretKeySpec secretKey = new SecretKeySpec(adjustedKey.getBytes(StandardCharsets.UTF_8), "AES");
+            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
+            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
+            byte[] encryptedBytes = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
+            return Base64.getEncoder().encodeToString(encryptedBytes);
+        } catch (Exception e) {
+            System.out.println("加密失败: " + e.getMessage());
+            return null;
+        }
+    }
+}

+ 422 - 0
tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/util/UploadUtil.java

@@ -0,0 +1,422 @@
+package com.jzg.quotation.huatai.crawler.util;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.core.io.FileSystemResource;
+import org.springframework.http.*;
+import org.springframework.stereotype.Service;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.util.UriComponentsBuilder;
+
+import javax.imageio.IIOImage;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageWriteParam;
+import javax.imageio.ImageWriter;
+import javax.imageio.stream.FileImageOutputStream;
+import java.awt.image.BufferedImage;
+import java.io.*;
+import java.util.*;
+
+/**
+ * 由 upload.py 转换而来的 Java 代码
+ * 负责图片上传、OCR 识别及相关影像处理
+ */
+public class UploadUtil {
+
+    private final ObjectMapper objectMapper = new ObjectMapper();
+
+    private String imagesPath;
+
+    // ============ 类字段(对应 Python 中的 self 属性) ============
+    private String orderNo;
+    private List<Map<String, String>> b64phoList;
+    private String username;
+    private Map<String, String> cookies;
+    private String comCode;
+    private Map<String, Object> gsInfo;
+    private String token;
+    private Map<String, Object> updataInfo;
+
+    /**
+     * 入口方法:对应 Python 中的 photo_up.main()
+     */
+    public Map<String, Object> upLoad(String orderNo, List<Map<String, String>> b64phoList, Map<String, Object> gsInfo, String username, String comCode, Map<String, String> cookies, String imagesPath, String token, Map<String, Object> updataInfo) throws Exception {
+        this.orderNo = orderNo;
+        this.b64phoList = b64phoList;
+        this.gsInfo = gsInfo;
+        this.username = username;
+        this.comCode = comCode;
+        this.cookies = cookies;
+        this.imagesPath = imagesPath;
+        this.token = token;
+        this.updataInfo = updataInfo;
+        uploads();
+
+        Map<String, Object> result = new LinkedHashMap<>();
+        result.put("code", 200);
+        result.put("message", "影像上传成功");
+        return result;
+    }
+
+    // ============ UUID / 文件名生成(替代 JS 的 get_uuid) ============
+
+    private String getFileName() {
+        return UUID.randomUUID().toString().replace("-", "");
+    }
+
+    // ============ 图片处理方法 ============
+
+    /**
+     * 压缩图片并返回 Base64(对应 Python 中的 ys_photo)
+     */
+    public String ysPhoto(String base64Image) throws Exception {
+        byte[] imageBytes = Base64.getDecoder().decode(base64Image);
+        File tempDir = new File(imagesPath + "huatai/");
+        if (!tempDir.exists()) {
+            tempDir.mkdirs();
+        }
+        File zzFile = File.createTempFile(imagesPath + "huatai/" + "upload_temp_zz", ".jpg", tempDir);
+        try (FileOutputStream fos = new FileOutputStream(zzFile)) {
+            fos.write(imageBytes);
+        }
+
+        BufferedImage img = ImageIO.read(zzFile);
+        if (img == null) {
+            throw new IOException("无法读取图片: " + zzFile.getAbsolutePath());
+        }
+        BufferedImage rgbImg = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_RGB);
+        rgbImg.createGraphics().drawImage(img, 0, 0, null);
+
+        File sbFile = File.createTempFile(imagesPath + "huatai/" + "upload_temp_sb", ".jpg", tempDir);
+        ImageWriter writer = ImageIO.getImageWritersByFormatName("jpg").next();
+        ImageWriteParam param = writer.getDefaultWriteParam();
+        param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
+        param.setCompressionQuality(0.4f);
+        try (FileImageOutputStream output = new FileImageOutputStream(sbFile)) {
+            writer.setOutput(output);
+            writer.write(null, new IIOImage(rgbImg, null, null), param);
+        } finally {
+            writer.dispose();
+        }
+
+        byte[] resultBytes;
+        try (FileInputStream fis = new FileInputStream(sbFile)) {
+            resultBytes = new byte[(int) sbFile.length()];
+            fis.read(resultBytes);
+        }
+        sbFile.delete();
+        return Base64.getEncoder().encodeToString(resultBytes);
+    }
+
+    /**
+     * 保存图片并返回尺寸和大小(对应 Python 中的 ys_photo_new)
+     */
+    public double[] ysPhotoNew(byte[] imageBytes, String imgName) throws Exception {
+        File tempDir = new File(imagesPath + "huatai/");
+        if (!tempDir.exists()) {
+            tempDir.mkdirs();
+        }
+        File originalFile = File.createTempFile(imagesPath + "huatai/" + "upload_temp_" + imgName, ".jpg", tempDir.getAbsoluteFile());
+        try (FileOutputStream fos = new FileOutputStream(originalFile)) {
+            fos.write(imageBytes);
+        }
+
+        BufferedImage img = ImageIO.read(originalFile);
+        if (img == null) {
+            throw new IOException("无法读取图片: " + originalFile.getAbsolutePath());
+        }
+
+        String width = "";
+        String height = "";
+
+        if (img.getColorModel().hasAlpha() || img.getType() == BufferedImage.TYPE_BYTE_INDEXED) {
+            BufferedImage rgbImg = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_RGB);
+            rgbImg.createGraphics().drawImage(img, 0, 0, null);
+            img = rgbImg;
+        }
+
+        if (width != null && !width.isEmpty() || height != null && !height.isEmpty()) {
+            int originalWidth = img.getWidth();
+            int originalHeight = img.getHeight();
+
+            int targetWidth;
+            int targetHeight;
+
+            if (width != null && !width.isEmpty() && height != null && !height.isEmpty()) {
+                targetWidth = Integer.parseInt(width);
+                targetHeight = Integer.parseInt(height);
+            } else if (width != null && !width.isEmpty()) {
+                targetWidth = Integer.parseInt(width);
+                double ratio = (double) targetWidth / originalWidth;
+                targetHeight = (int) (originalHeight * ratio);
+            } else {
+                targetHeight = Integer.parseInt(height);
+                double ratio = (double) targetHeight / originalHeight;
+                targetWidth = (int) (originalWidth * ratio);
+            }
+
+            BufferedImage resizedImg = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB);
+            resizedImg.createGraphics().drawImage(
+                    img.getScaledInstance(targetWidth, targetHeight, java.awt.Image.SCALE_SMOOTH),
+                    0, 0, null);
+            img = resizedImg;
+        }
+
+        File newFile = new File(imagesPath + "huatai/" + imgName + "new.jpg");
+        ImageIO.write(img, "jpg", newFile);
+
+        int newWidth = img.getWidth();
+        int newHeight = img.getHeight();
+        long fileSize = newFile.length();
+        double sizeKb = fileSize / 1024.0;
+
+        return new double[]{newWidth, newHeight, sizeKb};
+    }
+
+    // ============ HTTP 请求方法 ============
+
+    /**
+     * 主上传逻辑(对应 Python 中的 upload)
+     */
+    public void uploads() throws Exception {
+        for (Map<String, String> zz : this.b64phoList) {
+            String imgType = zz.get("imgType");
+            String imageBase64 = zz.get("imageBase64");
+
+            if ("C01".equals(imgType) || "D01".equals(imgType)) {
+                // OCR 识别 + 影像上传
+                if ("C01".equals(imgType)) {
+                    doOcrUpload(imageBase64, "carPermit", "1");
+                } else if ("D01".equals(imgType)) {
+                    doOcrUpload(imageBase64, "carPermitFB", "0");
+                }
+                doImageUpload(imageBase64);
+            } else {
+                // 仅 OCR 识别
+                if ("C02".equals(imgType)) {
+                    doOcrUpload(imageBase64, "actionPermit", "onwer", "1");
+                } else if ("D02".equals(imgType)) {
+                    Map<String, Object> ocrRes = doOcrUpload(imageBase64, "actionPermit", "onwer", "0");
+                } else if ("C03".equals(imgType)) {
+                    doOcrUpload(imageBase64, "actionPermit", "action", "1");
+                } else if ("D03".equals(imgType)) {
+                    Map<String, Object> ocrRes = doOcrUpload(imageBase64, "actionPermit", "action", "0");
+                } else if ("C04".equals(imgType)) {
+                    doOcrUpload(imageBase64, "actionPermit", "insured", "1");
+                } else if ("D04".equals(imgType)) {
+                    Map<String, Object> ocrRes = doOcrUpload(imageBase64, "actionPermit", "insured", "0");
+                }
+            }
+        }
+    }
+
+    // ============ 内部业务方法 ============
+
+    /**
+     * 行驶证类 OCR 上传(无 actionType)
+     */
+    private Map<String, Object> doOcrUpload(String imageBase64, String baseType, String side) throws Exception {
+        return doOcrUploadInternal(imageBase64, baseType, null, side);
+    }
+
+    /**
+     * 驾驶证类 OCR 上传(有 actionType)
+     */
+    private Map<String, Object> doOcrUpload(String imageBase64, String baseType, String actionType, String side) throws Exception {
+        return doOcrUploadInternal(imageBase64, baseType, actionType, side);
+    }
+
+    private Map<String, Object> doOcrUploadInternal(String imageBase64, String baseType, String actionType, String side) throws Exception {
+        String ysPhotoBase64 = ysPhoto(imageBase64);
+
+        HttpHeaders headers = new HttpHeaders();
+        headers.set("Accept", "application/json, text/javascript, */*; q=0.01");
+        headers.set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8");
+        headers.set("Cache-Control", "no-cache");
+        headers.set("Connection", "keep-alive");
+        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
+        headers.set("Origin", "https://cspxp.pc.ehuatai.com");
+        headers.set("Pragma", "no-cache");
+        headers.set("Referer", "https://cspxp.pc.ehuatai.com/htcsp/VehicleInfoEntryAction.do?cmd=startProcess");
+        headers.set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36");
+        headers.set("X-Requested-With", "XMLHttpRequest");
+        addCookies(headers);
+
+        String url = "https://cspxp.pc.ehuatai.com/htcsp/VehicleInfoEntryAction.do";
+        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
+        params.add("cmd", "uploadESignatureImg");
+
+        MultiValueMap<String, String> data = new LinkedMultiValueMap<>();
+        data.add("base64", "data:image/jpeg;base64," + ysPhotoBase64);
+        data.add("basetype", baseType);
+        data.add("side", side);
+        data.add("quotationNo", this.orderNo);
+        data.add("comCode", this.comCode);
+        data.add("userid", getGsInfoUserId());
+        if (actionType != null) {
+            data.add("actionType", actionType);
+        }
+
+        HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(data, headers);
+        ResponseEntity<String> response = CookieUtils.getRestTemplate().exchange(
+                buildUri(url, params), HttpMethod.POST, request, String.class);
+        System.out.println("response.getBody():::"+response.getBody());
+        return objectMapper.readValue(response.getBody(), Map.class);
+    }
+
+    /**
+     * 影像上传到 img-web(对应 Python 中的 upload 后半段)
+     */
+    private void doImageUpload(String imageBase64) throws Exception {
+        String filename = getFileName();
+
+        // 1. 先处理图片到本地
+        byte[] originalBytes = Base64.getDecoder().decode(imageBase64);
+        double[] whSize = ysPhotoNew(originalBytes, filename);
+        double fileSizeKb = whSize[2];
+
+        File uploadFile = new File(imagesPath + "huatai/" + filename + "new.jpg");
+
+        // 2. 上传文件
+        HttpHeaders uploadHeaders = new HttpHeaders();
+        uploadHeaders.set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6");
+        uploadHeaders.set("Cache-Control", "no-cache");
+        uploadHeaders.set("Connection", "keep-alive");
+        uploadHeaders.set("Host", "img-web.pc.ehuatai.com");
+        uploadHeaders.set("Origin", "https://img-web.pc.ehuatai.com");
+        uploadHeaders.set("Pragma", "no-cache");
+        uploadHeaders.set("Sec-Fetch-Dest", "empty");
+        uploadHeaders.set("Sec-Fetch-Mode", "cors");
+        uploadHeaders.set("Sec-Fetch-Site", "same-origin");
+        uploadHeaders.set("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1 Edg/133.0.0.0");
+        uploadHeaders.set("X-Requested-With", "XMLHttpRequest");
+        uploadHeaders.set("bucket", getUpdataValue("typeTreeNodeVo.bucket"));
+        uploadHeaders.set("Referer", "https://img-web.pc.ehuatai.com/app/upload.img?token=" + this.token);
+        uploadHeaders.set("bussModule", getUpdataValue("typeTreeNodeVo.bussType"));
+        uploadHeaders.set("bussNo", this.orderNo);
+        uploadHeaders.set("fileName", filename + ".jpg");
+        uploadHeaders.set("storageType", "Local");
+        uploadHeaders.set("token", this.token);
+
+        String uploadUrl = "https://img-web.pc.ehuatai.com/app/ImgFileUpload/upload.do";
+
+        MultiValueMap<String, Object> uploadBody = new LinkedMultiValueMap<>();
+        uploadBody.add("file", new FileSystemResource(uploadFile));
+        uploadBody.add("token", this.token);
+        uploadBody.add("bucket", getUpdataValue("typeTreeNodeVo.bucket"));
+        uploadBody.add("storageType", getUpdataValue("storageType"));
+        uploadBody.add("bussModule", getUpdataValue("typeTreeNodeVo.bussType"));
+        uploadBody.add("bussNo", this.orderNo);
+        uploadBody.add("fileName", filename + ".jpg");
+        uploadBody.add("saveFileName", "");
+
+        HttpEntity<MultiValueMap<String, Object>> uploadRequest = new HttpEntity<>(uploadBody, uploadHeaders);
+        ResponseEntity<String> uploadResponse = CookieUtils.getRestTemplate().exchange(uploadUrl, HttpMethod.POST, uploadRequest, String.class);
+        String uploadResponseText = uploadResponse.getBody();
+
+        // 3. 保存文件索引
+        String appendPath = uploadResponseText != null ?
+                uploadResponseText.substring(0, uploadResponseText.lastIndexOf("/")).replace("\"", "") + "/" : "";
+        String fileNameInResponse = uploadResponseText != null ?
+                uploadResponseText.substring(uploadResponseText.lastIndexOf("/") + 1).replace("\"", "") : "";
+
+        HttpHeaders idxHeaders = new HttpHeaders();
+        idxHeaders.setContentType(MediaType.APPLICATION_JSON);
+        idxHeaders.set("Accept", "application/json, text/plain, */*");
+        idxHeaders.set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36");
+
+        String idxUrl = "https://img-web.pc.ehuatai.com/app/ImgManager/saveFileIdx.cdo";
+
+        long now = System.currentTimeMillis();
+        Map<String, Object> fileIdxVo = new LinkedHashMap<>();
+        fileIdxVo.put("rotate", 0);
+        fileIdxVo.put("rotateStart", 0);
+        fileIdxVo.put("optionFlag", 0);
+        fileIdxVo.put("imgId", now);
+        fileIdxVo.put("createTime", now);
+        fileIdxVo.put("createUser", getUpdataValue("optUserId"));
+        fileIdxVo.put("createUserName", getUpdataValue("optUserName"));
+        fileIdxVo.put("docId", getUpdataValue("typeTreeNodeVo.docId"));
+        fileIdxVo.put("bussNo", this.orderNo);
+        fileIdxVo.put("bussType", getUpdataValue("typeTreeNodeVo.bussType"));
+        fileIdxVo.put("bussTypeName", getUpdataValue("typeTreeNodeVo.bussTypeName"));
+        fileIdxVo.put("riskCode", getUpdataValue("firstRiskCode"));
+        fileIdxVo.put("riskCodeName", getUpdataValue("typeTreeNodeVo.riskCodeName"));
+        fileIdxVo.put("comCode", getUpdataValue("comCode"));
+        fileIdxVo.put("validFlag", 1);
+        fileIdxVo.put("uploadNode", getUpdataValue("uploadNode"));
+        fileIdxVo.put("appendPath", appendPath);
+        fileIdxVo.put("editable", true);
+        fileIdxVo.put("deletable", true);
+        fileIdxVo.put("voType", "C");
+        fileIdxVo.put("picFileFlag", 1);
+        fileIdxVo.put("fileSize", fileSizeKb);
+        fileIdxVo.put("fileSizeFormat", String.format("%.2fKB", fileSizeKb));
+        fileIdxVo.put("fileOrgName", filename + ".jpg");
+        fileIdxVo.put("fileTitle", filename);
+        fileIdxVo.put("fileName", fileNameInResponse);
+        fileIdxVo.put("typePath", "|ITEMCAR|3001|");
+        fileIdxVo.put("typePathName", "|车辆资料|行驶证|");
+
+        Map<String, Object> exifdata = new LinkedHashMap<>();
+        Map<String, Object> iptcdata = new LinkedHashMap<>();
+        Map<String, Object> fileMap = new LinkedHashMap<>();
+        fileMap.put("exifdata", exifdata);
+        fileMap.put("iptcdata", iptcdata);
+        fileIdxVo.put("file", fileMap);
+
+        fileIdxVo.put("typeName", "行驶证");
+        fileIdxVo.put("picMaxSize", 1024);
+        fileIdxVo.put("picQuality", 90);
+        fileIdxVo.put("showIdx", 4);
+        fileIdxVo.put("storageType", "local");
+        fileIdxVo.put("systemTag", "mobile.v6.0.0");
+        fileIdxVo.put("appSource", "UW");
+
+        Map<String, Object> idxData = new LinkedHashMap<>();
+        idxData.put("token", this.token);
+        idxData.put("fileIdxVo", fileIdxVo);
+
+        String jsonBody = objectMapper.writeValueAsString(idxData);
+        HttpEntity<String> idxRequest = new HttpEntity<>(jsonBody, idxHeaders);
+        CookieUtils.getRestTemplate().exchange(idxUrl, HttpMethod.POST, idxRequest, String.class);
+    }
+
+    // ============ 工具方法 ============
+
+    private String getGsInfoUserId() {
+        Object useridValue = this.gsInfo.get("userid_value");
+        Object useridName = this.gsInfo.get("userid_name");
+        return (useridValue != null ? useridValue.toString() : "") + " - " + (useridName != null ? useridName.toString() : "");
+    }
+
+    private String getUpdataValue(String keyPath) {
+        if (this.updataInfo == null) return "";
+        String[] keys = keyPath.split("\\.");
+        Object current = this.updataInfo;
+        for (String key : keys) {
+            if (current instanceof Map) {
+                current = ((Map<?, ?>) current).get(key);
+            } else {
+                return "";
+            }
+        }
+        return current != null ? current.toString() : "";
+    }
+
+    private void addCookies(HttpHeaders headers) {
+        if (this.cookies == null || this.cookies.isEmpty()) return;
+        StringBuilder sb = new StringBuilder();
+        for (Map.Entry<String, String> entry : this.cookies.entrySet()) {
+            if (sb.length() > 0) sb.append("; ");
+            sb.append(entry.getKey()).append("=").append(entry.getValue());
+        }
+        headers.set("Cookie", sb.toString());
+    }
+
+    private String buildUri(String url, MultiValueMap<String, String> params) {
+        return UriComponentsBuilder.fromHttpUrl(url).queryParams(params).toUriString();
+    }
+}

+ 1 - 1
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/async/AsyncGetPayLink.java

@@ -33,7 +33,7 @@ public class AsyncGetPayLink {
     public void paymentLink(QuotationBaseService quoteService,OrderBase order, String companyCode ){
         try {
             if (StringUtils.equals(CompanyConstants.TPBX.getCompanyCode(),companyCode) || StringUtils.equals(CompanyConstants.TKIC.getCompanyCode(),companyCode)
-                    || StringUtils.equals(CompanyConstants.TSBX.getCompanyCode(),companyCode)
+                    || StringUtils.equals(CompanyConstants.TSBX.getCompanyCode(),companyCode) || StringUtils.equals(CompanyConstants.HTIC.getCompanyCode(),companyCode)
             ){
                 PaymentLinkVo paymentLinkVo = new PaymentLinkVo();
                 paymentLinkVo.setOrder(order);

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません