package com.xcong.excoin.modules.okxApi; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import java.security.SecureRandom; import java.security.cert.X509Certificate; import java.text.SimpleDateFormat; import java.util.Base64; import java.util.Date; import java.util.Random; /** * OKX API 工具类:SSL配置、HMAC-SHA256签名、订单ID生成、日期格式化、JSON构建。 * * @author Administrator */ @Slf4j public final class OkxWsUtil { private OkxWsUtil() {} // ==================== SSL ==================== public static void configureSSL() { 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 sc = SSLContext.getInstance("TLS"); sc.init(null, trustAllCerts, new SecureRandom()); SSLContext.setDefault(sc); } catch (Exception e) { log.error("SSL配置失败", e); } } // ==================== HMAC-SHA256 签名 ==================== public static String signWebsocket(String timestamp, String secretKey) { return sign(timestamp, "GET", "/users/self/verify", "", secretKey); } public static String signRest(String timestamp, String method, String path, String body, String secretKey) { return sign(timestamp, method.toUpperCase(), path, body, secretKey); } private static String sign(String timestamp, String method, String path, String body, String secretKey) { try { String message = String.format("%s%s%s%s", timestamp, method, path, body); Mac mac = Mac.getInstance("HmacSHA256"); SecretKeySpec spec = new SecretKeySpec(secretKey.getBytes("UTF-8"), "HmacSHA256"); mac.init(spec); byte[] hash = mac.doFinal(message.getBytes("UTF-8")); return Base64.getEncoder().encodeToString(hash); } catch (Exception e) { log.error("签名计算失败", e); return ""; } } // ==================== 订单ID ==================== private static final ThreadLocal ORDER_ID_DF = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyyMMddHHmmss")); private static final ThreadLocal RANDOM = ThreadLocal.withInitial(Random::new); public static String getOrderNum(String prefix) { String dd = ORDER_ID_DF.get().format(new Date()); if (prefix != null && !prefix.isEmpty()) { return prefix + dd + getRandomNum(5); } return dd + getRandomNum(5); } private static String getRandomNum(int length) { String str = "0123456789"; Random random = RANDOM.get(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < length; ++i) { sb.append(str.charAt(random.nextInt(str.length()))); } return sb.toString(); } // ==================== JSON构建 ==================== public static JSONObject buildJsonObject(String connId, String op, JSONArray args) { JSONObject jsonObject = new JSONObject(); if (connId != null && !connId.isEmpty()) { jsonObject.put("id", connId); } jsonObject.put("op", op); jsonObject.put("args", args); return jsonObject; } // ==================== 日期格式化 ==================== private static final ThreadLocal DATE_TIME_DF = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); private static final ThreadLocal ISO8601_DF = ThreadLocal.withInitial(() -> { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); sdf.setTimeZone(java.util.TimeZone.getTimeZone("UTC")); return sdf; }); public static String getIso8601Timestamp() { return ISO8601_DF.get().format(new Date()); } public static String timestampToDateTime(long timestamp) { return DATE_TIME_DF.get().format(new Date(timestamp)); } }