From e0ce7bc8678e771d13090d9b262eb833aef114b9 Mon Sep 17 00:00:00 2001
From: zyy <zyy@email.com>
Date: Fri, 04 Jul 2025 18:44:31 +0800
Subject: [PATCH] 新增websocket美国、墨西哥客户端 多线程执行同步股票、新闻咨询抓取
---
src/main/java/com/nq/service/impl/UserStockSubscribeServiceImpl.java | 10
src/main/resources/application.properties | 14 +
src/main/java/com/nq/ws/WebsocketRunClient.java | 65 +++++-----
src/main/java/com/nq/enums/EStockType.java | 20 +-
src/main/java/com/nq/ws/WebSocketClientBeanConfig.java | 56 ++++++--
src/main/java/com/nq/service/impl/SiteNewsServiceImpl.java | 19 +++
src/main/java/com/nq/utils/task/stock/StockTask.java | 22 +++
src/main/java/com/nq/ws/MXWebsocketRunClient.java | 127 +++++++++++++++++++++
8 files changed, 262 insertions(+), 71 deletions(-)
diff --git a/src/main/java/com/nq/enums/EStockType.java b/src/main/java/com/nq/enums/EStockType.java
index 373ee52..5754a61 100644
--- a/src/main/java/com/nq/enums/EStockType.java
+++ b/src/main/java/com/nq/enums/EStockType.java
@@ -12,10 +12,13 @@
US("US","美国股票","5",PropertiesUtil.getProperty("US_HTTP_API"),PropertiesUtil.getProperty("US_KEY"),"USD","$"),
- HK("HK","香港股票","39",PropertiesUtil.getProperty("HK_HTTP_API"),PropertiesUtil.getProperty("HK_KEY"),"HKD","HK$"),
- MAS("MAS","马来西亚股票","42",PropertiesUtil.getProperty("MAS_HTTP_API"),PropertiesUtil.getProperty("MAS_KEY"),"MYR","RM"),
- IN("IN","印度股票","14", PropertiesUtil.getProperty("JS_IN_HTTP_URL"),PropertiesUtil.getProperty("JS_IN_KEY"),"INR","₹");
+// HK("HK","香港股票","39",PropertiesUtil.getProperty("HK_HTTP_API"),PropertiesUtil.getProperty("HK_KEY"),"HKD","HK$"),
+// MAS("MAS","马来西亚股票","42",PropertiesUtil.getProperty("MAS_HTTP_API"),PropertiesUtil.getProperty("MAS_KEY"),"MYR","RM"),
+//
+ IN("IN","印度股票","14", PropertiesUtil.getProperty("JS_IN_HTTP_URL"),PropertiesUtil.getProperty("JS_IN_KEY"),"INR","₹"),
+ MX("MX","墨西哥股票","7",PropertiesUtil.getProperty("MX_HTTP_API"),PropertiesUtil.getProperty("MX_KEY"),"MXN","MXN$");
+
// TH("TH","泰国股票","41",PropertiesUtil.getProperty("TH_HTTP_API"),PropertiesUtil.getProperty("TH_KEY")),
// HG("HG","韩国股票","11",PropertiesUtil.getProperty("HG_HTTP_API"),PropertiesUtil.getProperty("HG_KEY")),
// SZHB("SZHB","数字货币","41",PropertiesUtil.getProperty("SZHB_HTTP_API"),PropertiesUtil.getProperty("SZHB_KEY"));
@@ -44,15 +47,10 @@
public static EStockType getEStockTypeByCode(String code){
if(EStockType.US.getCode().equals(code)){
return US;
-
- }else if(EStockType.HK.getCode().equals(code)){
- return HK;
- }else if(EStockType.MAS.getCode().equals(code)){
- return MAS;
- }else if(EStockType.IN.getCode().equals(code)){
- return IN;
+ }else if(EStockType.MX.getCode().equals(code)){
+ return MX;
}else{
- return MAS;
+ return US;
}
}
diff --git a/src/main/java/com/nq/service/impl/SiteNewsServiceImpl.java b/src/main/java/com/nq/service/impl/SiteNewsServiceImpl.java
index fb7a0d9..00908c5 100644
--- a/src/main/java/com/nq/service/impl/SiteNewsServiceImpl.java
+++ b/src/main/java/com/nq/service/impl/SiteNewsServiceImpl.java
@@ -24,6 +24,8 @@
import java.util.Base64;
import java.util.Date;
import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
/**
* 新闻资讯
@@ -132,7 +134,22 @@
@Override
public void grabNews() {
- addNews(1, PropertiesUtil.getProperty("JS_IN_HTTP_URL") + "stock-markets?key=" + PropertiesUtil.getProperty("JS_IN_KEY") + "&type=6");
+ // 创建固定大小的线程池,根据需求调整线程数量
+ ExecutorService executor = Executors.newFixedThreadPool(2);
+ try {
+ // 提交美国新闻抓取任务
+ executor.submit(() ->
+ addNews(1, PropertiesUtil.getProperty("US_HTTP_API") + "stock-markets?key=" + PropertiesUtil.getProperty("US_KEY") + "&type=1")
+ );
+ // 提交墨西哥新闻抓取任务
+ executor.submit(() ->
+ addNews(1, PropertiesUtil.getProperty("MX_HTTP_API") + "stock-markets?key=" + PropertiesUtil.getProperty("MX_KEY") + "&type=1")
+ );
+ } finally {
+ // 关闭线程池
+ executor.shutdown();
+ }
+
}
private void addNews(Integer type, String url) {
diff --git a/src/main/java/com/nq/service/impl/UserStockSubscribeServiceImpl.java b/src/main/java/com/nq/service/impl/UserStockSubscribeServiceImpl.java
index f202434..34261d8 100644
--- a/src/main/java/com/nq/service/impl/UserStockSubscribeServiceImpl.java
+++ b/src/main/java/com/nq/service/impl/UserStockSubscribeServiceImpl.java
@@ -191,7 +191,7 @@
// bound = new BigDecimal(model.getApplyNums()).multiply(stockSubscribe.getPrice());
// }
//
- BigDecimal useEnaAmount = iUserAssetsServices.getAvailableBalance(EStockType.IN.getCode(), user.getId());
+ BigDecimal useEnaAmount = iUserAssetsServices.getAvailableBalance(EStockType.US.getCode(), user.getId());
if(useEnaAmount.compareTo(bound)<0){
return ServerResponse.createByErrorMsg("余额不足,配售失败",request);
}
@@ -210,7 +210,7 @@
UserStockSubscribe userStockSubscribe = Convert.convert(UserStockSubscribe.class, model);
userStockSubscribe.setNewStockId(stockSubscribe.getNewlistId());
ret = userStockSubscribeMapper.insert(userStockSubscribe);
- iUserAssetsServices.availablebalanceChange(EStockType.IN.getCode(), user.getId(),EUserAssets.BUY,bound.negate(),"","");
+ iUserAssetsServices.availablebalanceChange(EStockType.US.getCode(), user.getId(),EUserAssets.BUY,bound.negate(),"","");
if (ret > 0) {
return ServerResponse.createBySuccessMsg("配售成功",request);
} else {
@@ -295,7 +295,7 @@
}
BigDecimal cCount = new BigDecimal(model.getApplyNums()-model.getApplyNumber());
BigDecimal tMoney = ((stockSubscribe.getMinPrice() != null ? stockSubscribe.getMinPrice() : stockSubscribe.getPrice())).multiply(cCount);
- iUserAssetsServices.availablebalanceChange(EStockType.IN.getCode(),userStockSubscribe.getUserId(),
+ iUserAssetsServices.availablebalanceChange(EStockType.US.getCode(),userStockSubscribe.getUserId(),
EUserAssets.TOP_UP,tMoney,"","");
model.setBond((stockSubscribe.getMinPrice() != null ? stockSubscribe.getMinPrice() : stockSubscribe.getPrice()).multiply(BigDecimal.valueOf(model.getApplyNumber())));
model.setDbMoney(BigDecimal.ZERO);
@@ -499,14 +499,14 @@
userStockSubscribe.setSubmitTime(DateTimeUtil.getCurrentDate());
userStockSubscribe.setStatus(4);
BigDecimal bigDecimal = iUserAssetsServices.
- getAvailableBalance(EStockType.IN.getCode(),
+ getAvailableBalance(EStockType.US.getCode(),
userStockSubscribe.getUserId());
BigDecimal multiply = userStockSubscribe.getBuyPrice().multiply(new BigDecimal(userStockSubscribe.getApplyNumber()));
if(bigDecimal.compareTo(multiply) <= 0){
return ServerResponse.createByErrorMsg("余额不足",request);
}
- iUserAssetsServices.availablebalanceChange(EStockType.IN.getCode(),userStockSubscribe.getUserId(),
+ iUserAssetsServices.availablebalanceChange(EStockType.US.getCode(),userStockSubscribe.getUserId(),
EUserAssets.BUY,multiply.negate(),"","");
userStockSubscribe.setDbMoney(BigDecimal.ZERO);
userStockSubscribeMapper.update1(userStockSubscribe);
diff --git a/src/main/java/com/nq/utils/task/stock/StockTask.java b/src/main/java/com/nq/utils/task/stock/StockTask.java
index 635286c..6e97651 100644
--- a/src/main/java/com/nq/utils/task/stock/StockTask.java
+++ b/src/main/java/com/nq/utils/task/stock/StockTask.java
@@ -25,6 +25,9 @@
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@@ -67,10 +70,27 @@
return;
}
if (syncINStockDataLock.tryLock()) {
+ ExecutorService executor = Executors.newFixedThreadPool(2);
+ Future<?> usFuture = null;
+ Future<?> mxFuture = null;
try {
syncINStockData.set(true); // 设置处理中标识为true
- loadAllStock(EStockType.IN);
+
+ // 并行执行US和MX的股票数据加载
+ usFuture = executor.submit(() -> loadAllStock(EStockType.US));
+ mxFuture = executor.submit(() -> loadAllStock(EStockType.MX));
+
+ // 等待两个任务都完成
+ usFuture.get();
+ mxFuture.get();
+ } catch (Exception e) {
+ Thread.currentThread().interrupt();
+ log.error("同步股票数据出错", e);
} finally {
+ // 关闭线程池
+ if (executor != null) {
+ executor.shutdown();
+ }
syncINStockDataLock.unlock();
syncINStockData.set(false); // 设置处理中标识为false
}
diff --git a/src/main/java/com/nq/ws/MXWebsocketRunClient.java b/src/main/java/com/nq/ws/MXWebsocketRunClient.java
new file mode 100644
index 0000000..d1f3d19
--- /dev/null
+++ b/src/main/java/com/nq/ws/MXWebsocketRunClient.java
@@ -0,0 +1,127 @@
+package com.nq.ws;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import com.nq.enums.EStockType;
+import com.nq.pojo.StockRealTimeBean;
+import com.nq.utils.redis.RedisKeyUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.message.BasicNameValuePair;
+import org.java_websocket.client.WebSocketClient;
+import org.java_websocket.handshake.ServerHandshake;
+
+import java.io.IOException;
+import java.lang.reflect.Type;
+import java.net.URI;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+
+@Slf4j
+public class MXWebsocketRunClient extends WebSocketClient {
+
+ private EStockType eStockType;
+ public MXWebsocketRunClient(URI serverUri,
+ EStockType eStockType
+ ) {
+ super(serverUri);
+ this.eStockType = eStockType;
+ }
+
+ private static HttpClient httpClient = HttpClients.createDefault(); // 单例化 HttpClient
+
+
+ private static HttpPost httpPost;
+ static {
+ httpPost = new HttpPost("http://127.0.0.1:8001/api/sendNotification"); // 初始化 HttpPost
+ }
+
+ @Override
+ public void onOpen(ServerHandshake serverHandshake) {
+ send(("key:"+ eStockType.getStockKey()+":"+eStockType.getContryId()).getBytes());
+ Timer heartbeatTimer;
+ // 启动心跳定时器
+ heartbeatTimer = new Timer();
+ heartbeatTimer.schedule(new TimerTask() {
+ @Override
+ public void run() {
+ send(("key:"+ eStockType.getStockKey()+":"+eStockType.getContryId()).getBytes());
+ }
+ }, 0, 3000); // 每3秒发送一次心跳消息
+ }
+
+ @Override
+ public void onMessage(String message) {
+ if (message.contains("身份验证成功") || message.contains("pong") || message.contains("身份验证失败")) {
+ System.out.println("mx" + message);
+ return;
+ }
+ System.out.println("mx2" + message);
+ Map<String, String> stringObjectMap = jsonToMap(message);
+ StockRealTimeBean stockRealTimeBean = new StockRealTimeBean();
+ stockRealTimeBean.setPid(stringObjectMap.get("Id").toString());
+ stockRealTimeBean.setLast(stringObjectMap.get("Last").toString());
+ stockRealTimeBean.setBid(stringObjectMap.get("Bid").toString());
+ stockRealTimeBean.setAsk(stringObjectMap.get("Ask").toString());
+ stockRealTimeBean.setHigh(stringObjectMap.get("High").toString());
+ stockRealTimeBean.setLow(stringObjectMap.get("Low").toString());
+ stockRealTimeBean.setPc(stringObjectMap.get("Chg").toString());
+ stockRealTimeBean.setPcp(stringObjectMap.get("ChgPct").toString()+"%");
+ stockRealTimeBean.setTime(stringObjectMap.get("Time").toString());
+ RedisKeyUtil.setCacheRealTimeStock(EStockType.MX,stockRealTimeBean);
+ ObjectMapper objectMapper = new ObjectMapper();
+ try {
+ if(!stockRealTimeBean.getPcp().contains("-")){
+ stockRealTimeBean.setPcp("+"+stringObjectMap.get("ChgPct").toString()+"%");
+ }
+ String json = objectMapper.writeValueAsString(stockRealTimeBean);
+ sendLoca(json);
+ StockRealTimeBean stockDetailBean = new Gson().fromJson(message, StockRealTimeBean.class);
+ RedisKeyUtil.setCacheRealTimeStock(EStockType.MX,stockDetailBean);
+ } catch (JsonProcessingException e) {
+ log.error("websocket 墨西哥股票 消息错误:{}", e.getMessage());
+ }
+ }
+
+ public static Map<String, String> jsonToMap(String json) {
+ Gson gson = new Gson();
+ Type type = new TypeToken<Map<String, String>>(){}.getType();
+ return gson.fromJson(json, type);
+ }
+
+ @Override
+ public void onClose(int i, String s, boolean b) {
+ log.info("websocket 墨西哥股票 关闭"+1);
+ }
+
+ @Override
+ public void onError(Exception e) {
+ log.info("websocket 墨西哥股票 错误");
+ }
+
+ public void sendLoca(String message) {
+ try {
+ // 准备 form-data 参数
+ List<BasicNameValuePair> params = new ArrayList<>();
+ params.add(new BasicNameValuePair("message", message));
+
+ // 设置编码格式为 UTF-8
+ UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, StandardCharsets.UTF_8);
+ httpPost.setEntity(entity); // 设置 HttpPost 对象的参数
+
+ // 发送请求
+ HttpResponse response = httpClient.execute(httpPost);
+
+ // 处理响应
+ int statusCode = response.getStatusLine().getStatusCode();
+ } catch (IOException e) {
+ log.error("Http 请求错误", e);
+ }
+ }
+}
diff --git a/src/main/java/com/nq/ws/WebSocketClientBeanConfig.java b/src/main/java/com/nq/ws/WebSocketClientBeanConfig.java
index 3b8a3a0..5e2d6ec 100644
--- a/src/main/java/com/nq/ws/WebSocketClientBeanConfig.java
+++ b/src/main/java/com/nq/ws/WebSocketClientBeanConfig.java
@@ -22,26 +22,48 @@
Map<String, WebSocketClient> retMap = new HashMap<>(2);
try {
- WebsocketRunClient websocketRunClient = new WebsocketRunClient(new URI(PropertiesUtil.getProperty("JS_IN_WS_URL")),EStockType.IN);
- websocketRunClient.connect();
- websocketRunClient.setConnectionLostTimeout(0);
- new Thread(() -> {
- while (true) {
+ WebsocketRunClient usWebsocketRunClient = new WebsocketRunClient(new URI(PropertiesUtil.getProperty("US_WS_URL")),EStockType.US);
+ usWebsocketRunClient.connect();
+ usWebsocketRunClient.setConnectionLostTimeout(0);
+ startHeartbeatThread(usWebsocketRunClient);
+ retMap.put(EStockType.US.getStockKey(), usWebsocketRunClient);
+ } catch (Exception e) {
+ log.error("usWebsocketRunClient 异常: {}", e.getMessage());
+ }
+ try {
+ MXWebsocketRunClient mxWebsocketRunClient = new MXWebsocketRunClient(new URI(PropertiesUtil.getProperty("MX_WS_URL")),EStockType.MX);
+ mxWebsocketRunClient.connect();
+ mxWebsocketRunClient.setConnectionLostTimeout(0);
+ startHeartbeatThread(mxWebsocketRunClient);
+ retMap.put(EStockType.MX.getStockKey(), mxWebsocketRunClient);
+ } catch (Exception e) {
+ log.error("mxWebsocketRunClient 异常: {}", e.getMessage());
+ }
+ return retMap;
+ }
+
+ private void startHeartbeatThread(WebSocketClient client) {
+ new Thread(() -> {
+ while (true) {
+ try {
+ Thread.sleep(8000);
+ if (client.isOpen()) { // 先检查连接状态
+ client.send("heartbeat".getBytes());
+ } else {
+ client.reconnect();
+ client.setConnectionLostTimeout(0);
+ }
+ } catch (Exception e) {
+ log.error("心跳线程异常, 尝试重连: {}", e.getMessage());
try {
- Thread.sleep(8000);
- websocketRunClient.send("heartbeat".getBytes());
- } catch (Exception e) {
- websocketRunClient.reconnect();
- websocketRunClient.setConnectionLostTimeout(0);
+ client.reconnect();
+ client.setConnectionLostTimeout(0);
+ } catch (Exception re) {
+ log.error("重连失败: {}", re.getMessage());
}
}
- }).start();
- } catch (Exception e) {
- }
-
-
-
- return retMap;
+ }
+ }).start();
}
diff --git a/src/main/java/com/nq/ws/WebsocketRunClient.java b/src/main/java/com/nq/ws/WebsocketRunClient.java
index 9c2fd8a..5477bd8 100644
--- a/src/main/java/com/nq/ws/WebsocketRunClient.java
+++ b/src/main/java/com/nq/ws/WebsocketRunClient.java
@@ -6,9 +6,6 @@
import com.google.gson.reflect.TypeToken;
import com.nq.enums.EStockType;
import com.nq.pojo.StockRealTimeBean;
-import com.nq.service.IMandatoryLiquidationService;
-import com.nq.service.impl.MandatoryLiquidationService;
-import com.nq.utils.ApplicationContextRegisterUtil;
import com.nq.utils.redis.RedisKeyUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpResponse;
@@ -61,35 +58,37 @@
}
@Override
- public void onMessage(String s) {
- if(!s.equals("pong") && !s.equals("身份验证成功")){
- Map<String, String> stringObjectMap = jsonToMap(s);
- StockRealTimeBean stockRealTimeBean = new StockRealTimeBean();
- stockRealTimeBean.setPid(stringObjectMap.get("Id").toString());
- stockRealTimeBean.setLast(stringObjectMap.get("Last").toString());
- stockRealTimeBean.setBid(stringObjectMap.get("Bid").toString());
- stockRealTimeBean.setAsk(stringObjectMap.get("Ask").toString());
- stockRealTimeBean.setHigh(stringObjectMap.get("High").toString());
- stockRealTimeBean.setLow(stringObjectMap.get("Low").toString());
- stockRealTimeBean.setPc(stringObjectMap.get("Chg").toString());
- stockRealTimeBean.setPcp(stringObjectMap.get("ChgPct").toString()+"%");
- stockRealTimeBean.setTime(stringObjectMap.get("Time").toString());
- RedisKeyUtil.setCacheRealTimeStock(EStockType.IN,stockRealTimeBean);
- ObjectMapper objectMapper = new ObjectMapper();
- try {
- if(!stockRealTimeBean.getPcp().contains("-")){
- stockRealTimeBean.setPcp("+"+stringObjectMap.get("ChgPct").toString()+"%");
- }
- String json = objectMapper.writeValueAsString(stockRealTimeBean);
- sendLoca(json);
- StockRealTimeBean stockDetailBean = new Gson().fromJson(s, StockRealTimeBean.class);
- RedisKeyUtil.setCacheRealTimeStock(EStockType.IN,stockDetailBean);
- } catch (JsonProcessingException e) {
- throw new RuntimeException(e);
+ public void onMessage(String message) {
+ if (message.contains("身份验证成功") || message.contains("pong") || message.contains("身份验证失败")) {
+ System.out.println("us" + message);
+ return;
+ }
+ System.out.println("us2" + message);
+ Map<String, String> stringObjectMap = jsonToMap(message);
+ StockRealTimeBean stockRealTimeBean = new StockRealTimeBean();
+ stockRealTimeBean.setPid(stringObjectMap.get("Id").toString());
+ stockRealTimeBean.setLast(stringObjectMap.get("Last").toString());
+ stockRealTimeBean.setBid(stringObjectMap.get("Bid").toString());
+ stockRealTimeBean.setAsk(stringObjectMap.get("Ask").toString());
+ stockRealTimeBean.setHigh(stringObjectMap.get("High").toString());
+ stockRealTimeBean.setLow(stringObjectMap.get("Low").toString());
+ stockRealTimeBean.setPc(stringObjectMap.get("Chg").toString());
+ stockRealTimeBean.setPcp(stringObjectMap.get("ChgPct").toString()+"%");
+ stockRealTimeBean.setTime(stringObjectMap.get("Time").toString());
+ RedisKeyUtil.setCacheRealTimeStock(EStockType.US,stockRealTimeBean);
+ ObjectMapper objectMapper = new ObjectMapper();
+ try {
+ System.out.println("sdd");
+ if(!stockRealTimeBean.getPcp().contains("-")){
+ stockRealTimeBean.setPcp("+"+stringObjectMap.get("ChgPct").toString()+"%");
}
-
- }else{
- log.error("websocket 消息错误:"+s);
+ String json = objectMapper.writeValueAsString(stockRealTimeBean);
+ sendLoca(json);
+ StockRealTimeBean stockDetailBean = new Gson().fromJson(message, StockRealTimeBean.class);
+ System.out.println(stockDetailBean);
+ RedisKeyUtil.setCacheRealTimeStock(EStockType.US,stockDetailBean);
+ } catch (JsonProcessingException e) {
+ log.error("websocket 美国股票 消息错误:{}", e.getMessage());
}
}
@@ -101,12 +100,12 @@
@Override
public void onClose(int i, String s, boolean b) {
- log.info("websocket 印度股票 关闭"+1);
+ log.info("websocket 美国股票 关闭"+1);
}
@Override
public void onError(Exception e) {
- log.info("websocket 错误");
+ log.info("websocket 美国股票 错误" + e.getMessage());
}
public void sendLoca(String message) {
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 5fbe190..bbace32 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -52,14 +52,22 @@
JS_IN_WS_URL = ws://api-in-pro-ws.js-stock.top
JS_IN_KEY = xKChgi47AP1NMwMeYI3c
-US_HTTP_API = http://api-us.js-stock.top/
-US_WS_URL = ws://ws-us.js-stock.top
-US_KEY = jZFrku4RGQjP87Hmq5tm
+#US_HTTP_API = http://api-us.js-stock.top/
+#US_WS_URL = ws://ws-us.js-stock.top
+#US_KEY = jZFrku4RGQjP87Hmq5tm
HK_HTTP_API = http://test.js-stock.top/
HK_WS_URL = ws://test-ws.js-stock.top
HK_KEY = mG8QQDdjGuLjLnrryd0B
+US_HTTP_API = http://api-us-v2.js-stock.top/
+US_WS_URL = ws://api-us-v2-ws.js-stock.top
+US_KEY = x45TBc52rI0nH9Hsyqeo
+
+MX_HTTP_API = http://api-mx.js-stock.top/
+MX_WS_URL = ws://api-mx-ws.js-stock.top
+MX_KEY = nFQivDtnjHZliFGPF1Gu
+
#HK_HTTP_API = http://api-v1.js-stock.top/
#HK_WS_URL = ws://api-v1-ws.js-stock.top
--
Gitblit v1.9.3