From debb7b1ef8bb4e96e09b2d878ad821b4b2f3a110 Mon Sep 17 00:00:00 2001
From: xin <1099200748@qq.com>
Date: Fri, 07 Nov 2025 22:00:17 +0800
Subject: [PATCH] 短信api更新维护(未完成)

---
 oying-system/src/main/java/com/oying/modules/winnerlook/client/OkHttpService.java |  201 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 201 insertions(+), 0 deletions(-)

diff --git a/oying-system/src/main/java/com/oying/modules/winnerlook/client/OkHttpService.java b/oying-system/src/main/java/com/oying/modules/winnerlook/client/OkHttpService.java
new file mode 100644
index 0000000..fdf7ff5
--- /dev/null
+++ b/oying-system/src/main/java/com/oying/modules/winnerlook/client/OkHttpService.java
@@ -0,0 +1,201 @@
+package com.oying.modules.winnerlook.client;
+
+import cn.hutool.core.util.IdUtil;
+import com.alibaba.fastjson2.JSONArray;
+import com.alibaba.fastjson2.JSONObject;
+import com.oying.exception.BadRequestException;
+import com.oying.modules.winnerlook.util.Md5Util;
+import lombok.extern.slf4j.Slf4j;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import shade.okhttp3.*;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import java.io.ByteArrayInputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.UUID;
+
+/**
+ * @author MinaWu
+ * @description
+ * @date 2025/5/14 16:16
+ */
+
+@Slf4j
+public class OkHttpService {
+    private static final String SECRET_KEY = "X-Winner-Secret-Key";
+    private static final String TIMESTAMP_HEADER = "X-Winner-Timestamp";
+    private static final String SIGNATURE_HEADER = "X-Winner-Signature";
+    private static final String REQUEST_ID = "X-Winner-Request-Id";
+    private static final String TOKEN = "X-Winner-token";
+    private static final String PARAMS = "params";
+
+    /**
+     * 生成 requestId
+     *
+     * @param timestamp 时间戳
+     * @return requestId
+     */
+    private static String generateRequestId(String userName, long timestamp) {
+        return userName.replace("_", "") + "_" + IdUtil.simpleUUID() + "_" + timestamp;
+    }
+
+    public static String doPost(Map<String, Object> params, String baseUrl, String userName, String token) {
+        String secretKey = UUID.randomUUID().toString().replace("-", "");
+        String boundary = UUID.randomUUID().toString().replace("-", "");
+
+        // 生成时间戳
+        long timestamp = System.currentTimeMillis();
+        String timestampStr = String.valueOf(timestamp);
+        // 生成 requestId
+        String requestId = generateRequestId(userName, timestamp);
+
+        // 生成签名
+        String signature = generateSignature(params, timestampStr, secretKey, requestId, token);
+
+        // 创建请求体
+        MultipartBody.Builder bodyBuilder = new MultipartBody.Builder(boundary)
+                .setType(MultipartBody.FORM);
+        for (Map.Entry<String, Object> entry : params.entrySet()) {
+            bodyBuilder.addFormDataPart(entry.getKey(), entry.getValue().toString());
+        }
+        // 创建请求
+        Request request = new Request.Builder()
+                .url(baseUrl)
+                .header(TIMESTAMP_HEADER, timestampStr)
+                .header(SIGNATURE_HEADER, signature)
+                .header(REQUEST_ID, requestId)
+                .header(SECRET_KEY, secretKey)
+                .header("Content-Type", "multipart/form-data;charset=UTF-8; boundary=" + boundary)
+                .post(bodyBuilder.build())
+                .build();
+        // 发送请求
+        try {
+            return "response";
+        } catch (Exception e) {
+            log.info("doPost requestId:{},body:{},headers:{} ", requestId, request.body().toString(), request.headers().toString());
+            throw new BadRequestException("短信POST:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 对 treeMap 的键进行排序
+     */
+    private static void sortParams(Map<String, Object> treeMap) {
+        for (String key : treeMap.keySet()) {
+            Object value = treeMap.get(key);
+            if (value instanceof JSONObject) {
+                // 如果是 JSONObject,递归排序
+                treeMap.put(key, sortJsonObject((JSONObject) value));
+            } else if (value instanceof JSONArray) {
+                // 如果是 JSONArray,对数组中的每个对象排序
+                treeMap.put(key, sortJsonArray((JSONArray) value));
+            } else {
+                // 其他类型直接放入
+                treeMap.put(key, value);
+            }
+        }
+    }
+
+    /**
+     * 对 JSONObject 的键进行排序
+     */
+    private static JSONObject sortJsonObject(JSONObject jsonObject) {
+        Map<String, Object> treeMap = new TreeMap<>();
+        Set<String> keys = jsonObject.keySet();
+        for (String key : keys) {
+            Object value = jsonObject.get(key);
+            if (value instanceof JSONObject) {
+                // 如果是 JSONObject,递归排序
+                treeMap.put(key, sortJsonObject((JSONObject) value));
+            } else if (value instanceof JSONArray) {
+                // 如果是 JSONArray,对数组中的每个对象排序
+                treeMap.put(key, sortJsonArray((JSONArray) value));
+            } else {
+                // 其他类型直接放入
+                treeMap.put(key, value);
+            }
+        }
+        return new JSONObject(treeMap);
+    }
+
+    /**
+     * 对 JSONArray 中的每个 JSONObject 进行排序
+     */
+    private static JSONArray sortJsonArray(JSONArray jsonArray) {
+        JSONArray sortedJsonArray = new JSONArray();
+        for (Object item : jsonArray) {
+            if (item instanceof JSONObject) {
+                // 如果是 JSONObject,递归排序
+                sortedJsonArray.add(sortJsonObject((JSONObject) item));
+            } else {
+                // 其他类型直接放入
+                sortedJsonArray.add(item);
+            }
+        }
+        return sortedJsonArray;
+    }
+
+
+    /**
+     * 生成签名
+     *
+     * @param map       请求参数
+     * @param timestamp 时间戳
+     * @param secretKey 密钥
+     * @return 签名
+     */
+    private static String generateSignature(Map<String, Object> map, String timestamp, String secretKey, String requestId, String token) {
+        try {
+            // 对参数进行排序 将params转成字符串再转成map是为了将其中的对象和集合转成jsonObject和jsonArray 方便排序处理
+//            Map<String, Object> map = JSONObject.parseObject(JSONObject.toJSONString(map), Map.class);
+            Map<String, Object> sortedParams = new TreeMap<>(map);
+            sortParams(sortedParams);
+            // 将参数转换为 JSON 字符串
+            String jsonString = JSONObject.toJSONString(sortedParams);
+            // 计算参数的 MD5
+            String paramsMD5 = Md5Util.getMD5ByCharset(jsonString, StandardCharsets.UTF_8);
+            log.info("generateSignature requestId:{} jsonString:{} paramsMD5:{}", requestId, jsonString, paramsMD5);
+            // 生成待签名的数据
+            String dataToSign = PARAMS + "=" + paramsMD5 +
+                    "&" + TIMESTAMP_HEADER + "=" + timestamp +
+                    "&" + REQUEST_ID + "=" + requestId +
+                    "&" + TOKEN + "=" + token;
+
+            // 使用 HMAC-SHA256 生成签名
+            return Md5Util.hmacSha256(dataToSign, secretKey);
+        } catch (Exception e) {
+            throw new BadRequestException("短信生成签名:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 解析 XML 响应并提取 <string> 标签中的值
+     *
+     * @param xmlResponse XML 响应字符串
+     * @return <string> 标签中的值
+     */
+    public static String parseXmlResponse(String xmlResponse) {
+        try {
+            // 创建 DocumentBuilder
+            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+            DocumentBuilder builder = factory.newDocumentBuilder();
+
+            // 将 XML 字符串转换为 Document 对象
+            Document document = builder.parse(new ByteArrayInputStream(xmlResponse.getBytes(StandardCharsets.UTF_8)));
+
+            // 获取 <string> 标签
+            NodeList nodeList = document.getElementsByTagName("string");
+            Element stringElement = (Element) nodeList.item(0);
+            // 提取标签中的文本内容
+            return stringElement.getTextContent();
+        } catch (Exception e) {
+            throw new BadRequestException("短信解析XML:" + e.getMessage());
+        }
+    }
+}

--
Gitblit v1.9.3