gao
2020-05-27 ef935bb058f0a45a815efee851aae921629d350b
Merge branch 'master' of https://chonggaoxiao:xcg523511090712@gitee.com/chonggaoxiao/new_excoin.git
56 files added
2 files modified
3753 ■■■■■ changed files
lib/taobao-sdk-java.jar patch | view | raw | blame | history
pom.xml 60 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/modules/symbols/Entity/PlatformSymbolsContractEntity.java 21 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/modules/symbols/dao/PlatformSymbolsContractDao.java 11 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/modules/symbols/service/SymbolsService.java 12 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/modules/symbols/service/impl/SymbolsServiceImpl.java 84 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/quartz/job/KlineDataUpdateJob.java 151 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/ApiClient.java 607 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/ApiException.java 33 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/request/CreateOrderRequest.java 52 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/request/DepthRequest.java 26 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/request/IntrustOrdersDetailRequest.java 62 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/Account.java 8 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/Accounts.java 48 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/AccountsResponse.java 56 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/ApiResponse.java 19 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/Balance.java 57 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/BalanceBean.java 37 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/BalanceResponse.java 47 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/Batchcancel.java 22 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/BatchcancelBean.java 34 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/BatchcancelResponse.java 47 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/Currencys.java 4 ●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/CurrencysResponse.java 55 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/Depth.java 57 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/DepthResponse.java 78 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/DetailResponse.java 67 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/Details.java 98 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/HistoryTrade.java 57 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/HistoryTradeResponse.java 67 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/HistoryTradess.java 37 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/IntrustDetail.java 194 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/IntrustDetailResponse.java 47 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/Kline.java 68 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/KlineResponse.java 55 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/KlineReturn.java 66 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/MatchresultsOrdersDetail.java 112 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/MatchresultsOrdersDetailResponse.java 47 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/Merged.java 121 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/MergedResponse.java 77 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/OrdersDetail.java 178 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/OrdersDetailResponse.java 50 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/Place.java 4 ●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/SubmitcancelResponse.java 47 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/Symbol.java 9 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/Symbols.java 98 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/SymbolsResponse.java 67 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/TimestampResponse.java 45 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/Trade.java 38 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/TradeBean.java 60 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/api/response/TradeResponse.java 70 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/mail/RequestEncoder.java 71 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/utils/mail/SubMailSend.java 133 ●●●●● patch | view | raw | blame | history
src/main/resources/logback-spring.xml 1 ●●●● patch | view | raw | blame | history
src/main/resources/mapper/platform/PlatformSymbolsContractDao.xml 5 ●●●●● patch | view | raw | blame | history
src/test/java/com/xcong/excoin/HuobiTest.java 39 ●●●●● patch | view | raw | blame | history
src/test/java/com/xcong/excoin/SmsTest.java 14 ●●●●● patch | view | raw | blame | history
src/test/java/com/xcong/excoin/SymbolsTest.java 23 ●●●●● patch | view | raw | blame | history
lib/taobao-sdk-java.jar
Binary files differ
pom.xml
@@ -29,6 +29,8 @@
        <fastjson.version>1.2.61</fastjson.version>
        <netty.version>4.1.33.Final</netty.version>
        <dom4j.version>1.6.1</dom4j.version>
        <okhttp.version>3.6.0</okhttp.version>
        <aliyun-oss.version>3.8.0</aliyun-oss.version>
    </properties>
    <dependencies>
@@ -165,6 +167,10 @@
            <artifactId>fastjson</artifactId>
            <version>${fastjson.version}</version>
        </dependency>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
@@ -182,6 +188,60 @@
            <artifactId>netty-all</artifactId>
            <version>${netty.version}</version>
        </dependency>
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>${okhttp.version}</version>
        </dependency>
        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>${aliyun-oss.version}</version>
        </dependency>
        <dependency>
            <groupId>com.huobi.sdk</groupId>
            <artifactId>huobi-client</artifactId>
            <version>1.0.8-SNAPSHOT</version>
            <scope>system</scope>
            <systemPath>${basedir}/lib/huobi-client-1.0.8-SNAPSHOT.jar</systemPath>
        </dependency>
        <!-- submail邮件 start -->
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.1.1</version>
        </dependency>
        <dependency>
            <groupId>commons-collections</groupId>
            <artifactId>commons-collections</artifactId>
            <version>3.2.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.3.2</version>
        </dependency>
        <dependency>
            <groupId>net.sf.ezmorph</groupId>
            <artifactId>ezmorph</artifactId>
            <version>1.0.3</version>
        </dependency>
        <dependency>
            <groupId>net.sf.json-lib</groupId>
            <artifactId>json-lib</artifactId>
            <version>2.2.3</version>
            <classifier>jdk15</classifier>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpmime</artifactId>
            <version>4.3.5</version>
        </dependency>
        <!-- submail邮件 end -->
    </dependencies>
    <build>
src/main/java/com/xcong/excoin/modules/symbols/Entity/PlatformSymbolsContractEntity.java
New file
@@ -0,0 +1,21 @@
package com.xcong.excoin.modules.symbols.Entity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serializable;
/**
 * @author wzy
 * @date 2020-05-26
 **/
@Data
@TableName("platform_symbols_contract")
public class PlatformSymbolsContractEntity implements Serializable {
    private static final long serialVersionUID = -1L;
    private Long id;
    private String name;
}
src/main/java/com/xcong/excoin/modules/symbols/dao/PlatformSymbolsContractDao.java
New file
@@ -0,0 +1,11 @@
package com.xcong.excoin.modules.symbols.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xcong.excoin.modules.symbols.Entity.PlatformSymbolsContractEntity;
/**
 *
 * @author wzy
 */
public interface PlatformSymbolsContractDao extends BaseMapper<PlatformSymbolsContractEntity> {
}
src/main/java/com/xcong/excoin/modules/symbols/service/SymbolsService.java
New file
@@ -0,0 +1,12 @@
package com.xcong.excoin.modules.symbols.service;
/**
 * @author wzy
 * @date 2020-05-26
 **/
public interface SymbolsService {
    public void updateSymbolsKine(String time);
}
src/main/java/com/xcong/excoin/modules/symbols/service/impl/SymbolsServiceImpl.java
New file
@@ -0,0 +1,84 @@
package com.xcong.excoin.modules.symbols.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.huobi.client.model.Candlestick;
import com.xcong.excoin.common.enumerates.SymbolEnum;
import com.xcong.excoin.modules.symbols.service.SymbolsService;
import com.xcong.excoin.utils.RedisUtils;
import com.xcong.excoin.utils.api.ApiClient;
import com.xcong.excoin.utils.api.response.Kline;
import com.xcong.excoin.utils.api.response.KlineResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
/**
 * @author wzy
 * @date 2020-05-26
 **/
@Slf4j
@Service
public class SymbolsServiceImpl implements SymbolsService {
    @Resource
    private RedisUtils redisUtils;
    private static final String API_KEY = "3938f004-bfe31905-f7581c1a-6abe0";
    private static final String API_SECRET = "a0f7a154-ghxertfvbf-6ce2d90c-a0bab";
    private static volatile ApiClient client;
    private static ApiClient getClient() {
        if (client == null) {
            synchronized (ApiClient.class) {
                if (client == null) {
                    client = new ApiClient(API_KEY, API_SECRET);
                }
            }
        }
        return client;
    }
    @Override
    public void updateSymbolsKine(String time) {
        synchronized (this) {
            //更新币币交易K线历史数据
            for (SymbolEnum symbol : SymbolEnum.values()) {
                log.info(symbol.getValue());
                String[] symbols = symbol.getValue().toLowerCase().split("/");
                ApiClient client = new ApiClient(API_KEY, API_SECRET);
                KlineResponse kline = client.kline(symbols[0] + symbols[1], time, 1000 + "");
                log.info("{}", JSONObject.toJSONString(kline));
                if (kline != null) {
                    if ("ok".equalsIgnoreCase(kline.getStatus())) {
                        List<Kline> klines = (List<Kline>) kline.data;
                        List<Candlestick> list = new ArrayList<Candlestick>();
                        Candlestick candlestick = null;
                        for (Kline kline1 : klines) {
                            candlestick = new Candlestick();
                            candlestick.setAmount(BigDecimal.valueOf(kline1.getAmount()));
                            candlestick.setClose(BigDecimal.valueOf(kline1.getClose()));
                            candlestick.setCount(kline1.getCount());
                            candlestick.setHigh(BigDecimal.valueOf(kline1.getHigh()));
                            candlestick.setLow(BigDecimal.valueOf(kline1.getLow()));
                            candlestick.setVolume(BigDecimal.valueOf(kline1.getVol()));
                            candlestick.setTimestamp(kline1.getId() * 1000);
                            candlestick.setOpen(BigDecimal.valueOf(kline1.getOpen()));
                            list.add(candlestick);
                        }
                        if (klines.size() > 0) {
//                            redisUtils.set("KINE_" + symbol.getValue() + "_" + time, list);
                        }
                    }
                }
            }
        }
    }
}
src/main/java/com/xcong/excoin/quartz/job/KlineDataUpdateJob.java
New file
@@ -0,0 +1,151 @@
package com.xcong.excoin.quartz.job;
import com.xcong.excoin.modules.symbols.service.SymbolsService;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
 * k线数据更新任务
 *
 * @author wzy
 * @date 2020-05-26
 **/
@Component
public class KlineDataUpdateJob {
    @Resource
    private SymbolsService symbolsService;
    private static boolean min1 = true;
    private static boolean min5 = true;
    private static boolean min30 = true;
    private static boolean min60 = true;
    private static boolean hour4 = true;
    private static boolean day1 = true;
    private static boolean week = true;
    /**
     * 定时更新每一分钟的K线数据
     */
    @Scheduled(cron = "0/1 * * * * ? ")
    public void updateSymbolsKineOneMin() {
        if (min1) {
            min1 = false;
            try {
                symbolsService.updateSymbolsKine("1min");
            } catch (Exception e) {
                // e.printStackTrace();
            } finally {
                min1 = true;
            }
        }
    }
    /**
     * 定时更新每十分钟的K线数据
     */
    @Scheduled(cron = "0/10 * * * * ? ")
    public void updateSymbolsKineFiveMin() {
        if (min5) {
            min5 = false;
            try {
                symbolsService.updateSymbolsKine("5min");
            } catch (Exception e) {
                //e.printStackTrace();
            } finally {
                min5 = true;
            }
        }
    }
    /**
     * 定时更新每30分钟的K线数据
     */
    @Scheduled(cron = "0/120 * * * * ? ")
    public void updateSymbolsKineMin() {
        if (min30) {
            min30 = false;
            try {
                symbolsService.updateSymbolsKine("30min");
            } catch (Exception e) {
                //e.printStackTrace();
            } finally {
                min30 = true;
            }
        }
    }
    /**
     * 定时更新1小时的K线数据
     */
    @Scheduled(cron = "* 0/2 * * * ? ")
    public void updateSymbolsKineOneHour() {
        if (min60) {
            min60 = false;
            try {
                symbolsService.updateSymbolsKine("60min");
            } catch (Exception e) {
                //e.printStackTrace();
            } finally {
                min60 = true;
            }
        }
    }
    /**
     * 定时更新4小时的K线数据
     */
    @Scheduled(cron = "* 0/1 * * * ? ")
    public void updateSymbolsKineFourHour() {
        if (hour4) {
            hour4 = false;
            try {
                symbolsService.updateSymbolsKine("4hour");
            } catch (Exception e) {
                //e.printStackTrace();
            } finally {
                hour4 = true;
            }
        }
    }
    /**
     * 定时更新1天的K线数据
     */
    @Scheduled(cron = "* 0/1 * * * ? ")
    public void updateSymbolsKineOneDay() {
        if (day1) {
            day1 = false;
            try {
                symbolsService.updateSymbolsKine("1day");
            } catch (Exception e) {
                //e.printStackTrace();
            } finally {
                day1 = true;
            }
        }
    }
    /**
     * 定时更新1周的K线数据
     */
    @Scheduled(cron = "* 0/1 * * * ? ")
    public void updateSymbolsKineOneWeek() {
        if (week) {
            week = false;
            try {
                symbolsService.updateSymbolsKine("1week");
            } catch (Exception e) {
                // e.printStackTrace();
            } finally {
                week = true;
            }
        }
    }
}
src/main/java/com/xcong/excoin/utils/api/ApiClient.java
New file
@@ -0,0 +1,607 @@
package com.xcong.excoin.utils.api;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.xcong.excoin.utils.api.request.CreateOrderRequest;
import com.xcong.excoin.utils.api.request.IntrustOrdersDetailRequest;
import com.xcong.excoin.utils.api.response.*;
import okhttp3.*;
import okhttp3.OkHttpClient.Builder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
 * API client.
 *
 * @Date 2018/1/14
 * @Time 16:02
 */
public class ApiClient {
    static final int CONN_TIMEOUT = 50;
    static final int READ_TIMEOUT = 50;
    static final int WRITE_TIMEOUT = 50;
    // static final String API_URL = "https://api.huobi.pro:443";
    // static final String API_URL = "https://api.huobi.pro";
    // static final String API_URL = "https://api.hbdm.com";
    // static final String API_URL = "https://api.huobi.br.com";
    // static final String API_URL = "https://api.btcgateway.pro";
    static final String API_URL = "https://api.hadax.com";
    static final String API_HOST = getHost();
    static final MediaType JSON = MediaType.parse("application/json");
    static final OkHttpClient client = createOkHttpClient();
    final String accessKeyId;
    final String accessKeySecret;
    final String assetPassword;
    /**
     * 创建一个ApiClient实例
     *
     * @param accessKeyId     AccessKeyId
     * @param accessKeySecret AccessKeySecret
     */
    public ApiClient(String accessKeyId, String accessKeySecret) {
        this.accessKeyId = accessKeyId;
        this.accessKeySecret = accessKeySecret;
        this.assetPassword = null;
    }
    /**
     * 创建一个ApiClient实例
     *
     * @param accessKeyId     AccessKeyId
     * @param accessKeySecret AccessKeySecret
     * @param assetPassword   AssetPassword
     */
    public ApiClient(String accessKeyId, String accessKeySecret, String assetPassword) {
        this.accessKeyId = accessKeyId;
        this.accessKeySecret = accessKeySecret;
        this.assetPassword = assetPassword;
    }
    /**
     * 查询交易对
     *
     * @return List of symbols.
     */
    public List<Symbol> getSymbols() {
        ApiResponse<List<Symbol>> resp =
                get("/v1/common/symbols", null, new TypeReference<ApiResponse<List<Symbol>>>() {
                });
        return resp.checkAndReturn();
    }
    /**
     * 查询所有账户信息
     *
     * @return List of accounts.
     */
    public List<Account> getAccounts() {
        ApiResponse<List<Account>> resp =
                get("/v1/account/accounts", null, new TypeReference<ApiResponse<List<Account>>>() {
                });
        return resp.checkAndReturn();
    }
    /**
     * 创建订单
     *
     * @param request CreateOrderRequest object.
     * @return Order id.
     */
    public Long createOrder(CreateOrderRequest request) {
        ApiResponse<Long> resp =
                post("/v1/order/orders/place", request, new TypeReference<ApiResponse<Long>>() {
                });
        return resp.checkAndReturn();
    }
    /**
     * 执行订单
     *
     * @param orderId The id of created order.
     * @return Order id.
     */
    public String placeOrder(long orderId) {
        ApiResponse<String> resp = post("/v1/order/orders/" + orderId + "/place", null,
                new TypeReference<ApiResponse<String>>() {
                });
        return resp.checkAndReturn();
    }
    // ----------------------------------------行情API-------------------------------------------
    /**
     * GET /market/history/kline 获取K线数据
     *
     * @param symbol
     * @param period
     * @param size
     * @return
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    public KlineResponse kline(String symbol, String period, String size) {
        HashMap map = new HashMap();
        map.put("symbol", symbol);
        map.put("period", period);
        map.put("size", size);
        KlineResponse resp = get("/market/history/kline", map, new TypeReference<KlineResponse<List<Kline>>>() {
        });
        return resp;
    }
    /**
     * GET /market/detail/merged 获取聚合行情(Ticker)
     *
     * @param symbol
     * @return
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    public MergedResponse merged(String symbol) {
        HashMap map = new HashMap();
        map.put("symbol", symbol);
        MergedResponse resp = get("/market/detail/merged", map, new TypeReference<MergedResponse<List<Merged>>>() {
        });
        return resp;
    }
    /**
     * GET /market/depth 获取 Market Depth 数据
     *
     * @return
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    public DepthResponse depth(String symbol, String type, String depth) {
        HashMap map = new HashMap();
        map.put("symbol", symbol);
        map.put("type", type);
        map.put("depth", depth);
        DepthResponse resp = get("/market/depth", map, new TypeReference<DepthResponse<List<Depth>>>() {
        });
        return resp;
    }
    /**
     * GET /market/trade 获取 Trade Detail 数据
     *
     * @param symbol
     * @return
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    public TradeResponse trade(String symbol) {
        HashMap map = new HashMap();
        map.put("symbol", symbol);
        TradeResponse resp = get("/market/trade", map, new TypeReference<TradeResponse>() {
        });
        return resp;
    }
    /**
     * GET /market/history/trade 批量获取最近的交易记录
     *
     * @param symbol
     * @param size
     * @return
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    public HistoryTradeResponse historyTrade(String symbol, String size) {
//        System.out.println("symbol = "+symbol+"  size = "+size);
        HashMap map = new HashMap();
        map.put("symbol", symbol);
        map.put("size", size);
        HistoryTradeResponse resp = get("/market/history/trade", map, new TypeReference<HistoryTradeResponse>() {
        });
        return resp;
    }
    /**
     * GET /market/detail 获取 Market Detail 24小时成交量数据
     *
     * @param symbol
     * @return
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    public DetailResponse detail(String symbol) {
        HashMap map = new HashMap();
        map.put("symbol", symbol);
        DetailResponse resp = get("/market/detail", map, new TypeReference<DetailResponse<Details>>() {
        });
        return resp;
    }
    /**
     * GET /v1/common/symbols 查询系统支持的所有交易对及精度
     *
     * @param symbol
     * @return
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    public SymbolsResponse symbols(String symbol) {
        HashMap map = new HashMap();
        map.put("symbol", symbol);
        SymbolsResponse resp = get("/v1/common/symbols", map, new TypeReference<SymbolsResponse<Symbols>>() {
        });
        return resp;
    }
    /**
     * GET /v1/common/currencys 查询系统支持的所有币种
     *
     * @param symbol
     * @return
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    public CurrencysResponse currencys(String symbol) {
        HashMap map = new HashMap();
        map.put("symbol", symbol);
        CurrencysResponse resp = get("/v1/common/currencys", map, new TypeReference<CurrencysResponse>() {
        });
        return resp;
    }
    /**
     * GET /v1/common/timestamp 查询系统当前时间
     *
     * @return
     */
    public TimestampResponse timestamp() {
        TimestampResponse resp = get("/v1/common/timestamp", null, new TypeReference<TimestampResponse>() {
        });
        return resp;
    }
    /**
     * GET /v1/account/accounts 查询当前用户的所有账户(即account-id)
     *
     * @return
     */
    @SuppressWarnings({"rawtypes"})
    public AccountsResponse accounts() {
        AccountsResponse resp = get("/v1/account/accounts", null, new TypeReference<AccountsResponse<List<Accounts>>>() {
        });
        return resp;
    }
    /**
     * GET /v1/account/accounts/{account-id}/balance 查询指定账户的余额
     *
     * @param accountId
     * @return
     */
    @SuppressWarnings({"rawtypes"})
    public BalanceResponse balance(String accountId) {
        BalanceResponse resp = get("/v1/account/accounts/" + accountId + "/balance", null, new TypeReference<BalanceResponse<Balance>>() {
        });
        return resp;
    }
    /**
     * POST /v1/order/orders/{order-id}/submitcancel 申请撤销一个订单请求
     *
     * @param orderId
     * @return
     */
    public SubmitcancelResponse submitcancel(String orderId) {
        SubmitcancelResponse resp = post("/v1/order/orders/" + orderId + "/submitcancel", null, new TypeReference<SubmitcancelResponse>() {
        });
        return resp;
    }
    /**
     * POST /v1/order/orders/batchcancel 批量撤销订单
     *
     * @param orderList
     * @return
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    public BatchcancelResponse submitcancels(List orderList) {
        Map<String, List> parameterMap = new HashMap();
        parameterMap.put("order-ids", orderList);
        BatchcancelResponse resp = post("/v1/order/orders/batchcancel", parameterMap, new TypeReference<BatchcancelResponse<Batchcancel<List, List<BatchcancelBean>>>>() {
        });
        return resp;
    }
    /**
     * GET /v1/order/orders/{order-id} 查询某个订单详情
     *
     * @param orderId
     * @return
     */
    @SuppressWarnings({"rawtypes"})
    public OrdersDetailResponse ordersDetail(String orderId) {
        OrdersDetailResponse resp = get("/v1/order/orders/" + orderId, null, new TypeReference<OrdersDetailResponse>() {
        });
        return resp;
    }
    /**
     * GET /v1/order/orders/{order-id}/matchresults 查询某个订单的成交明细
     *
     * @param orderId
     * @return
     */
    @SuppressWarnings({"rawtypes"})
    public MatchresultsOrdersDetailResponse matchresults(String orderId) {
        MatchresultsOrdersDetailResponse resp = get("/v1/order/orders/" + orderId + "/matchresults", null, new TypeReference<MatchresultsOrdersDetailResponse>() {
        });
        return resp;
    }
    @SuppressWarnings({"rawtypes", "unchecked"})
    public IntrustDetailResponse intrustOrdersDetail(IntrustOrdersDetailRequest req) {
        HashMap map = new HashMap();
        map.put("symbol", req.symbol);
        map.put("states", req.states);
        if (req.startDate != null) {
            map.put("startDate", req.startDate);
        }
        if (req.startDate != null) {
            map.put("start-date", req.startDate);
        }
        if (req.endDate != null) {
            map.put("end-date", req.endDate);
        }
        if (req.types != null) {
            map.put("types", req.types);
        }
        if (req.from != null) {
            map.put("from", req.from);
        }
        if (req.direct != null) {
            map.put("direct", req.direct);
        }
        if (req.size != null) {
            map.put("size", req.size);
        }
        IntrustDetailResponse resp = get("/v1/order/orders/", map, new TypeReference<IntrustDetailResponse<List<IntrustDetail>>>() {
        });
        return resp;
    }
//  public IntrustDetailResponse getALlOrdersDetail(String orderId) {
//    IntrustDetailResponse resp = get("/v1/order/orders/"+orderId, null,new TypeReference<IntrustDetailResponse>() {});
//    return resp;
//  }
    // send a GET request.
    <T> T get(String uri, Map<String, String> params, TypeReference<T> ref) {
        if (params == null) {
            params = new HashMap<>();
        }
        return call("GET", uri, null, params, ref);
    }
    // send a POST request.
    <T> T post(String uri, Object object, TypeReference<T> ref) {
        return call("POST", uri, object, new HashMap<String, String>(), ref);
    }
    // call api by endpoint.
    <T> T call(String method, String uri, Object object, Map<String, String> params,
               TypeReference<T> ref) {
        ApiSignature sign = new ApiSignature();
        sign.createSignature(this.accessKeyId, this.accessKeySecret, method, API_HOST, uri, params);
        try {
            Request.Builder builder = null;
            if ("POST".equals(method)) {
                RequestBody body = RequestBody.create(JSON, JsonUtil.writeValue(object));
                builder = new Request.Builder().url(API_URL + uri + "?" + toQueryString(params)).post(body);
            } else {
                builder = new Request.Builder().url(API_URL + uri + "?" + toQueryString(params)).get();
            }
            if (this.assetPassword != null) {
                builder.addHeader("AuthData", authData());
            }
            Request request = builder.build();
            Response response = client.newCall(request).execute();
            String s = response.body().string();
            //System.out.println("-----s:"+JsonUtil.writeValue(s));
            return JsonUtil.readValue(s, ref);
        } catch (IOException e) {
            // throw new ApiException(e);
            e.printStackTrace();
            return null;
        }
    }
    String authData() {
        MessageDigest md = null;
        try {
            md = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
        md.update(this.assetPassword.getBytes(StandardCharsets.UTF_8));
        md.update("hello, moto".getBytes(StandardCharsets.UTF_8));
        Map<String, String> map = new HashMap<>();
        map.put("assetPwd", DatatypeConverter.printHexBinary(md.digest()).toLowerCase());
        try {
            return ApiSignature.urlEncode(JsonUtil.writeValue(map));
        } catch (IOException e) {
            throw new RuntimeException("Get json failed: " + e.getMessage());
        }
    }
    // Encode as "a=1&b=%20&c=&d=AAA"
    String toQueryString(Map<String, String> params) {
        return String.join("&", params.entrySet().stream().map((entry) -> {
            return entry.getKey() + "=" + ApiSignature.urlEncode(entry.getValue());
        }).collect(Collectors.toList()));
    }
    // create OkHttpClient:
    static OkHttpClient createOkHttpClient() {
        return new Builder().connectTimeout(CONN_TIMEOUT, TimeUnit.SECONDS)
                .readTimeout(READ_TIMEOUT, TimeUnit.SECONDS).writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS)
                .build();
    }
    static String getHost() {
        String host = null;
        try {
            host = new URL(API_URL).getHost();
        } catch (MalformedURLException e) {
            System.err.println("parse API_URL error,system exit!,please check API_URL:" + API_URL);
            System.exit(0);
        }
        return host;
    }
}
/**
 * API签名,签名规范:
 * <p>
 * http://docs.aws.amazon.com/zh_cn/general/latest/gr/signature-version-2.html
 *
 * @Date 2018/1/14
 * @Time 16:02
 */
class ApiSignature {
    final Logger log = LoggerFactory.getLogger(getClass());
    static final DateTimeFormatter DT_FORMAT = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss");
    static final ZoneId ZONE_GMT = ZoneId.of("Z");
    /**
     * 创建一个有效的签名。该方法为客户端调用,将在传入的params中添加AccessKeyId、Timestamp、SignatureVersion、SignatureMethod、Signature参数。
     *
     * @param appKey       AppKeyId.
     * @param appSecretKey AppKeySecret.
     * @param method       请求方法,"GET"或"POST"
     * @param host         请求域名,例如"be.huobi.com"
     * @param uri          请求路径,注意不含?以及后的参数,例如"/v1/api/info"
     * @param params       原始请求参数,以Key-Value存储,注意Value不要编码
     */
    public void createSignature(String appKey, String appSecretKey, String method, String host,
                                String uri, Map<String, String> params) {
        StringBuilder sb = new StringBuilder(1024);
        sb.append(method.toUpperCase()).append('\n') // GET
                .append(host.toLowerCase()).append('\n') // Host
                .append(uri).append('\n'); // /path
        params.remove("Signature");
        params.put("AccessKeyId", appKey);
        params.put("SignatureVersion", "2");
        params.put("SignatureMethod", "HmacSHA256");
        params.put("Timestamp", gmtNow());
        // build signature:
        SortedMap<String, String> map = new TreeMap<>(params);
        for (Map.Entry<String, String> entry : map.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            sb.append(key).append('=').append(urlEncode(value)).append('&');
        }
        // remove last '&':
        sb.deleteCharAt(sb.length() - 1);
        // sign:
        Mac hmacSha256 = null;
        try {
            hmacSha256 = Mac.getInstance("HmacSHA256");
            SecretKeySpec secKey =
                    new SecretKeySpec(appSecretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
            hmacSha256.init(secKey);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("No such algorithm: " + e.getMessage());
        } catch (InvalidKeyException e) {
            throw new RuntimeException("Invalid key: " + e.getMessage());
        }
        String payload = sb.toString();
        byte[] hash = hmacSha256.doFinal(payload.getBytes(StandardCharsets.UTF_8));
        String actualSign = Base64.getEncoder().encodeToString(hash);
        params.put("Signature", actualSign);
        if (log.isDebugEnabled()) {
            log.debug("Dump parameters:");
            for (Map.Entry<String, String> entry : params.entrySet()) {
                log.debug("  key: " + entry.getKey() + ", value: " + entry.getValue());
            }
        }
    }
    /**
     * 使用标准URL Encode编码。注意和JDK默认的不同,空格被编码为%20而不是+。
     *
     * @param s String字符串
     * @return URL编码后的字符串
     */
    public static String urlEncode(String s) {
        try {
            return URLEncoder.encode(s, "UTF-8").replaceAll("\\+", "%20");
        } catch (UnsupportedEncodingException e) {
            throw new IllegalArgumentException("UTF-8 encoding not supported!");
        }
    }
    /**
     * Return epoch seconds
     */
    long epochNow() {
        return Instant.now().getEpochSecond();
    }
    String gmtNow() {
        return Instant.ofEpochSecond(epochNow()).atZone(ZONE_GMT).format(DT_FORMAT);
    }
}
class JsonUtil {
    public static String writeValue(Object obj) throws IOException {
        return objectMapper.writeValueAsString(obj);
    }
    public static <T> T readValue(String s, TypeReference<T> ref) throws IOException {
        return objectMapper.readValue(s, ref);
    }
    static final ObjectMapper objectMapper = createObjectMapper();
    static ObjectMapper createObjectMapper() {
        final ObjectMapper mapper = new ObjectMapper();
        mapper.setPropertyNamingStrategy(PropertyNamingStrategy.KEBAB_CASE);
        mapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
        // disabled features:
        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        return mapper;
    }
}
src/main/java/com/xcong/excoin/utils/api/ApiException.java
New file
@@ -0,0 +1,33 @@
package com.xcong.excoin.utils.api;
/**
 * ApiException if api returns error.
 *
 * @Date 2018/1/14
 * @Time 16:02
 */
public class ApiException extends RuntimeException {
    /**
     *
     */
    private static final long serialVersionUID = 8196662756375909063L;
    final String errCode;
    public ApiException(String errCode, String errMsg) {
        super(errMsg);
        this.errCode = errCode;
    }
    public ApiException(Exception e) {
        super(e);
        this.errCode = e.getClass().getName();
    }
    public String getErrCode() {
        return this.errCode;
    }
}
src/main/java/com/xcong/excoin/utils/api/request/CreateOrderRequest.java
New file
@@ -0,0 +1,52 @@
package com.xcong.excoin.utils.api.request;
public class CreateOrderRequest {
    public static interface OrderType {
        /**
         * 限价买入
         */
        static final String BUY_LIMIT = "buy-limit";
        /**
         * 限价卖出
         */
        static final String SELL_LIMIT = "sell-limit";
        /**
         * 市价买入
         */
        static final String BUY_MARKET = "buy-market";
        /**
         * 市价卖出
         */
        static final String SELL_MARKET = "sell-market";
    }
    /**
     * 交易对,必填,例如:"ethcny",
     */
    public String symbol;
    /**
     * 账户ID,必填,例如:"12345"
     */
    public String accountId;
    /**
     * 当订单类型为buy-limit,sell-limit时,表示订单数量, 当订单类型为buy-market时,表示订单总金额, 当订单类型为sell-market时,表示订单总数量
     */
    public String amount;
    /**
     * 订单价格,仅针对限价单有效,例如:"1234.56"
     */
    public String price = "0.0";
    /**
     * 订单类型,取值范围"buy-market,sell-market,buy-limit,sell-limit"
     */
    public String type;
    /**
     * 订单来源,例如:"api"
     */
    public String source = "com/huobi/client/api";
}
src/main/java/com/xcong/excoin/utils/api/request/DepthRequest.java
New file
@@ -0,0 +1,26 @@
package com.xcong.excoin.utils.api.request;
public class DepthRequest {
    //交易对
    public String symbol;
    //Depth 类型 step0, step1, step2, step3, step4, step5(合并深度0-5);step0时,不合并深度
    public String type;
    public String getSymbol() {
        return symbol;
    }
    public void setSymbol(String symbol) {
        this.symbol = symbol;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
}
src/main/java/com/xcong/excoin/utils/api/request/IntrustOrdersDetailRequest.java
New file
@@ -0,0 +1,62 @@
package com.xcong.excoin.utils.api.request;
public class IntrustOrdersDetailRequest {
    public static interface OrderType {
        /**
         * 限价买入
         */
        static final String BUY_LIMIT = "buy-limit";
        /**
         * 限价卖出
         */
        static final String SELL_LIMIT = "sell-limit";
        /**
         * 市价买入
         */
        static final String BUY_MARKET = "buy-market";
        /**
         * 市价卖出
         */
        static final String SELL_MARKET = "sell-market";
    }
    public static interface OrderStates {
        /**
         * pre-submitted 准备提交
         */
        static final String PRE_SUBMITTED = "pre-submitted";
        /**
         * submitted 已提交
         */
        static final String SUBMITTED = "submitted";
        /**
         * partial-filled 部分成交
         */
        static final String PARTIAL_FILLED = "partial-filled";
        /**
         * partial-canceled 部分成交撤销
         */
        static final String PARTIAL_CANCELED = "partial-canceled";
        /**
         * filled 完全成交
         */
        static final String FILLED = "filled";
        /**
         * canceled 已撤销
         */
        static final String CANCELED = "canceled";
    }
    public String symbol;       //true    string    交易对        btcusdt, bccbtc, rcneth ...
    public String types;       //false    string    查询的订单类型组合,使用','分割        buy-market:市价买, sell-market:市价卖, buy-limit:限价买, sell-limit:限价卖
    public String startDate;   //false    string    查询开始日期, 日期格式yyyy-mm-dd
    public String endDate;       //false    string    查询结束日期, 日期格式yyyy-mm-dd
    public String states;       //true    string    查询的订单状态组合,使用','分割        pre-submitted 准备提交, submitted 已提交, partial-filled 部分成交,
    // partial-canceled 部分成交撤销, filled 完全成交, canceled 已撤销
    public String from;           //false    string    查询起始 ID
    public String direct;       //false    string    查询方向        prev 向前,next 向后
    public String size;           //false    string    查询记录大小
}
src/main/java/com/xcong/excoin/utils/api/response/Account.java
New file
@@ -0,0 +1,8 @@
package com.xcong.excoin.utils.api.response;
public class Account {
    public long id;
    public String type;
    public String state;
}
src/main/java/com/xcong/excoin/utils/api/response/Accounts.java
New file
@@ -0,0 +1,48 @@
package com.xcong.excoin.utils.api.response;
public class Accounts {
    /**
     * id : 100009
     * type : spot
     * state : working
     * user-id : 1000
     */
    private int id;
    private String type;
    private String state;
    private int userid;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public String getState() {
        return state;
    }
    public void setState(String state) {
        this.state = state;
    }
    public int getUserid() {
        return userid;
    }
    public void setUserid(int userid) {
        this.userid = userid;
    }
}
src/main/java/com/xcong/excoin/utils/api/response/AccountsResponse.java
New file
@@ -0,0 +1,56 @@
package com.xcong.excoin.utils.api.response;
import com.xcong.excoin.utils.api.ApiException;
public class AccountsResponse<T> {
    /**
     * status : ok
     * data : [{"id":100009,"type":"spot","state":"working","user-id":1000}]
     */
    private String status;
    public String errCode;
    public String errMsg;
    private T data;
    public T checkAndReturn() {
        if ("ok".equals(status)) {
            return data;
        }
        throw new ApiException(errCode, errMsg);
    }
    public String getStatus() {
        return status;
    }
    public void setStatus(String status) {
        this.status = status;
    }
    public T getData() {
        return data;
    }
    public void setData(T data) {
        this.data = data;
    }
    public String getErrCode() {
        return errCode;
    }
    public void setErrCode(String errCode) {
        this.errCode = errCode;
    }
    public String getErrMsg() {
        return errMsg;
    }
    public void setErrMsg(String errMsg) {
        this.errMsg = errMsg;
    }
}
src/main/java/com/xcong/excoin/utils/api/response/ApiResponse.java
New file
@@ -0,0 +1,19 @@
package com.xcong.excoin.utils.api.response;
import com.xcong.excoin.utils.api.ApiException;
public class ApiResponse<T> {
    public String status;
    public String errCode;
    public String errMsg;
    public T data;
    public T checkAndReturn() {
        if ("ok".equals(status)) {
            return data;
        }
        throw new ApiException(errCode, errMsg);
    }
}
src/main/java/com/xcong/excoin/utils/api/response/Balance.java
New file
@@ -0,0 +1,57 @@
package com.xcong.excoin.utils.api.response;
public class Balance<T> {
    /**
     * id : 100009
     * type : spot
     * state : working
     * list : [{"currency":"usdt","type":"trade","balance":"500009195917.4362872650"}]
     * user-id : 1000
     */
    private String id;
    private String type;
    private String state;
    private String userid;
    private T list;
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public String getState() {
        return state;
    }
    public void setState(String state) {
        this.state = state;
    }
    public String getUserid() {
        return userid;
    }
    public void setUserid(String userid) {
        this.userid = userid;
    }
    public T getList() {
        return list;
    }
    public void setList(T list) {
        this.list = list;
    }
}
src/main/java/com/xcong/excoin/utils/api/response/BalanceBean.java
New file
@@ -0,0 +1,37 @@
package com.xcong.excoin.utils.api.response;
public class BalanceBean {
    /**
     * currency : usdt
     * type : trade
     * balance : 500009195917.4362872650
     */
    private String currency;
    private String type;
    private String balance;
    public String getCurrency() {
        return currency;
    }
    public void setCurrency(String currency) {
        this.currency = currency;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public String getBalance() {
        return balance;
    }
    public void setBalance(String balance) {
        this.balance = balance;
    }
}
src/main/java/com/xcong/excoin/utils/api/response/BalanceResponse.java
New file
@@ -0,0 +1,47 @@
package com.xcong.excoin.utils.api.response;
public class BalanceResponse<T> {
    /**
     * status : ok
     * data : {"id":"100009","type":"spot","state":"working","list":[{"currency":"usdt","type":"trade","balance":"500009195917.4362872650"}],"user-id":"1000"}
     */
    private String status;
    public String errCode;
    public String errMsg;
    private T data;
    public String getStatus() {
        return status;
    }
    public void setStatus(String status) {
        this.status = status;
    }
    public T getData() {
        return data;
    }
    public void setData(T data) {
        this.data = data;
    }
    public String getErrCode() {
        return errCode;
    }
    public void setErrCode(String errCode) {
        this.errCode = errCode;
    }
    public String getErrMsg() {
        return errMsg;
    }
    public void setErrMsg(String errMsg) {
        this.errMsg = errMsg;
    }
}
src/main/java/com/xcong/excoin/utils/api/response/Batchcancel.java
New file
@@ -0,0 +1,22 @@
package com.xcong.excoin.utils.api.response;
public class Batchcancel<T1, T2> {
    private T1 success;
    private T2 failed;
    public T1 getSuccess() {
        return success;
    }
    public void setSuccess(T1 success) {
        this.success = success;
    }
    public T2 getFailed() {
        return failed;
    }
    public void setFailed(T2 failed) {
        this.failed = failed;
    }
}
src/main/java/com/xcong/excoin/utils/api/response/BatchcancelBean.java
New file
@@ -0,0 +1,34 @@
package com.xcong.excoin.utils.api.response;
/** @Author ISME @Date 2018/1/14 @Time 17:53 */
public class BatchcancelBean {
    /** err-msg : 记录无效 order-id : 2 err-code : base-record-invalid */
    private String errMsg;
    private String orderId;
    private String errCode;
    public String getErrMsg() {
        return errMsg;
    }
    public void setErrMsg(String errMsg) {
        this.errMsg = errMsg;
    }
    public String getOrderId() {
        return orderId;
    }
    public void setOrderId(String orderId) {
        this.orderId = orderId;
    }
    public String getErrCode() {
        return errCode;
    }
    public void setErrCode(String errCode) {
        this.errCode = errCode;
    }
}
src/main/java/com/xcong/excoin/utils/api/response/BatchcancelResponse.java
New file
@@ -0,0 +1,47 @@
package com.xcong.excoin.utils.api.response;
public class BatchcancelResponse<T> {
    /**
     * status : ok
     * data : {"success":["1","3"],"failed":[{"err-msg":"记录无效","order-id":"2","err-code":"base-record-invalid"}]}
     */
    private String status;
    public String errCode;
    public String errMsg;
    private T data;
    public String getStatus() {
        return status;
    }
    public void setStatus(String status) {
        this.status = status;
    }
    public String getErrCode() {
        return errCode;
    }
    public void setErrCode(String errCode) {
        this.errCode = errCode;
    }
    public String getErrMsg() {
        return errMsg;
    }
    public void setErrMsg(String errMsg) {
        this.errMsg = errMsg;
    }
    public T getData() {
        return data;
    }
    public void setData(T data) {
        this.data = data;
    }
}
src/main/java/com/xcong/excoin/utils/api/response/Currencys.java
New file
@@ -0,0 +1,4 @@
package com.xcong.excoin.utils.api.response;
public class Currencys {
}
src/main/java/com/xcong/excoin/utils/api/response/CurrencysResponse.java
New file
@@ -0,0 +1,55 @@
package com.xcong.excoin.utils.api.response;
import java.util.List;
/**
 * @Author ISME
 * @Date 2018/1/14
 * @Time 15:46
 */
public class CurrencysResponse {
    /**
     * status : ok
     * data : ["usdt","eth","etc"]
     */
    private String status;
    public String errCode;
    public String errMsg;
    private List<String> data;
    public String getStatus() {
        return status;
    }
    public void setStatus(String status) {
        this.status = status;
    }
    public List<String> getData() {
        return data;
    }
    public void setData(List<String> data) {
        this.data = data;
    }
    public String getErrCode() {
        return errCode;
    }
    public void setErrCode(String errCode) {
        this.errCode = errCode;
    }
    public String getErrMsg() {
        return errMsg;
    }
    public void setErrMsg(String errMsg) {
        this.errMsg = errMsg;
    }
}
src/main/java/com/xcong/excoin/utils/api/response/Depth.java
New file
@@ -0,0 +1,57 @@
package com.xcong.excoin.utils.api.response;
import java.math.BigDecimal;
import java.util.List;
/**
 * @Author ISME
 * @Date 2018/1/14
 * @Time 14:39
 */
public class Depth {
    /**
     * id : 1489464585407
     * ts : 1489464585407
     * bids : [[7964,0.0678],[7963,0.9162]]
     * asks : [[7979,0.0736],[8020,13.6584]]
     */
    private String id;
    private String ts;
    private List<List<BigDecimal>> bids;
    private List<List<BigDecimal>> asks;
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getTs() {
        return ts;
    }
    public void setTs(String ts) {
        this.ts = ts;
    }
    public List<List<BigDecimal>> getBids() {
        return bids;
    }
    public void setBids(List<List<BigDecimal>> bids) {
        this.bids = bids;
    }
    public List<List<BigDecimal>> getAsks() {
        return asks;
    }
    public void setAsks(List<List<BigDecimal>> asks) {
        this.asks = asks;
    }
}
src/main/java/com/xcong/excoin/utils/api/response/DepthResponse.java
New file
@@ -0,0 +1,78 @@
package com.xcong.excoin.utils.api.response;
public class DepthResponse<T> {
    /**
     * status : ok
     * ch : market.btcusdt.depth.step1
     * ts : 1489472598812
     * tick : {"id":"1489464585407","ts":"1489464585407","bids":[[7964,0.0678],[7963,0.9162]],"asks":[[7979,0.0736],[8020,13.6584]]}
     */
    private String status;
    private String ch;
    private String ts;
    public String errCode;
    public String errMsg;
    /**
     * tick 说明:
     * "tick": {
     * "id": 消息id,
     * "ts": 消息生成时间,单位:毫秒,
     * "bids": 买盘,[price(成交价), amount(成交量)], 按price降序,
     * "asks": 卖盘,[price(成交价), amount(成交量)], 按price升序
     * }
     */
    private Depth tick;
    public String getStatus() {
        return status;
    }
    public void setStatus(String status) {
        this.status = status;
    }
    public String getCh() {
        return ch;
    }
    public void setCh(String ch) {
        this.ch = ch;
    }
    public String getTs() {
        return ts;
    }
    public void setTs(String ts) {
        this.ts = ts;
    }
    public Depth getTick() {
        return tick;
    }
    public void setTick(Depth tick) {
        this.tick = tick;
    }
    public String getErrCode() {
        return errCode;
    }
    public void setErrCode(String errCode) {
        this.errCode = errCode;
    }
    public String getErrMsg() {
        return errMsg;
    }
    public void setErrMsg(String errMsg) {
        this.errMsg = errMsg;
    }
}
src/main/java/com/xcong/excoin/utils/api/response/DetailResponse.java
New file
@@ -0,0 +1,67 @@
package com.xcong.excoin.utils.api.response;
public class DetailResponse<T> {
    /**
     * status : ok
     * ch : market.btcusdt.detail
     * ts : 1489473538996
     * tick : {"amount":4316.4346,"open":8090.54,"close":7962.62,"high":8119,"ts":1489464451000,"id":1489464451,"count":9595,"low":7875,"vol":3.449727690576E7}
     */
    private String status;
    private String ch;
    private long ts;
    public String errCode;
    public String errMsg;
    private T tick;
    public String getStatus() {
        return status;
    }
    public void setStatus(String status) {
        this.status = status;
    }
    public String getCh() {
        return ch;
    }
    public void setCh(String ch) {
        this.ch = ch;
    }
    public long getTs() {
        return ts;
    }
    public void setTs(long ts) {
        this.ts = ts;
    }
    public String getErrCode() {
        return errCode;
    }
    public void setErrCode(String errCode) {
        this.errCode = errCode;
    }
    public String getErrMsg() {
        return errMsg;
    }
    public void setErrMsg(String errMsg) {
        this.errMsg = errMsg;
    }
    public T getTick() {
        return tick;
    }
    public void setTick(T tick) {
        this.tick = tick;
    }
}
src/main/java/com/xcong/excoin/utils/api/response/Details.java
New file
@@ -0,0 +1,98 @@
package com.xcong.excoin.utils.api.response;
public class Details {
    /**
     * amount : 4316.4346
     * open : 8090.54
     * close : 7962.62
     * high : 8119
     * ts : 1489464451000
     * id : 1489464451
     * count : 9595
     * low : 7875
     * vol : 3.449727690576E7
     */
    private double amount;
    private double open;
    private double close;
    private int high;
    private long ts;
    private long id;
    private int count;
    private int low;
    private double vol;
    public double getAmount() {
        return amount;
    }
    public void setAmount(double amount) {
        this.amount = amount;
    }
    public double getOpen() {
        return open;
    }
    public void setOpen(double open) {
        this.open = open;
    }
    public double getClose() {
        return close;
    }
    public void setClose(double close) {
        this.close = close;
    }
    public int getHigh() {
        return high;
    }
    public void setHigh(int high) {
        this.high = high;
    }
    public long getTs() {
        return ts;
    }
    public void setTs(long ts) {
        this.ts = ts;
    }
    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }
    public int getCount() {
        return count;
    }
    public void setCount(int count) {
        this.count = count;
    }
    public int getLow() {
        return low;
    }
    public void setLow(int low) {
        this.low = low;
    }
    public double getVol() {
        return vol;
    }
    public void setVol(double vol) {
        this.vol = vol;
    }
}
src/main/java/com/xcong/excoin/utils/api/response/HistoryTrade.java
New file
@@ -0,0 +1,57 @@
package com.xcong.excoin.utils.api.response;
public class HistoryTrade {
    /**
     * id : 17592256642623
     * amount : 0.04
     * price : 1997
     * direction : buy
     * ts : 1502448920106
     */
    private long id;
    private double amount;
    private int price;
    private String direction;
    private long ts;
    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }
    public double getAmount() {
        return amount;
    }
    public void setAmount(double amount) {
        this.amount = amount;
    }
    public int getPrice() {
        return price;
    }
    public void setPrice(int price) {
        this.price = price;
    }
    public String getDirection() {
        return direction;
    }
    public void setDirection(String direction) {
        this.direction = direction;
    }
    public long getTs() {
        return ts;
    }
    public void setTs(long ts) {
        this.ts = ts;
    }
}
src/main/java/com/xcong/excoin/utils/api/response/HistoryTradeResponse.java
New file
@@ -0,0 +1,67 @@
package com.xcong.excoin.utils.api.response;
public class HistoryTradeResponse<T> {
    /**
     * status : ok
     * ch : market.ethusdt.trade.detail
     * ts : 1502448925216
     * data : [{"id":31459998,"ts":1502448920106,"data":[{"id":17592256642623,"amount":0.04,"price":1997,"direction":"buy","ts":1502448920106}]}]
     */
    private String status;
    private String ch;
    private long ts;
    public String errCode;
    public String errMsg;
    private T data;
    public String getStatus() {
        return status;
    }
    public void setStatus(String status) {
        this.status = status;
    }
    public String getCh() {
        return ch;
    }
    public void setCh(String ch) {
        this.ch = ch;
    }
    public long getTs() {
        return ts;
    }
    public void setTs(long ts) {
        this.ts = ts;
    }
    public T getData() {
        return data;
    }
    public void setData(T data) {
        this.data = data;
    }
    public String getErrCode() {
        return errCode;
    }
    public void setErrCode(String errCode) {
        this.errCode = errCode;
    }
    public String getErrMsg() {
        return errMsg;
    }
    public void setErrMsg(String errMsg) {
        this.errMsg = errMsg;
    }
}
src/main/java/com/xcong/excoin/utils/api/response/HistoryTradess.java
New file
@@ -0,0 +1,37 @@
package com.xcong.excoin.utils.api.response;
public class HistoryTradess {
    /**
     * id : 31459998
     * ts : 1502448920106
     * data : [{"id":17592256642623,"amount":0.04,"price":1997,"direction":"buy","ts":1502448920106}]
     */
    private long id;
    private long ts;
    private HistoryTrade data;
    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }
    public long getTs() {
        return ts;
    }
    public void setTs(long ts) {
        this.ts = ts;
    }
    public HistoryTrade getData() {
        return data;
    }
    public void setData(HistoryTrade data) {
        this.data = data;
    }
}
src/main/java/com/xcong/excoin/utils/api/response/IntrustDetail.java
New file
@@ -0,0 +1,194 @@
package com.xcong.excoin.utils.api.response;
import com.google.gson.annotations.SerializedName;
/**
 * @Author ISME
 * @Date 2018/1/14
 * @Time 19:20
 */
public class IntrustDetail {
    /**
     * id : 59378
     * symbol : ethusdt
     * account-id : 100009
     * amount : 10.1000000000
     * price : 100.1000000000
     * created-at : 1494901162595
     * type : buy-limit
     * field-amount : 10.1000000000
     * field-cash-amount : 1011.0100000000
     * field-fees : 0.0202000000
     * finished-at : 1494901400468
     * user-id : 1000
     * source : api
     * state : filled
     * canceled-at : 0
     * exchange : huobi
     * batch :
     */
    private long id;
    private String symbol;
    @SerializedName("account-id")
    private int accountid;
    private String amount;
    private String price;
    @SerializedName("created-at")
    private long createdat;
    private String type;
    @SerializedName("field-amount")
    private String fieldamount;
    @SerializedName("field-cash-amount")
    private String fieldcashamount;
    @SerializedName("field-fees")
    private String fieldfees;
    @SerializedName("finished-at")
    private long finishedat;
    @SerializedName("user-id")
    private int userid;
    private String source;
    private String state;
    @SerializedName("canceled-at")
    private int canceledat;
    private String exchange;
    private String batch;
    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }
    public String getSymbol() {
        return symbol;
    }
    public void setSymbol(String symbol) {
        this.symbol = symbol;
    }
    public int getAccountid() {
        return accountid;
    }
    public void setAccountid(int accountid) {
        this.accountid = accountid;
    }
    public String getAmount() {
        return amount;
    }
    public void setAmount(String amount) {
        this.amount = amount;
    }
    public String getPrice() {
        return price;
    }
    public void setPrice(String price) {
        this.price = price;
    }
    public long getCreatedat() {
        return createdat;
    }
    public void setCreatedat(long createdat) {
        this.createdat = createdat;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public String getFieldamount() {
        return fieldamount;
    }
    public void setFieldamount(String fieldamount) {
        this.fieldamount = fieldamount;
    }
    public String getFieldcashamount() {
        return fieldcashamount;
    }
    public void setFieldcashamount(String fieldcashamount) {
        this.fieldcashamount = fieldcashamount;
    }
    public String getFieldfees() {
        return fieldfees;
    }
    public void setFieldfees(String fieldfees) {
        this.fieldfees = fieldfees;
    }
    public long getFinishedat() {
        return finishedat;
    }
    public void setFinishedat(long finishedat) {
        this.finishedat = finishedat;
    }
    public int getUserid() {
        return userid;
    }
    public void setUserid(int userid) {
        this.userid = userid;
    }
    public String getSource() {
        return source;
    }
    public void setSource(String source) {
        this.source = source;
    }
    public String getState() {
        return state;
    }
    public void setState(String state) {
        this.state = state;
    }
    public int getCanceledat() {
        return canceledat;
    }
    public void setCanceledat(int canceledat) {
        this.canceledat = canceledat;
    }
    public String getExchange() {
        return exchange;
    }
    public void setExchange(String exchange) {
        this.exchange = exchange;
    }
    public String getBatch() {
        return batch;
    }
    public void setBatch(String batch) {
        this.batch = batch;
    }
}
src/main/java/com/xcong/excoin/utils/api/response/IntrustDetailResponse.java
New file
@@ -0,0 +1,47 @@
package com.xcong.excoin.utils.api.response;
public class IntrustDetailResponse<T> {
    /**
     * status : ok
     * data : [{"id":59378,"symbol":"ethusdt","account-id":100009,"amount":"10.1000000000","price":"100.1000000000","created-at":1494901162595,"type":"buy-limit","field-amount":"10.1000000000","field-cash-amount":"1011.0100000000","field-fees":"0.0202000000","finished-at":1494901400468,"user-id":1000,"source":"api","state":"filled","canceled-at":0,"exchange":"huobi","batch":""}]
     */
    private String status;
    public String errCode;
    public String errMsg;
    private T data;
    public String getStatus() {
        return status;
    }
    public void setStatus(String status) {
        this.status = status;
    }
    public T getData() {
        return data;
    }
    public void setData(T data) {
        this.data = data;
    }
    public String getErrCode() {
        return errCode;
    }
    public void setErrCode(String errCode) {
        this.errCode = errCode;
    }
    public String getErrMsg() {
        return errMsg;
    }
    public void setErrMsg(String errMsg) {
        this.errMsg = errMsg;
    }
}
src/main/java/com/xcong/excoin/utils/api/response/Kline.java
New file
@@ -0,0 +1,68 @@
package com.xcong.excoin.utils.api.response;
public class Kline {
    private long id;
    private float amount;
    private int count;
    private float open;
    private float close;
    private float low;
    private float high;
    private float vol;
    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }
    public float getAmount() {
        return amount;
    }
    public void setAmount(float amount) {
        this.amount = amount;
    }
    public int getCount() {
        return count;
    }
    public void setCount(int count) {
        this.count = count;
    }
    public float getOpen() {
        return open;
    }
    public void setOpen(float open) {
        this.open = open;
    }
    public float getClose() {
        return close;
    }
    public void setClose(float close) {
        this.close = close;
    }
    public float getLow() {
        return low;
    }
    public void setLow(float low) {
        this.low = low;
    }
    public float getHigh() {
        return high;
    }
    public void setHigh(float high) {
        this.high = high;
    }
    public float getVol() {
        return vol;
    }
    public void setVol(float vol) {
        this.vol = vol;
    }
    @Override
    public String toString() {
        return "Kline [id=" + id + ", amount=" + amount + ", count=" + count + ", open=" + open + ", close=" + close
                + ", low=" + low + ", high=" + high + ", vol=" + vol + "]";
    }
}
src/main/java/com/xcong/excoin/utils/api/response/KlineResponse.java
New file
@@ -0,0 +1,55 @@
package com.xcong.excoin.utils.api.response;
import com.xcong.excoin.utils.api.ApiException;
public class KlineResponse<T> {
    private String status;
    /**
     * 接口名
     */
    private String ch;
    /**
     * 时间格式
     */
    private String ts;
    public String errCode;
    public String errMsg;
    /**
     * 数据
     */
    public T data;
    public T checkAndReturn() {
        if ("ok".equals(status)) {
            return data;
        }
        throw new ApiException(errCode, errMsg);
    }
    public String getStatus() {
        return status;
    }
    public void setStatus(String status) {
        this.status = status;
    }
    public String getCh() {
        return ch;
    }
    public void setCh(String ch) {
        this.ch = ch;
    }
    public String getTs() {
        return ts;
    }
    public void setTs(String ts) {
        this.ts = ts;
    }
}
src/main/java/com/xcong/excoin/utils/api/response/KlineReturn.java
New file
@@ -0,0 +1,66 @@
package com.xcong.excoin.utils.api.response;
public class KlineReturn {
    private long time;
    private float open;
    private float high;
    private float low;
    private float close;
    private float volume;
    private float amount;
//    private int count;
    public float getOpen() {
        return open;
    }
    public void setOpen(float open) {
        this.open = open;
    }
    public float getClose() {
        return close;
    }
    public void setClose(float close) {
        this.close = close;
    }
    public float getLow() {
        return low;
    }
    public void setLow(float low) {
        this.low = low;
    }
    public float getHigh() {
        return high;
    }
    public void setHigh(float high) {
        this.high = high;
    }
    public long getTime() {
        return time;
    }
    public void setTime(long time) {
        this.time = time;
    }
    public float getVolume() {
        return volume;
    }
    public void setVolume(float volume) {
        this.volume = volume;
    }
    public float getAmount() {
        return amount;
    }
    public void setAmount(float amount) {
        this.amount = amount;
    }
    @Override
    public String toString() {
        return "KlineReturn [time=" + time + ", open=" + open + ", high=" + high + ", low=" + low + ", close=" + close
                + ", volume=" + volume + "]";
    }
}
src/main/java/com/xcong/excoin/utils/api/response/MatchresultsOrdersDetail.java
New file
@@ -0,0 +1,112 @@
package com.xcong.excoin.utils.api.response;
public class MatchresultsOrdersDetail {
    /**
     * id : 29553
     * order-id : 59378
     * match-id : 59335
     * symbol : ethusdt
     * type : buy-limit
     * source : api
     * price : 100.1000000000
     * filled-amount : 9.1155000000
     * filled-fees : 0.0182310000
     * created-at : 1494901400435
     */
    private long id;
    @com.google.gson.annotations.SerializedName("order-id")
    private long orderid;
    @com.google.gson.annotations.SerializedName("match-id")
    private long matchid;
    private String symbol;
    private String type;
    private String source;
    private String price;
    @com.google.gson.annotations.SerializedName("filled-amount")
    private String filledamount;
    @com.google.gson.annotations.SerializedName("filled-fees")
    private String filledfees;
    @com.google.gson.annotations.SerializedName("created-at")
    private long createdat;
    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }
    public long getOrderid() {
        return orderid;
    }
    public void setOrderid(long orderid) {
        this.orderid = orderid;
    }
    public long getMatchid() {
        return matchid;
    }
    public void setMatchid(long matchid) {
        this.matchid = matchid;
    }
    public String getSymbol() {
        return symbol;
    }
    public void setSymbol(String symbol) {
        this.symbol = symbol;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public String getSource() {
        return source;
    }
    public void setSource(String source) {
        this.source = source;
    }
    public String getPrice() {
        return price;
    }
    public void setPrice(String price) {
        this.price = price;
    }
    public String getFilledamount() {
        return filledamount;
    }
    public void setFilledamount(String filledamount) {
        this.filledamount = filledamount;
    }
    public String getFilledfees() {
        return filledfees;
    }
    public void setFilledfees(String filledfees) {
        this.filledfees = filledfees;
    }
    public long getCreatedat() {
        return createdat;
    }
    public void setCreatedat(long createdat) {
        this.createdat = createdat;
    }
}
src/main/java/com/xcong/excoin/utils/api/response/MatchresultsOrdersDetailResponse.java
New file
@@ -0,0 +1,47 @@
package com.xcong.excoin.utils.api.response;
public class MatchresultsOrdersDetailResponse<T> {
    /**
     * status : ok
     * data : [{"id":29553,"order-id":59378,"match-id":59335,"symbol":"ethusdt","type":"buy-limit","source":"api","price":"100.1000000000","filled-amount":"9.1155000000","filled-fees":"0.0182310000","created-at":1494901400435}]
     */
    private String status;
    public String errCode;
    public String errMsg;
    private T data;
    public String getStatus() {
        return status;
    }
    public void setStatus(String status) {
        this.status = status;
    }
    public T getData() {
        return data;
    }
    public void setData(T data) {
        this.data = data;
    }
    public String getErrCode() {
        return errCode;
    }
    public void setErrCode(String errCode) {
        this.errCode = errCode;
    }
    public String getErrMsg() {
        return errMsg;
    }
    public void setErrMsg(String errMsg) {
        this.errMsg = errMsg;
    }
}
src/main/java/com/xcong/excoin/utils/api/response/Merged.java
New file
@@ -0,0 +1,121 @@
package com.xcong.excoin.utils.api.response;
import java.util.List;
public class Merged {
    /**
     * id : 1499225271
     * ts : 1499225271000
     * close : 1885
     * open : 1960
     * high : 1985
     * low : 1856
     * amount : 81486.2926
     * count : 42122
     * vol : 1.57052744857082E8
     * ask : [1885,21.8804]
     * bid : [1884,1.6702]
     */
    private long id;
    private long ts;
    private int close;
    private int open;
    private int high;
    private int low;
    private double amount;
    private int count;
    private double vol;
    private List<Integer> ask;
    private List<Integer> bid;
    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }
    public long getTs() {
        return ts;
    }
    public void setTs(long ts) {
        this.ts = ts;
    }
    public int getClose() {
        return close;
    }
    public void setClose(int close) {
        this.close = close;
    }
    public int getOpen() {
        return open;
    }
    public void setOpen(int open) {
        this.open = open;
    }
    public int getHigh() {
        return high;
    }
    public void setHigh(int high) {
        this.high = high;
    }
    public int getLow() {
        return low;
    }
    public void setLow(int low) {
        this.low = low;
    }
    public double getAmount() {
        return amount;
    }
    public void setAmount(double amount) {
        this.amount = amount;
    }
    public int getCount() {
        return count;
    }
    public void setCount(int count) {
        this.count = count;
    }
    public double getVol() {
        return vol;
    }
    public void setVol(double vol) {
        this.vol = vol;
    }
    public List<Integer> getAsk() {
        return ask;
    }
    public void setAsk(List<Integer> ask) {
        this.ask = ask;
    }
    public List<Integer> getBid() {
        return bid;
    }
    public void setBid(List<Integer> bid) {
        this.bid = bid;
    }
}
src/main/java/com/xcong/excoin/utils/api/response/MergedResponse.java
New file
@@ -0,0 +1,77 @@
package com.xcong.excoin.utils.api.response;
import com.xcong.excoin.utils.api.ApiException;
public class MergedResponse<T> {
    /**
     * status : ok
     * ch : market.ethusdt.detail.merged
     * ts : 1499225276950
     * tick : {"id":1499225271,"ts":1499225271000,"close":1885,"open":1960,"high":1985,"low":1856,"amount":81486.2926,"count":42122,"vol":1.57052744857082E8,"ask":[1885,21.8804],"bid":[1884,1.6702]}
     */
    private String status;
    private String ch;
    private long ts;
    public String errCode;
    public String errMsg;
    public Object tick;
    public Object checkAndReturn() {
        if ("ok".equals(status)) {
            return tick;
        }
        throw new ApiException(errCode, errMsg);
    }
    public String getStatus() {
        return status;
    }
    public void setStatus(String status) {
        this.status = status;
    }
    public String getCh() {
        return ch;
    }
    public void setCh(String ch) {
        this.ch = ch;
    }
    public long getTs() {
        return ts;
    }
    public void setTs(long ts) {
        this.ts = ts;
    }
    public String getErrCode() {
        return errCode;
    }
    public void setErrCode(String errCode) {
        this.errCode = errCode;
    }
    public String getErrMsg() {
        return errMsg;
    }
    public void setErrMsg(String errMsg) {
        this.errMsg = errMsg;
    }
    public Object getTick() {
        return tick;
    }
    public void setTick(Object tick) {
        this.tick = tick;
    }
}
src/main/java/com/xcong/excoin/utils/api/response/OrdersDetail.java
New file
@@ -0,0 +1,178 @@
package com.xcong.excoin.utils.api.response;
public class OrdersDetail {
    /**
     * id : 59378
     * symbol : ethusdt
     * account-id : 100009
     * amount : 10.1000000000
     * price : 100.1000000000
     * created-at : 1494901162595
     * type : buy-limit
     * field-amount : 10.1000000000
     * field-cash-amount : 1011.0100000000
     * field-fees : 0.0202000000
     * finished-at : 1494901400468
     * user-id : 1000
     * source : api
     * state : filled
     * canceled-at : 0
     * exchange : huobi
     * batch :
     */
    private long id;
    private String symbol;
    private int accountid;
    private String amount;
    private String price;
    private long createdat;
    private String type;
    private String fieldamount;
    private String fieldcashamount;
    private String fieldfees;
    private long finishedat;
    private int userid;
    private String source;
    private String state;
    private long canceledat;
    private String exchange;
    private String batch;
    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }
    public String getSymbol() {
        return symbol;
    }
    public void setSymbol(String symbol) {
        this.symbol = symbol;
    }
    public int getAccountid() {
        return accountid;
    }
    public void setAccountid(int accountid) {
        this.accountid = accountid;
    }
    public String getAmount() {
        return amount;
    }
    public void setAmount(String amount) {
        this.amount = amount;
    }
    public String getPrice() {
        return price;
    }
    public void setPrice(String price) {
        this.price = price;
    }
    public long getCreatedat() {
        return createdat;
    }
    public void setCreatedat(long createdat) {
        this.createdat = createdat;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public String getFieldamount() {
        return fieldamount;
    }
    public void setFieldamount(String fieldamount) {
        this.fieldamount = fieldamount;
    }
    public String getFieldcashamount() {
        return fieldcashamount;
    }
    public void setFieldcashamount(String fieldcashamount) {
        this.fieldcashamount = fieldcashamount;
    }
    public String getFieldfees() {
        return fieldfees;
    }
    public void setFieldfees(String fieldfees) {
        this.fieldfees = fieldfees;
    }
    public long getFinishedat() {
        return finishedat;
    }
    public void setFinishedat(long finishedat) {
        this.finishedat = finishedat;
    }
    public int getUserid() {
        return userid;
    }
    public void setUserid(int userid) {
        this.userid = userid;
    }
    public String getSource() {
        return source;
    }
    public void setSource(String source) {
        this.source = source;
    }
    public String getState() {
        return state;
    }
    public void setState(String state) {
        this.state = state;
    }
    public long getCanceledat() {
        return canceledat;
    }
    public void setCanceledat(long canceledat) {
        this.canceledat = canceledat;
    }
    public String getExchange() {
        return exchange;
    }
    public void setExchange(String exchange) {
        this.exchange = exchange;
    }
    public String getBatch() {
        return batch;
    }
    public void setBatch(String batch) {
        this.batch = batch;
    }
}
src/main/java/com/xcong/excoin/utils/api/response/OrdersDetailResponse.java
New file
@@ -0,0 +1,50 @@
package com.xcong.excoin.utils.api.response;
public class OrdersDetailResponse<T> {
    /**
     * status : ok
     * data : {"id":59378,"symbol":"ethusdt","account-id":100009,"amount":"10.1000000000","price":"100.1000000000","created-at":1494901162595,"type":"buy-limit","field-amount":"10.1000000000","field-cash-amount":"1011.0100000000","field-fees":"0.0202000000","finished-at":1494901400468,"user-id":1000,"source":"api","state":"filled","canceled-at":0,"exchange":"huobi","batch":""}
     */
    private String status;
    public String errCode;
    public String errMsg;
    private T data;
    public String getStatus() {
        return status;
    }
    public void setStatus(String status) {
        this.status = status;
    }
    public T getData() {
        return data;
    }
    public void setData(T data) {
        this.data = data;
    }
    public static class DataBean {
    }
    public String getErrCode() {
        return errCode;
    }
    public void setErrCode(String errCode) {
        this.errCode = errCode;
    }
    public String getErrMsg() {
        return errMsg;
    }
    public void setErrMsg(String errMsg) {
        this.errMsg = errMsg;
    }
}
src/main/java/com/xcong/excoin/utils/api/response/Place.java
New file
@@ -0,0 +1,4 @@
package com.xcong.excoin.utils.api.response;
public class Place {
}
src/main/java/com/xcong/excoin/utils/api/response/SubmitcancelResponse.java
New file
@@ -0,0 +1,47 @@
package com.xcong.excoin.utils.api.response;
public class SubmitcancelResponse {
    /**
     * status : ok
     * data : 59378
     */
    private String status;
    public String errCode;
    public String errMsg;
    private String data;
    public String getStatus() {
        return status;
    }
    public void setStatus(String status) {
        this.status = status;
    }
    public String getData() {
        return data;
    }
    public void setData(String data) {
        this.data = data;
    }
    public String getErrCode() {
        return errCode;
    }
    public void setErrCode(String errCode) {
        this.errCode = errCode;
    }
    public String getErrMsg() {
        return errMsg;
    }
    public void setErrMsg(String errMsg) {
        this.errMsg = errMsg;
    }
}
src/main/java/com/xcong/excoin/utils/api/response/Symbol.java
New file
@@ -0,0 +1,9 @@
package com.xcong.excoin.utils.api.response;
public class Symbol {
    public String baseCurrency;
    public String quoteCurrency;
    public String symbol;
}
src/main/java/com/xcong/excoin/utils/api/response/Symbols.java
New file
@@ -0,0 +1,98 @@
package com.xcong.excoin.utils.api.response;
public class Symbols {
    /**
     * amount : 4316.4346
     * open : 8090.54
     * close : 7962.62
     * high : 8119
     * ts : 1489464451000
     * id : 1489464451
     * count : 9595
     * low : 7875
     * vol : 3.449727690576E7
     */
    private double amount;
    private double open;
    private double close;
    private int high;
    private long ts;
    private long id;
    private int count;
    private int low;
    private double vol;
    public double getAmount() {
        return amount;
    }
    public void setAmount(double amount) {
        this.amount = amount;
    }
    public double getOpen() {
        return open;
    }
    public void setOpen(double open) {
        this.open = open;
    }
    public double getClose() {
        return close;
    }
    public void setClose(double close) {
        this.close = close;
    }
    public int getHigh() {
        return high;
    }
    public void setHigh(int high) {
        this.high = high;
    }
    public long getTs() {
        return ts;
    }
    public void setTs(long ts) {
        this.ts = ts;
    }
    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }
    public int getCount() {
        return count;
    }
    public void setCount(int count) {
        this.count = count;
    }
    public int getLow() {
        return low;
    }
    public void setLow(int low) {
        this.low = low;
    }
    public double getVol() {
        return vol;
    }
    public void setVol(double vol) {
        this.vol = vol;
    }
}
src/main/java/com/xcong/excoin/utils/api/response/SymbolsResponse.java
New file
@@ -0,0 +1,67 @@
package com.xcong.excoin.utils.api.response;
public class SymbolsResponse<T> {
    /**
     * status : ok
     * ch : market.btcusdt.detail
     * ts : 1489473538996
     * tick : {"amount":4316.4346,"open":8090.54,"close":7962.62,"high":8119,"ts":1489464451000,"id":1489464451,"count":9595,"low":7875,"vol":3.449727690576E7}
     */
    private String status;
    private String ch;
    private long ts;
    public String errCode;
    public String errMsg;
    private T tick;
    public String getStatus() {
        return status;
    }
    public void setStatus(String status) {
        this.status = status;
    }
    public String getCh() {
        return ch;
    }
    public void setCh(String ch) {
        this.ch = ch;
    }
    public long getTs() {
        return ts;
    }
    public void setTs(long ts) {
        this.ts = ts;
    }
    public String getErrCode() {
        return errCode;
    }
    public void setErrCode(String errCode) {
        this.errCode = errCode;
    }
    public String getErrMsg() {
        return errMsg;
    }
    public void setErrMsg(String errMsg) {
        this.errMsg = errMsg;
    }
    public T getTick() {
        return tick;
    }
    public void setTick(T tick) {
        this.tick = tick;
    }
}
src/main/java/com/xcong/excoin/utils/api/response/TimestampResponse.java
New file
@@ -0,0 +1,45 @@
package com.xcong.excoin.utils.api.response;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
 * @Author ISME
 * @Date 2018/1/14
 * @Time 15:53
 */
public class TimestampResponse {
    /**
     * status : ok
     * data : 1494900087029
     */
    private String status;
    private long data;
    @SuppressWarnings("unused")
    private String dateTime;
    public String getStatus() {
        return status;
    }
    public void setStatus(String status) {
        this.status = status;
    }
    public long getData() {
        return data;
    }
    public void setData(long data) {
        this.data = data;
    }
    public String getDateTime() {
        SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd hh:mm:ss");
        Date date = new Date(data);
        return sdf.format(date);
    }
}
src/main/java/com/xcong/excoin/utils/api/response/Trade.java
New file
@@ -0,0 +1,38 @@
package com.xcong.excoin.utils.api.response;
public class Trade<T> {
    /**
     * id : 600848670
     * ts : 1489464451000
     * data : [{"id":600848670,"price":7962.62,"amount":0.0122,"direction":"buy","ts":1489464451000}]
     */
    private long id;
    private long ts;
    private T data;
    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }
    public long getTs() {
        return ts;
    }
    public void setTs(long ts) {
        this.ts = ts;
    }
    public T getData() {
        return data;
    }
    public void setData(T data) {
        this.data = data;
    }
}
src/main/java/com/xcong/excoin/utils/api/response/TradeBean.java
New file
@@ -0,0 +1,60 @@
package com.xcong.excoin.utils.api.response;
public class TradeBean {
    /**
     * id : 600848670
     * price : 7962.62
     * amount : 0.0122
     * direction : buy
     * ts : 1489464451000
     */
    private long id;
    private double price;
    private double amount;
    private String direction;
    private long ts;
    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }
    public double getPrice() {
        return price;
    }
    public void setPrice(double price) {
        this.price = price;
    }
    public double getAmount() {
        return amount;
    }
    public void setAmount(double amount) {
        this.amount = amount;
    }
    public String getDirection() {
        return direction;
    }
    public void setDirection(String direction) {
        this.direction = direction;
    }
    public long getTs() {
        return ts;
    }
    public void setTs(long ts) {
        this.ts = ts;
    }
}
src/main/java/com/xcong/excoin/utils/api/response/TradeResponse.java
New file
@@ -0,0 +1,70 @@
package com.xcong.excoin.utils.api.response;
public class TradeResponse {
    /**
     * status : ok
     * ch : market.btcusdt.trade.detail
     * ts : 1489473346905
     * tick : {"id":600848670,"ts":1489464451000,"data":[{"id":600848670,"price":7962.62,"amount":0.0122,"direction":"buy","ts":1489464451000}]}
     */
    private String status;
    private String ch;
    private long ts;
    public String errCode;
    public String errMsg;
    @SuppressWarnings("rawtypes")
    private Trade tick;
    public String getStatus() {
        return status;
    }
    public void setStatus(String status) {
        this.status = status;
    }
    public String getCh() {
        return ch;
    }
    public void setCh(String ch) {
        this.ch = ch;
    }
    public long getTs() {
        return ts;
    }
    public void setTs(long ts) {
        this.ts = ts;
    }
    public String getErrCode() {
        return errCode;
    }
    public void setErrCode(String errCode) {
        this.errCode = errCode;
    }
    public String getErrMsg() {
        return errMsg;
    }
    public void setErrMsg(String errMsg) {
        this.errMsg = errMsg;
    }
    @SuppressWarnings("rawtypes")
    public Trade getTick() {
        return tick;
    }
    @SuppressWarnings("rawtypes")
    public void setTick(Trade tick) {
        this.tick = tick;
    }
}
src/main/java/com/xcong/excoin/utils/mail/RequestEncoder.java
New file
@@ -0,0 +1,71 @@
package com.xcong.excoin.utils.mail;
import java.security.MessageDigest;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
 * 处理请求数据
 * @author submail
 *
 */
public class RequestEncoder {
    private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5',
            '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
    public static final String MD5 = "MD5";
    public static final String SHA1 = "SHA1";
    /**
     * 编码的字符串
     *
     * @param algorithm
     * @param str
     * @return String
     */
    public static String encode(String algorithm, String str) {
        if (str == null) {
            return null;
        }
        try {
            MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
            messageDigest.update(str.getBytes("UTF-8"));
            return getFormattedText(messageDigest.digest());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    /**
     *获取原始字节并将其格式化。
     * @param bytes
     *            the raw bytes from the digest.
     * @return the formatted bytes.
     */
    private static String getFormattedText(byte[] bytes) {
        int len = bytes.length;
        StringBuilder buf = new StringBuilder(len * 2);
        for (int j = 0; j < len; j++) {             buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
            buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
        }
        return buf.toString();
    }
    public static String formatRequest(Map<String, Object> data){
        Set<String> keySet = data.keySet();
        Iterator<String> it = keySet.iterator();
        StringBuffer sb = new StringBuffer();
        while(it.hasNext()){
            String key = it.next();
            Object value = data.get(key);
            if(value instanceof String){
                sb.append(key + "=" + value + "&");
            }
        }
        if(sb.length() != 0){
            return sb.substring(0, sb.length() - 1);
        }
        return null;
    }
}
src/main/java/com/xcong/excoin/utils/mail/SubMailSend.java
New file
@@ -0,0 +1,133 @@
package com.xcong.excoin.utils.mail;
import net.sf.json.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.util.Map;
import java.util.TreeMap;
/**
 * 邮件发送
 *
 * @author wzy
 * @date 2020-05-27
 **/
public class SubMailSend {
    /**
     * 时间戳接口配置
     */
    public static final String TIMESTAMP = "https://api.mysubmail.com/service/timestamp";
    /**
     * API 请求接口配置
     */
    private static final String URL = "https://api.mysubmail.com/mail/xsend";
    public static final String TYPE_MD5 = "md5";
    public static final String TYPE_SHA1 = "sha1";
    public static boolean sendMail(String to, String code) {
        TreeMap<String, Object> requestData = new TreeMap<String, Object>();
        JSONObject vars = new JSONObject();
        vars.put("code", code);
        String appid = "16082";
        String appkey = "f34c792a1112c16c190ed7190d386c4f";
        String project = "fMBQk1";
        String signtype = "";
        String from = "ex@submail.excoin.site";
        requestData.put("appid", appid);
        requestData.put("project", project);
        requestData.put("to", to);
        requestData.put("from", from);
        if (!vars.isEmpty()) {
            requestData.put("vars", vars.toString());
        }
        MultipartEntityBuilder builder = MultipartEntityBuilder.create();
        @SuppressWarnings("deprecation")
        ContentType contentType = ContentType.create(HTTP.PLAIN_TEXT_TYPE, HTTP.UTF_8);
        for (Map.Entry<String, Object> entry : requestData.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            if (value instanceof String) {
                builder.addTextBody(key, String.valueOf(value), contentType);
            }
        }
        if (signtype.equals(TYPE_MD5) || signtype.equals(TYPE_SHA1)) {
            String timestamp = getTimestamp();
            requestData.put("timestamp", timestamp);
            requestData.put("sign_type", signtype);
            String signStr = appid + appkey + RequestEncoder.formatRequest(requestData) + appid + appkey;
            builder.addTextBody("timestamp", timestamp);
            builder.addTextBody("sign_type", signtype);
            builder.addTextBody("signature", RequestEncoder.encode(signtype, signStr), contentType);
        } else {
            builder.addTextBody("signature", appkey, contentType);
        }
        HttpPost httpPost = new HttpPost(URL);
        httpPost.addHeader("charset", "UTF-8");
        httpPost.setEntity(builder.build());
        try {
            CloseableHttpClient closeableHttpClient = HttpClientBuilder.create().build();
            HttpResponse response = closeableHttpClient.execute(httpPost);
            HttpEntity httpEntity = response.getEntity();
            if (httpEntity != null) {
                String jsonStr = EntityUtils.toString(httpEntity, "UTF-8");
                if ("success".equals(JSONObject.fromObject(jsonStr).getString("status"))) {
                    return true;
                }
            }
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }
    /**
     * 获取时间戳
     *
     * @return
     */
    private static String getTimestamp() {
        CloseableHttpClient closeableHttpClient = HttpClientBuilder.create().build();
        HttpGet httpget = new HttpGet(TIMESTAMP);
        try {
            HttpResponse response = closeableHttpClient.execute(httpget);
            HttpEntity httpEntity = response.getEntity();
            String jsonStr = EntityUtils.toString(httpEntity, "UTF-8");
            if (jsonStr != null) {
                JSONObject json = JSONObject.fromObject(jsonStr);
                return json.getString("timestamp");
            }
            closeableHttpClient.close();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    public static void main(String[] args) {
        System.out.println(sendMail("123@123.com", "123456"));
    }
}
src/main/resources/logback-spring.xml
@@ -3,6 +3,7 @@
    <contextName>logback</contextName>
    <!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 -->
    <property name="log.path" value="logs" />
    <statusListener class="ch.qos.logback.core.status.NopStatusListener" />
    <!-- 彩色日志 -->
    <!-- 彩色日志依赖的渲染类 -->
src/main/resources/mapper/platform/PlatformSymbolsContractDao.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xcong.excoin.modules.symbols.dao.PlatformSymbolsContractDao">
</mapper>
src/test/java/com/xcong/excoin/HuobiTest.java
New file
@@ -0,0 +1,39 @@
package com.xcong.excoin;
import com.alibaba.fastjson.JSONObject;
import com.huobi.client.SubscriptionClient;
import com.huobi.client.SubscriptionOptions;
import com.huobi.client.model.Candlestick;
import com.huobi.client.model.enums.CandlestickInterval;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
/**
 * @author wzy
 * @date 2020-05-22
 **/
@Slf4j
@SpringBootTest
public class HuobiTest {
    @Test
    public void websocketTest() {
    }
    public static void main(String[] args) {
        System.out.println("========价格更新开启=======");
        SubscriptionOptions subscriptionOptions = new SubscriptionOptions();
        //3秒重试
        subscriptionOptions.setConnectionDelayOnFailure(5);
        subscriptionOptions.setUri("wss://api.hadax.com/ws");
        SubscriptionClient subscriptionClient = SubscriptionClient.create("", "", subscriptionOptions);
//        subscriptionClient.subscribeTradeEvent("btcusdt,ethusdt,xrpusdt,ltcusdt,bchusdt,eosusdt,etcusdt", tradeEvent -> {
//            log.info("{}", JSONObject.toJSONString(tradeEvent));
//        });
        subscriptionClient.subscribeCandlestickEvent("btcusdt,ethusdt,eosusdt,etcusdt,ltcusdt,bchusdt,xrpusdt", CandlestickInterval.DAY1, (candlestickEvent) -> {
            log.info("{}", JSONObject.toJSONString(candlestickEvent));
        });
    }
}
src/test/java/com/xcong/excoin/SmsTest.java
New file
@@ -0,0 +1,14 @@
package com.xcong.excoin;
import cn.hutool.core.text.UnicodeUtil;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
/**
 * @author wzy
 * @date 2020-05-26
 **/
@SpringBootTest
public class SmsTest {
}
src/test/java/com/xcong/excoin/SymbolsTest.java
New file
@@ -0,0 +1,23 @@
package com.xcong.excoin;
import com.xcong.excoin.modules.symbols.service.SymbolsService;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
/**
 * @author wzy
 * @date 2020-05-26
 **/
@SpringBootTest
public class SymbolsTest {
    @Resource
    private SymbolsService symbolsService;
    @Test
    public void symbolsTest() {
        symbolsService.updateSymbolsKine("1min");
    }
}