package com.xcong.excoin.modules.gateApi.wsHandler;
|
|
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONObject;
|
import com.xcong.excoin.modules.gateApi.GateGridTradeService;
|
import com.xcong.excoin.modules.gateApi.wsHandler.GateChannelHandler;
|
import lombok.extern.slf4j.Slf4j;
|
import org.java_websocket.client.WebSocketClient;
|
|
import javax.crypto.Mac;
|
import javax.crypto.spec.SecretKeySpec;
|
import java.nio.charset.StandardCharsets;
|
|
/**
|
* 私有频道的抽象基类,封装 HMAC-SHA512 签名和认证请求构建。
|
*
|
* @author Administrator
|
*/
|
@Slf4j
|
public abstract class AbstractPrivateChannelHandler implements GateChannelHandler {
|
|
private static final char[] HEX_ARRAY = "0123456789abcdef".toCharArray();
|
|
private final String channelName;
|
private final String apiKey;
|
private final String apiSecret;
|
private final String contract;
|
private final GateGridTradeService gridTradeService;
|
|
public AbstractPrivateChannelHandler(String channelName,
|
String apiKey, String apiSecret,
|
String contract,
|
GateGridTradeService gridTradeService) {
|
this.channelName = channelName;
|
this.apiKey = apiKey;
|
this.apiSecret = apiSecret;
|
this.contract = contract;
|
this.gridTradeService = gridTradeService;
|
}
|
|
@Override
|
public String getChannelName() {
|
return channelName;
|
}
|
|
@Override
|
public void subscribe(WebSocketClient ws) {
|
long timeSec = System.currentTimeMillis() / 1000;
|
JSONObject msg = buildAuthRequest("subscribe", buildUid(), timeSec);
|
ws.send(msg.toJSONString());
|
log.info("[{}] 已发送订阅请求(含认证),合约: {}", channelName, contract);
|
}
|
|
@Override
|
public void unsubscribe(WebSocketClient ws) {
|
JSONObject unsubscribeMsg = new JSONObject();
|
unsubscribeMsg.put("time", System.currentTimeMillis() / 1000);
|
unsubscribeMsg.put("channel", channelName);
|
unsubscribeMsg.put("event", "unsubscribe");
|
JSONArray payload = new JSONArray();
|
payload.add(contract);
|
unsubscribeMsg.put("payload", payload);
|
ws.send(unsubscribeMsg.toJSONString());
|
log.info("[{}] 已发送取消订阅请求,合约: {}", channelName, contract);
|
}
|
|
protected GateGridTradeService getGridTradeService() {
|
return gridTradeService;
|
}
|
|
protected String getContract() {
|
return contract;
|
}
|
|
private String buildUid() {
|
return gridTradeService != null && gridTradeService.getUserId() != null
|
? String.valueOf(gridTradeService.getUserId()) : "";
|
}
|
|
private JSONObject buildAuthRequest(String event, String uid, long timeSec) {
|
JSONObject msg = new JSONObject();
|
msg.put("id", timeSec * 1000000 + (System.currentTimeMillis() % 1000));
|
msg.put("time", timeSec);
|
msg.put("channel", channelName);
|
msg.put("event", event);
|
JSONArray payload = new JSONArray();
|
payload.add(uid);
|
payload.add(contract);
|
msg.put("payload", payload);
|
JSONObject auth = new JSONObject();
|
auth.put("method", "api_key");
|
auth.put("KEY", apiKey);
|
auth.put("SIGN", hs512Sign(event, timeSec));
|
msg.put("auth", auth);
|
return msg;
|
}
|
|
private String hs512Sign(String event, long timeSec) {
|
try {
|
String message = "channel=" + channelName + "&event=" + event + "&time=" + timeSec;
|
Mac mac = Mac.getInstance("HmacSHA512");
|
SecretKeySpec spec = new SecretKeySpec(apiSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA512");
|
mac.init(spec);
|
byte[] hash = mac.doFinal(message.getBytes(StandardCharsets.UTF_8));
|
StringBuilder hex = new StringBuilder(hash.length * 2);
|
for (byte b : hash) {
|
hex.append(HEX_ARRAY[(b >> 4) & 0xF]);
|
hex.append(HEX_ARRAY[b & 0xF]);
|
}
|
return hex.toString();
|
} catch (Exception e) {
|
log.error("[{}] 签名计算失败", channelName, e);
|
return "";
|
}
|
}
|
}
|