Przeglądaj źródła

新增中交接口

donglang 2 miesięcy temu
rodzic
commit
27c084d95c

+ 134 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/reponse/CollectZjxlResponse.java

@@ -0,0 +1,134 @@
+package com.sckw.core.reponse;
+
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * Author: donglang
+ * Time: 2025-10-19
+ * Des:
+ * Version: 1.0
+ */
+
+@Data
+public class CollectZjxlResponse {
+
+    /**
+     * 状态码
+     */
+    private String status;
+
+    /**
+     * 返回结果信息
+     */
+    private Result result;
+
+    @Data
+    public class Result {
+
+        /**
+         * 第一辆车
+         */
+        private ZjxlResultResDto firstVcl;
+
+        /**
+         * 其他车
+         */
+        private List<ZjxlResultResDto> others;
+
+
+        @Data
+        public class ZjxlResultResDto {
+
+            /**
+             *
+             */
+            private String lat;
+
+            /**
+             *
+             */
+            private String lon;
+
+            /**
+             *
+             */
+            private String adr;
+
+            /**
+             *
+             */
+            private String utc;
+
+            /**
+             *
+             */
+            private String spd;
+
+            /**
+             *
+             */
+            private String drc;
+
+            /**
+             *
+             */
+            private String province;
+
+            /**
+             *
+             */
+            private String city;
+
+            /**
+             *
+             */
+            private String country;
+
+            /**
+             *
+             */
+            private String mil;
+
+            /**
+             *
+             */
+            private String vno;
+
+            /**
+             *
+             */
+            private String status;
+
+            /**
+             *
+             */
+            private Boolean offlineState;
+
+            /**
+             *
+             */
+            private String offlineTime;
+
+            /**
+             *
+             */
+            private String runDistance;
+
+            /**
+             *
+             */
+            private String remainDistance;
+
+            /**
+             *
+             */
+            private String estimateArriveTime;
+
+        }
+
+    }
+
+}

+ 220 - 0
sckw-common/sckw-common-core/src/main/java/com/sckw/core/service/VehicleCollectService.java

@@ -0,0 +1,220 @@
+package com.sckw.core.service;
+
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.sckw.core.reponse.CollectZjxlResponse;
+import jakarta.annotation.Resource;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import javax.net.ssl.*;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.security.SecureRandom;
+import java.security.cert.X509Certificate;
+import java.util.*;
+
+
+/**
+ * Author: donglang
+ * Time: 2025-10-19
+ * Des: 中交接口
+ * Version: 1.0
+ */
+
+public class VehicleCollectService {
+
+    @Resource
+    private ObjectMapper objectMapper;
+
+    public static final String HMAC_SHA1 = "HmacSHA1";
+    public static final char[] DIGITAL = "0123456789ABCDEF".toCharArray();
+
+
+    /**
+     * <pre>
+     * 请求流程:
+     * 1、其他 API,cid + 私钥生成的签名 + 业务参数
+     * </pre>
+     */
+    public CollectZjxlResponse transTimeManage(String carNo) throws Exception {
+        // URL 前缀
+        String baseUrl = "https://openapi-test.sinoiov.cn/save/apis/";
+        // 检索最新节点
+        String vLastLocationV3Url = baseUrl + "transTimeManageV3";
+        Map<String, String> vLastLocationParam = new HashMap<>();
+        // 客户端 ID
+        vLastLocationParam.put("cid", "7598ca30-000e-4930-953d-39e6756b6ee5");
+        // 私钥
+        vLastLocationParam.put("srt", "2b15bfd6-3546-4e25-bc9b-7cf88d4d2c3c");
+        // 业务参数
+        vLastLocationParam.put("vclN", carNo);
+        vLastLocationParam.put("timeNearby", "24");
+        String vLastLocationV3Result = httpsCall(vLastLocationV3Url, vLastLocationParam, false);
+
+        //反序列化
+        CollectZjxlResponse response = objectMapper.readValue(vLastLocationV3Result, CollectZjxlResponse.class);
+        return response;
+    }
+
+
+    /**
+     * https 调用,1、处理参数:①移除srt,②计算签名,③增加sign;2、将 map参数拼接成string格式;3、发起调用;4、处理结果
+     *
+     * @param url    url
+     * @param param  请求参数
+     * @param strict 严格模式 true 校验证书等;false 不校验
+     */
+    public static String httpsCall(String url, Map<String, String> param, boolean strict) throws Exception {
+        // 1、处理参数
+        processParam(param);
+        // 2、将 map 参数拼接成 string 格式
+        String reqBody = convertMapToString(param);
+        System.out.printf("Request - url: %s, reqBody: %s\n", url, reqBody);
+        if (!strict) {
+            // 信任证书
+            trustAllCerts();
+            // 信任域名
+            trustAllHosts();
+        }
+        // 3、发起调用;
+        HttpsURLConnection conn = (HttpsURLConnection) new URL(url).openConnection();
+        conn.setDoInput(true);
+        conn.setDoOutput(true);
+
+        conn.setUseCaches(false);
+        conn.setRequestMethod("POST");
+        conn.setRequestProperty("Content-Length", String.valueOf(reqBody.getBytes(StandardCharsets.UTF_8).length));
+        conn.setRequestProperty("charset", "UTF-8");
+        conn.connect();
+        PrintWriter writer = new PrintWriter(new OutputStreamWriter(conn.getOutputStream(), StandardCharsets.UTF_8));
+        // 注意这里不能有换行
+        writer.print(reqBody);
+        writer.flush();
+        writer.close();
+        BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
+        String line;
+        StringBuilder result = new StringBuilder();
+        while ((line = reader.readLine()) != null) {
+            result.append(line);
+        }
+
+        reader.close();
+        System.out.printf("Response - code: %s, message: %s, respBody: %s\n", conn.getResponseCode(), conn.getResponseMessage(), result);
+        // 4、处理结果
+        return result.toString();
+    }
+
+
+    /**
+     * 处理参数:①移除 srt,②计算签名,③增加 sign;
+     *
+     * @param param 原始参数
+     */
+    private static void processParam(Map<String, String> param) throws Exception {
+        if (!param.containsKey("srt")) {
+            throw new NullPointerException();
+        }
+        String srt = param.remove("srt");
+        List<String> paramValueList = new ArrayList<>();
+        for (Map.Entry<String, String> entry : param.entrySet()) {
+            paramValueList.add(entry.getKey() + entry.getValue());
+        }
+        Collections.sort(paramValueList);
+        String[] data = new String[paramValueList.size()];
+        paramValueList.toArray(data);
+        byte[] signature = hmacSha1(data, srt.getBytes(StandardCharsets.UTF_8));
+        String sign = encodeHexStr(signature);
+        param.put("sign", sign);
+    }
+
+
+    /**
+     * 将参数转换为字符串
+     *
+     * @param param 请求参数
+     */
+    private static String convertMapToString(Map<String, String> param) {
+        StringBuilder sb = new StringBuilder();
+        if (param != null && !param.isEmpty()) {
+            for (Map.Entry<String, String> entry : param.entrySet()) {
+                sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
+            }
+            sb.deleteCharAt(sb.length() - 1);
+        }
+        return sb.toString();
+    }
+
+
+    /**
+     * 信任所有证书
+     */
+    private static void trustAllCerts() throws Exception {
+        TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
+            public X509Certificate[] getAcceptedIssuers() {
+                return null;
+            }
+
+            public void checkClientTrusted(X509Certificate[] certs, String authType) {
+            }
+
+            public void checkServerTrusted(X509Certificate[] certs, String authType) {
+            }
+        }};
+        SSLContext sc = SSLContext.getInstance("SSL");
+        sc.init(null, trustAllCerts, new SecureRandom());
+        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
+    }
+
+    /**
+     * 信任所有域名
+     */
+    private static void trustAllHosts() {
+        HostnameVerifier trustAllHosts = (hostname, session) -> true;
+        HttpsURLConnection.setDefaultHostnameVerifier(trustAllHosts);
+    }
+
+
+    /**
+     * HmacSha1 定制算法
+     *
+     * @param strings 内容
+     * @param key     key
+     * @return 签名
+     */
+    private static byte[] hmacSha1(String[] strings, byte[] key) throws Exception {
+        SecretKeySpec signingKey = new SecretKeySpec(key, HMAC_SHA1);
+        Mac mac = Mac.getInstance(HMAC_SHA1);
+        mac.init(signingKey);
+        for (String data : strings) {
+            mac.update(data.getBytes(StandardCharsets.UTF_8));
+        }
+        return mac.doFinal();
+
+    }
+
+
+    /**
+     * 字节转为 Hex 字符串
+     *
+     * @param bytes 字节数组
+     * @return Hex 字符串
+     */
+    private static String encodeHexStr(final byte[] bytes) {
+        if (bytes == null) {
+            return null;
+        }
+        char[] result = new char[bytes.length * 2];
+        for (int i = 0; i < bytes.length; i++) {
+            result[i * 2] = DIGITAL[(bytes[i] & 0xf0) >> 4];
+            result[i * 2 + 1] = DIGITAL[bytes[i] & 0x0f];
+        }
+        return new String(result);
+    }
+
+
+}