From 8925858fb424100acd761178bfbe30c3cbb21c2b Mon Sep 17 00:00:00 2001
From: Administrator <15274802129@163.com>
Date: Wed, 10 Dec 2025 15:04:25 +0800
Subject: [PATCH] feat(okx): 添加OKX WebSocket认证和签名工具

---
 src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxQuantWebSocketClient.java      |    4 +-
 src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/enums/ExchangeInfoEnum.java |   56 ++++++++++++++++++++++++++++
 src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/LoginWs.java                |    4 +-
 src/main/java/com/xcong/excoin/modules/okxNewPrice/utils/SignUtils.java              |   55 +++++++++++++++++++++++++++
 4 files changed, 115 insertions(+), 4 deletions(-)

diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxQuantWebSocketClient.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxQuantWebSocketClient.java
index 96a483f..e79cd49 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxQuantWebSocketClient.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxQuantWebSocketClient.java
@@ -7,6 +7,7 @@
 import com.xcong.excoin.modules.okxNewPrice.celue.CaoZuoService;
 import com.xcong.excoin.modules.okxNewPrice.okxWs.*;
 import com.xcong.excoin.modules.okxNewPrice.okxWs.enums.CoinEnums;
+import com.xcong.excoin.modules.okxNewPrice.okxWs.enums.ExchangeInfoEnum;
 import com.xcong.excoin.modules.okxNewPrice.okxWs.enums.OrderParamEnums;
 import com.xcong.excoin.modules.okxNewPrice.utils.SSLConfig;
 import com.xcong.excoin.modules.okxNewPrice.wangge.WangGeService;
@@ -50,7 +51,6 @@
 
     private static final String WS_URL_MONIPAN = "wss://wspap.okx.com:8443/ws/v5/private";
     private static final String WS_URL_SHIPAN = "wss://ws.okx.com:8443/ws/v5/private";
-    private static final boolean INTERNET = false;
 
     /**
      * 订阅频道指令
@@ -123,7 +123,7 @@
             SSLConfig.configureSSL();
             System.setProperty("https.protocols", "TLSv1.2,TLSv1.3");
             String WS_URL = WS_URL_MONIPAN;
-            if (INTERNET){
+            if (ExchangeInfoEnum.OKX_UAT.isAccountType()){
                 WS_URL = WS_URL_SHIPAN;
             }
             URI uri = new URI(WS_URL);
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/LoginWs.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/LoginWs.java
index db360ae..7ab4911 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/LoginWs.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/LoginWs.java
@@ -2,8 +2,8 @@
 
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
-import com.xcong.excoin.modules.okxNewPrice.okxpi.config.ExchangeInfoEnum;
-import com.xcong.excoin.modules.okxNewPrice.okxpi.config.utils.SignUtils;
+import com.xcong.excoin.modules.okxNewPrice.okxWs.enums.ExchangeInfoEnum;
+import com.xcong.excoin.modules.okxNewPrice.utils.SignUtils;
 import com.xcong.excoin.modules.okxNewPrice.utils.WsParamBuild;
 import lombok.extern.slf4j.Slf4j;
 import org.java_websocket.client.WebSocketClient;
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/enums/ExchangeInfoEnum.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/enums/ExchangeInfoEnum.java
new file mode 100644
index 0000000..4670873
--- /dev/null
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/enums/ExchangeInfoEnum.java
@@ -0,0 +1,56 @@
+package com.xcong.excoin.modules.okxNewPrice.okxWs.enums;
+
+import lombok.Getter;
+
+/**
+ * 交易信息枚举类
+ * 用于存储不同交易账户的密钥信息,包括实盘账户和模拟账户
+ */
+@Getter
+public enum ExchangeInfoEnum {
+
+    /**
+     * 模拟盘账户信息
+     * 存储了模拟盘交易所需的API密钥、秘钥和通过码
+     */
+    OKX_UAT("7a023eb2-06c0-4255-9969-b86ea1cef0d7",
+            "D0106A4D63BD22BEAB9CBA8F41219661",
+            "Aa12345678@",
+            false);
+
+//    /**
+//     * 模拟盘账户信息
+//     * 存储了模拟盘交易所需的API密钥、秘钥和通过码
+//     */
+//    OKX_UAT("0769b50c-2c36-4310-8bd9-cad6bc6c9d8f",
+//            "7AF4A574BC44907CE76BBFF91F53852D",
+//            "Aa123456@",
+//            false);
+
+    // API公钥,用于识别用户身份
+    private String apiKey;
+
+    // API秘钥,用于签名和验证请求
+    private String secretKey;
+
+    // API通过码,用于额外的身份验证
+    private String passphrase;
+
+    // 账户类型,true表示实盘账户,false表示模拟账户
+    private boolean accountType;
+
+    /**
+     * 构造方法
+     *
+     * @param apiKey API公钥,用于识别用户身份
+     * @param secretKey API秘钥,用于签名和验证请求
+     * @param passphrase API通过码,用于额外的身份验证
+     * @param accountType 账户类型,true表示实盘账户,false表示模拟账户
+     */
+    ExchangeInfoEnum(String apiKey, String secretKey, String passphrase, boolean accountType) {
+        this.apiKey = apiKey;
+        this.secretKey = secretKey;
+        this.passphrase = passphrase;
+        this.accountType = accountType;
+    }
+}
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/utils/SignUtils.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/utils/SignUtils.java
new file mode 100644
index 0000000..87dfb2c
--- /dev/null
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/utils/SignUtils.java
@@ -0,0 +1,55 @@
+package com.xcong.excoin.modules.okxNewPrice.utils;
+
+import lombok.extern.slf4j.Slf4j;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import java.util.Base64;
+
+
+@Slf4j
+public class SignUtils {
+
+    public static String signRest(String secretKey, String timestamp, String method, String path, String body) {
+        String str = String.format("%s%s%s%s",
+                timestamp, // timestamp
+                method,  // method GET/POST
+                path, // requestPath
+                body // body
+        );
+        try {
+            return Base64.getEncoder().encodeToString(hmacSHA256(secretKey.getBytes(), str.getBytes()));
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+
+
+    /**
+     * HmacSHA256算法,返回的结果始终是32位
+     *
+     * @param key     加密的键,可以是任何数据
+     * @param content 待加密的内容
+     * @return 加密后的内容
+     * @throws Exception ex
+     */
+    public static byte[] hmacSHA256(byte[] key, byte[] content) throws Exception {
+        Mac hmacSha256 = Mac.getInstance("HmacSHA256");
+        hmacSha256.init(new SecretKeySpec(key, 0, key.length, "HmacSHA256"));
+        return hmacSha256.doFinal(content);
+    }
+
+    public static String signWebsocket(String timestamp, String secretKey) {
+        String str = String.format("%s%s%s",
+                timestamp,
+                "GET",
+                "/users/self/verify");
+        try {
+            return Base64.getEncoder().encodeToString(hmacSHA256(secretKey.getBytes(), str.getBytes()));
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+}

--
Gitblit v1.9.1