From 6a51f45e6a00b65a9e7b0b0707b453c11311f3ef Mon Sep 17 00:00:00 2001
From: Administrator <15274802129@163.com>
Date: Mon, 11 May 2026 22:38:13 +0800
Subject: [PATCH] feat(okxApi): 添加仓位模式配置和REST客户端功能

---
 src/main/java/com/xcong/excoin/modules/okxApi/OkxRestClient.java |  125 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 125 insertions(+), 0 deletions(-)

diff --git a/src/main/java/com/xcong/excoin/modules/okxApi/OkxRestClient.java b/src/main/java/com/xcong/excoin/modules/okxApi/OkxRestClient.java
new file mode 100644
index 0000000..5c04970
--- /dev/null
+++ b/src/main/java/com/xcong/excoin/modules/okxApi/OkxRestClient.java
@@ -0,0 +1,125 @@
+package com.xcong.excoin.modules.okxApi;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+
+@Slf4j
+public class OkxRestClient {
+
+    private final String baseUrl;
+    private final String apiKey;
+    private final String secretKey;
+    private final String passphrase;
+    private final boolean isSimulate;
+
+    public OkxRestClient(String baseUrl, String apiKey, String secretKey, String passphrase, boolean isSimulate) {
+        this.baseUrl = baseUrl;
+        this.apiKey = apiKey;
+        this.secretKey = secretKey;
+        this.passphrase = passphrase;
+        this.isSimulate = isSimulate;
+    }
+
+    public boolean setPositionMode(String posMode) {
+        JSONObject params = new JSONObject();
+        params.put("posMode", posMode);
+        JSONObject result = post("/api/v5/account/set-position-mode", params);
+        return isSuccess(result, "设置持仓方式");
+    }
+
+    public boolean setLeverage(String instId, String lever, String mgnMode) {
+        JSONObject params = new JSONObject();
+        params.put("instId", instId);
+        params.put("lever", lever);
+        params.put("mgnMode", mgnMode);
+        JSONObject result = post("/api/v5/account/set-leverage", params);
+        return isSuccess(result, "设置杠杆");
+    }
+
+    private JSONObject post(String path, JSONObject body) {
+        HttpURLConnection conn = null;
+        try {
+            String bodyStr = body.toJSONString();
+            String timestamp = OkxWsUtil.getIso8601Timestamp();
+            String sign = OkxWsUtil.signRest(timestamp, "POST", path, bodyStr, secretKey);
+
+            URL url = new URL(baseUrl + path);
+            conn = (HttpURLConnection) url.openConnection();
+            conn.setRequestMethod("POST");
+            conn.setDoOutput(true);
+            conn.setConnectTimeout(15000);
+            conn.setReadTimeout(15000);
+            conn.setRequestProperty("Content-Type", "application/json");
+            conn.setRequestProperty("OK-ACCESS-KEY", apiKey);
+            conn.setRequestProperty("OK-ACCESS-SIGN", sign);
+            conn.setRequestProperty("OK-ACCESS-TIMESTAMP", timestamp);
+            conn.setRequestProperty("OK-ACCESS-PASSPHRASE", passphrase);
+            if (isSimulate) {
+                conn.setRequestProperty("x-simulated-trading", "1");
+            }
+
+            try (OutputStream os = conn.getOutputStream()) {
+                os.write(bodyStr.getBytes(StandardCharsets.UTF_8));
+                os.flush();
+            }
+
+            int code = conn.getResponseCode();
+            String response = readResponse(conn);
+            log.info("[REST] POST {} → HTTP {} body:{}", path, code, response);
+
+            return JSON.parseObject(response);
+        } catch (Exception e) {
+            log.error("[REST] POST {} 失败: {}", path, e.getMessage());
+            return null;
+        } finally {
+            if (conn != null) {
+                conn.disconnect();
+            }
+        }
+    }
+
+    private String readResponse(HttpURLConnection conn) throws Exception {
+        StringBuilder sb = new StringBuilder();
+        String line;
+        if (conn.getResponseCode() >= 200 && conn.getResponseCode() < 300) {
+            try (BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) {
+                while ((line = br.readLine()) != null) {
+                    sb.append(line);
+                }
+            }
+        } else {
+            try (BufferedReader br = new BufferedReader(new InputStreamReader(conn.getErrorStream(), StandardCharsets.UTF_8))) {
+                while ((line = br.readLine()) != null) {
+                    sb.append(line);
+                }
+            }
+        }
+        return sb.toString();
+    }
+
+    private boolean isSuccess(JSONObject result, String label) {
+        if (result == null) {
+            log.error("[REST] {}失败: 无响应", label);
+            return false;
+        }
+        String code = result.getString("code");
+        if ("0".equals(code)) {
+            log.info("[REST] {}成功", label);
+            return true;
+        }
+        if ("59000".equals(code)) {
+            log.info("[REST] {}已设置(59000:配置未变更)", label);
+            return true;
+        }
+        log.error("[REST] {}失败, code:{}, msg:{}", label, code, result.getString("msg"));
+        return false;
+    }
+}

--
Gitblit v1.9.1