├── C#
└── zb_api_c#.cs
├── IOS(OC)_Sign加密示例
├── IOS(OC)_Sign加密示例
│ ├── .DS_Store
│ ├── CBExamples.h
│ ├── CBExamples.m
│ └── CBSignEncodeTools
│ │ ├── CBSignEncodeTools.h
│ │ └── CBSignEncodeTools.m
└── __MACOSX
│ └── IOS(OC)_Sign加密示例
│ ├── ._.DS_Store
│ ├── ._CBExamples.h
│ ├── ._CBExamples.m
│ └── CBSignEncodeTools
│ ├── ._CBSignEncodeTools.h
│ └── ._CBSignEncodeTools.m
├── PHP
└── zbapi.php
├── PYTHON
├── rest 接口
│ ├── python3
│ │ ├── test.py
│ │ └── zapi.py
│ ├── zb_api_python.py
│ └── zb_api_python3.py
└── websocket 接口
│ ├── readme
│ ├── zb.com-api-master
│ ├── README.md
│ └── zb.comskd.py
│ └── zb_py_socket
│ ├── reame.txt
│ ├── test.py
│ ├── test.py.bak
│ └── vnzb.py
├── README.md
├── golang
└── zb-api-trade-master.zip
├── zb_api_rest_java
├── .classpath
├── .project
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── zb
│ │ │ └── kits
│ │ │ ├── EncryDigestUtil.java
│ │ │ ├── HttpUtilManager.java
│ │ │ ├── JsonFormatTool.java
│ │ │ └── MapSort.java
│ └── webapp
│ │ └── WEB-INF
│ │ └── web.xml
│ └── test
│ ├── java
│ └── com
│ │ └── zb
│ │ └── api
│ │ └── RestTest.java
│ └── resources
│ └── log4j.properties
├── zb_netty_client_java
├── pom.xml
└── src
│ └── main
│ └── java
│ ├── com
│ ├── world
│ │ ├── common
│ │ │ ├── SysEnum.java
│ │ │ ├── SystemCode.java
│ │ │ └── VerifiUtil.java
│ │ └── model
│ │ │ ├── entitys
│ │ │ ├── Balance.java
│ │ │ ├── Base.java
│ │ │ ├── Frozen.java
│ │ │ └── Order.java
│ │ │ └── market
│ │ │ ├── Arith.java
│ │ │ └── Market.java
│ └── zb
│ │ └── kits
│ │ └── MapSort.java
│ └── websocketx
│ └── client
│ ├── EncryDigestUtil.java
│ ├── RunExample.java
│ ├── WebSocketClient.java
│ └── WebSocketClientHandler.java
└── 易语言
├── 中币api示例.e
└── 精易模块5.7.ec
/C#/zb_api_c#.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Created by SharpDevelop.
3 | * User: Administrator
4 | * Date: 2014/1/2
5 | * Time: 12:56
6 | *
7 | * To change this template use Tools | Options | Coding | Edit Standard Headers.
8 | */
9 | using System;
10 | using System.Collections.Generic;
11 | using System.Linq;
12 | using System.Security.Cryptography;
13 | using System.Text;
14 | using System.Net;
15 | using System.IO;
16 | namespace zb {
17 | class zb_api {
18 | private static String encodingCharset = "UTF-8";
19 | /**
20 | *
21 | * @param aValue 要加密的文字
22 | * @param aKey 密钥
23 | * @return
24 | */
25 | public static String hmacSign(String aValue, String aKey) {
26 | byte[] k_ipad = new byte[64];
27 | byte[] k_opad = new byte[64];
28 | byte[] keyb;
29 | byte[] value;
30 | Encoding coding = Encoding.GetEncoding(encodingCharset);
31 | try {
32 | keyb = coding.GetBytes(aKey);
33 | // aKey.getBytes(encodingCharset);
34 | value = coding.GetBytes(aValue);
35 | // aValue.getBytes(encodingCharset);
36 | }
37 | catch (Exception e) {
38 | keyb = null;
39 | value =null;
40 | //throw;
41 | }
42 | for (int i = keyb.Length; i < 64; i++) {
43 | k_ipad[i] = (byte)54;
44 | k_opad[i] = (byte)92;
45 | }
46 | for (int i = 0; i < keyb.Length; i++) {
47 | k_ipad[i] = (byte) (keyb[i] ^ 0x36);
48 | k_opad[i] = (byte) (keyb[i] ^ 0x5c);
49 | }
50 | byte[] sMd5_1 = MakeMD5(k_ipad.Concat(value).ToArray());
51 | byte[] dg = MakeMD5(k_opad.Concat(sMd5_1).ToArray());
52 | return toHex(dg);
53 | }
54 | public static String toHex(byte[] input) {
55 | if (input == null)
56 | return null;
57 | StringBuilder output = new StringBuilder(input.Length * 2);
58 | for (int i = 0; i < input.Length; i++) {
59 | int current = input[i] & 0xff;
60 | if (current < 16)
61 | output.Append('0');
62 | output.Append( current.ToString("x"));
63 | }
64 | return output.ToString();
65 | }
66 | /**
67 | *
68 | * @param args
69 | * @param key
70 | * @return
71 | */
72 | public static String getHmac(String[] args, String key) {
73 | if (args == null || args.Length == 0) {
74 | return (null);
75 | }
76 | StringBuilder str = new StringBuilder();
77 | for (int i = 0; i < args.Length; i++) {
78 | str.Append(args[i]);
79 | }
80 | return (hmacSign(str.ToString(), key));
81 | }
82 | ///
83 | /// 生成MD5摘要
84 | ///
85 | /// 数据源
86 | /// 摘要
87 | public static byte[] MakeMD5(byte[] original) {
88 | MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
89 | byte[] keyhash = hashmd5.ComputeHash(original);
90 | hashmd5 = null;
91 | return keyhash;
92 | }
93 | /**
94 | * SHA加密
95 | * @param aValue
96 | * @return
97 | */
98 | public static String digest(String aValue) {
99 | aValue = aValue.Trim();
100 | byte[] value;
101 | SHA1 sha = null;
102 | Encoding coding = Encoding.GetEncoding(encodingCharset);
103 | try {
104 | value = coding.GetBytes(aValue);
105 | // aValue.getBytes(encodingCharset);
106 | HashAlgorithm ha=(HashAlgorithm) CryptoConfig.CreateFromName("SHA");
107 | value= ha.ComputeHash(value);
108 | }
109 | catch (Exception e) {
110 | //value = coding.GetBytes(aValue);
111 | throw;
112 | }
113 | return toHex(value);
114 | }
115 | /**
116 | * API调用示例
117 | * 其他方法调用及返回说明请查看API交易文档
118 | */
119 | public static String testGetAccountInfo() {
120 | String accesskey = "accesskey";
121 | String secretkey = "secretkey";
122 | String baseURL = "https://trade.zb.com/api/";
123 | String param = "accesskey="+accesskey+"&method=getAccountInfo";
124 | secretkey = digest(secretkey);
125 | String sign = hmacSign(param, secretkey);
126 | DateTime timeStamp=new DateTime(1970,1,1);
127 | //得到1970年的时间戳
128 | long stamp= (DateTime.UtcNow.Ticks - timeStamp.Ticks)/10000;
129 | //注意这里有时区问题,用now就要减掉8个小时
130 | baseURL += "getAccountInfo?" + param + "&sign=" + sign + "&reqTime=" + stamp;
131 | return HttpConnectToServer(baseURL);
132 | }
133 | /**
134 | * HttpConnectToServer
135 | */
136 | public static string HttpConnectToServer(string url) {
137 | //创建请求
138 | HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
139 | request.Method = "POST";
140 | request.ContentType = "application/x-www-form-urlencoded";
141 | //读取返回消息
142 | string res = string.Empty;
143 | try {
144 | HttpWebResponse response = (HttpWebResponse)request.GetResponse();
145 | StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
146 | res = reader.ReadToEnd();
147 | reader.Close();
148 | }
149 | catch (Exception ex) {
150 | return null;
151 | //连接服务器失败
152 | }
153 | return res;
154 | }
155 | public static void Main(string[] args) {
156 | // TODO: Implement Functionality Here
157 | //Console.WriteLine(hmacSign("administratorguoflyskyguosj","guosj"));
158 | //Console.WriteLine(digest("administratorguoflyskyguosj"));
159 | Console.WriteLine(testGetAccountInfo());
160 | }
161 | }
162 | }
--------------------------------------------------------------------------------
/IOS(OC)_Sign加密示例/IOS(OC)_Sign加密示例/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zb2017/api/4927d6940c9f217c91b11c042532827897f74927/IOS(OC)_Sign加密示例/IOS(OC)_Sign加密示例/.DS_Store
--------------------------------------------------------------------------------
/IOS(OC)_Sign加密示例/IOS(OC)_Sign加密示例/CBExamples.h:
--------------------------------------------------------------------------------
1 | //
2 | // CBExamples.h
3 | // JXMovableCellTableView
4 | //
5 | // Created by 丁 on 2017/9/14.
6 | // Copyright © 2017年 jiaxin. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface CBExamples : NSObject
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/IOS(OC)_Sign加密示例/IOS(OC)_Sign加密示例/CBExamples.m:
--------------------------------------------------------------------------------
1 | //
2 | // CBExamples.m
3 | // JXMovableCellTableView
4 | //
5 | // Created by 丁 on 2017/9/14.
6 | // Copyright © 2017年 jiaxin. All rights reserved.
7 | //
8 |
9 | #import "CBExamples.h"
10 | #import "CBSignEncodeTools.h"
11 |
12 | @implementation CBExamples
13 |
14 | //加密sign
15 | -(void)encode{
16 |
17 | /*
18 | 1) 先对 secretKey 进行 SHA 加密
19 | 2) 严格按照CHBTC文档 将参数按照顺序拼成字符串
20 | 3) 以 SHA加密后得到的字符串 为 key 对参数拼接字符串进行 HmacMD5 加密
21 | 3) 得到sign参数
22 | */
23 | NSString *signStr = [CBSignEncodeTools HMACMD5WithString:@"参数拼接字符串" WithKey:[CBSignEncodeTools getShaString:@"Secret Key"]];
24 |
25 | }
26 |
27 | @end
28 |
--------------------------------------------------------------------------------
/IOS(OC)_Sign加密示例/IOS(OC)_Sign加密示例/CBSignEncodeTools/CBSignEncodeTools.h:
--------------------------------------------------------------------------------
1 | //
2 | // SHA256.h
3 | // chbtc
4 | //
5 | // Created by 丁 on 2017/9/13.
6 | // Copyright © 2017年 丁. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | @interface CBSignEncodeTools : NSObject
13 |
14 | /** sha加密方式 */
15 | + (NSString *)getShaString:(NSString *)srcString;
16 | /** HmacMD5 加密 */
17 | + (NSString *)HMACMD5WithString:(NSString *)toEncryptStr WithKey:(NSString *)keyStr;
18 |
19 | @end
20 |
--------------------------------------------------------------------------------
/IOS(OC)_Sign加密示例/IOS(OC)_Sign加密示例/CBSignEncodeTools/CBSignEncodeTools.m:
--------------------------------------------------------------------------------
1 | //
2 | // SHA256.m
3 | // chbtc
4 | //
5 | // Created by 丁 on 2017/9/13.
6 | // Copyright © 2017年 丁. All rights reserved.
7 | //
8 |
9 | #import "CBSignEncodeTools.h"
10 |
11 | @implementation CBSignEncodeTools
12 |
13 | //sha加密方式
14 | + (NSString *)getShaString:(NSString *)srcString{
15 | const char *cstr = [srcString cStringUsingEncoding:NSUTF8StringEncoding];
16 | NSData *data = [NSData dataWithBytes:cstr length:srcString.length];
17 |
18 | uint8_t digest[CC_SHA1_DIGEST_LENGTH];
19 |
20 | CC_SHA1(data.bytes, (int)data.length, digest);
21 |
22 | NSMutableString* result = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];
23 |
24 | for(int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++) {
25 | [result appendFormat:@"%02x", digest[i]];
26 | }
27 |
28 | return result;
29 | }
30 |
31 |
32 |
33 | //HmacMD5 加密
34 | + (NSString *)HMACMD5WithString:(NSString *)toEncryptStr WithKey:(NSString *)keyStr
35 | {
36 | const char *cKey = [keyStr cStringUsingEncoding:NSUTF8StringEncoding];
37 | const char *cData = [toEncryptStr cStringUsingEncoding:NSUTF8StringEncoding];
38 | const unsigned int blockSize = 64;
39 | char ipad[blockSize];
40 | char opad[blockSize];
41 | char keypad[blockSize];
42 |
43 | unsigned int keyLen = (int)strlen(cKey);
44 | CC_MD5_CTX ctxt;
45 | if (keyLen > blockSize) {
46 | CC_MD5_Init(&ctxt);
47 | CC_MD5_Update(&ctxt, cKey, keyLen);
48 | CC_MD5_Final((unsigned char *)keypad, &ctxt);
49 | keyLen = CC_MD5_DIGEST_LENGTH;
50 | }
51 | else {
52 | memcpy(keypad, cKey, keyLen);
53 | }
54 |
55 | memset(ipad, 0x36, blockSize);
56 | memset(opad, 0x5c, blockSize);
57 |
58 | int i;
59 | for (i = 0; i < keyLen; i++) {
60 | ipad[i] ^= keypad[i];
61 | opad[i] ^= keypad[i];
62 | }
63 |
64 | CC_MD5_Init(&ctxt);
65 | CC_MD5_Update(&ctxt, ipad, blockSize);
66 | CC_MD5_Update(&ctxt, cData, (int)strlen(cData));
67 | unsigned char md5[CC_MD5_DIGEST_LENGTH];
68 | CC_MD5_Final(md5, &ctxt);
69 |
70 | CC_MD5_Init(&ctxt);
71 | CC_MD5_Update(&ctxt, opad, blockSize);
72 | CC_MD5_Update(&ctxt, md5, CC_MD5_DIGEST_LENGTH);
73 | CC_MD5_Final(md5, &ctxt);
74 |
75 | const unsigned int hex_len = CC_MD5_DIGEST_LENGTH*2+2;
76 | char hex[hex_len];
77 | for(i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
78 | snprintf(&hex[i*2], hex_len-i*2, "%02x", md5[i]);
79 | }
80 |
81 | NSData *HMAC = [[NSData alloc] initWithBytes:hex length:strlen(hex)];
82 | NSString *hash = [[NSString alloc] initWithData:HMAC encoding:NSUTF8StringEncoding];
83 |
84 | return hash;
85 | }
86 |
87 |
88 |
89 | @end
90 |
--------------------------------------------------------------------------------
/IOS(OC)_Sign加密示例/__MACOSX/IOS(OC)_Sign加密示例/._.DS_Store:
--------------------------------------------------------------------------------
1 | Mac OS X 2 F x ATTR x x
--------------------------------------------------------------------------------
/IOS(OC)_Sign加密示例/__MACOSX/IOS(OC)_Sign加密示例/._CBExamples.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zb2017/api/4927d6940c9f217c91b11c042532827897f74927/IOS(OC)_Sign加密示例/__MACOSX/IOS(OC)_Sign加密示例/._CBExamples.h
--------------------------------------------------------------------------------
/IOS(OC)_Sign加密示例/__MACOSX/IOS(OC)_Sign加密示例/._CBExamples.m:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zb2017/api/4927d6940c9f217c91b11c042532827897f74927/IOS(OC)_Sign加密示例/__MACOSX/IOS(OC)_Sign加密示例/._CBExamples.m
--------------------------------------------------------------------------------
/IOS(OC)_Sign加密示例/__MACOSX/IOS(OC)_Sign加密示例/CBSignEncodeTools/._CBSignEncodeTools.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zb2017/api/4927d6940c9f217c91b11c042532827897f74927/IOS(OC)_Sign加密示例/__MACOSX/IOS(OC)_Sign加密示例/CBSignEncodeTools/._CBSignEncodeTools.h
--------------------------------------------------------------------------------
/IOS(OC)_Sign加密示例/__MACOSX/IOS(OC)_Sign加密示例/CBSignEncodeTools/._CBSignEncodeTools.m:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zb2017/api/4927d6940c9f217c91b11c042532827897f74927/IOS(OC)_Sign加密示例/__MACOSX/IOS(OC)_Sign加密示例/CBSignEncodeTools/._CBSignEncodeTools.m
--------------------------------------------------------------------------------
/PHP/zbapi.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | zb
6 |
7 | Fund();
11 | //var_dump($Fond_zb);
12 |
13 | class zbAPI {
14 | var $access_key="***";
15 | var $secret_key="***";
16 |
17 | function httpRequest($pUrl, $pData){
18 | $tCh = curl_init();
19 | curl_setopt($tCh, CURLOPT_POST, true);
20 | curl_setopt($tCh, CURLOPT_POSTFIELDS, $pData);
21 | curl_setopt($tCh, CURLOPT_HTTPHEADER, array("Content-type: application/x-www-form-urlencoded"));
22 | curl_setopt($tCh, CURLOPT_URL, $pUrl);
23 | curl_setopt($tCh, CURLOPT_RETURNTRANSFER, true);
24 | curl_setopt($tCh, CURLOPT_SSL_VERIFYPEER, false);
25 | $tResult = curl_exec($tCh);
26 | curl_close($tCh);
27 | $tResult=json_decode ($tResult,true);
28 | return $tResult;
29 | }
30 |
31 | function HangqingRequest($pUrl){
32 | $tCh = curl_init();
33 | curl_setopt($tCh, CURLOPT_URL, $pUrl);
34 | curl_setopt($tCh, CURLOPT_RETURNTRANSFER, true);
35 | curl_setopt($tCh, CURLOPT_SSL_VERIFYPEER, false);
36 | curl_setopt($tCh, CURLOPT_TIMEOUT, 1);
37 | $tResult = curl_exec($tCh);
38 | curl_close($tCh);
39 | $tResult=json_decode ($tResult,true);
40 | return $tResult;
41 | }
42 |
43 | function createSign($pParams = array()){
44 | $tPreSign = http_build_query($pParams, '', '&');
45 | $SecretKey = sha1($this->secret_key);
46 | $tSign=hash_hmac('md5',$tPreSign,$SecretKey);
47 | $pParams['sign'] = $tSign;
48 | $pParams['reqTime'] = time()*1000;
49 | $tResult=http_build_query($pParams, '', '&');
50 | return $tResult;
51 | }
52 |
53 | function Hangqing(){
54 | $Url_btc="http://api.zb.com/data/v1/ticker?currency=btc";
55 | $res=array();
56 | $res=$this->HangqingRequest($Url_btc);
57 | return $res;
58 | }
59 |
60 | function MarketDepth($N=20){
61 | $res=$this->HangqingBtc();
62 | $res_ask=array_reverse(array_slice($res["asks"] , -$N, $N));
63 | $res_bid=array_slice($res["bids"] , 0, $N) ;
64 | $ans=array("asks"=>$res_ask,"bids"=>$res_bid);
65 | return $ans;
66 | }
67 |
68 |
69 | //BTC 下单
70 | function Trade($Price,$Amount,$Tradetype){
71 | $parameters=array("accesskey"=>$this->access_key,"amount"=>$Amount,"currency"=>"btc","method"=>"order","price"=>$Price,"tradeType"=>$Tradetype);
72 | $url= "https://trade.zb.com/api/order";
73 | $post=$this->createSign($parameters);
74 | $res=$this->httpRequest($url,$post);
75 | return $res;
76 | }
77 |
78 | //BTC 取消订单
79 | function CancelOrder($OrderID){
80 | $parameters=array("accesskey"=>$this->access_key,"currency"=>"btc","id"=>$OrderID,"method"=>"cancelOrder");
81 | $url='https://trade.zb.com/api/cancelOrder';
82 | $post=$this->createSign($parameters);
83 | $res=$this->httpRequest($url,$post);
84 | return $res;
85 | }
86 |
87 | //LTC 取消订单
88 | function CancelOrder_ltc($OrderID){
89 | $parameters=array("accesskey"=>$this->access_key,"currency"=>"ltc","id"=>$OrderID,"method"=>"cancelOrder");
90 | $url='https://trade.zb.com/api/cancelOrder';
91 | $post=$this->createSign($parameters);
92 | $res=$this->httpRequest($url,$post);
93 | return $res;
94 | }
95 |
96 |
97 | function Fund(){
98 | $parameters=array("accesskey"=>$this->access_key,"method"=>"getAccountInfo");
99 | $url='https://trade.zb.com/api/getAccountInfo';
100 | $post=$this->createSign($parameters);
101 | $res=$this->httpRequest($url,$post);
102 | return $res;
103 | }
104 |
105 | //获取订单信息
106 | function GetOrder($OrderID){
107 | $parameters=array("accesskey"=>$this->access_key,"currency"=>"btc","id"=>$OrderID,"method"=>"getOrder");
108 | $url= 'https://trade.zb.com/api/getOrder';
109 | $post=$this->createSign($parameters);
110 | $res=$this->httpRequest($url,$post);
111 | return $res;
112 | }
113 |
114 | //获取订单信息
115 | function GetOrder_ltc($OrderID){
116 | $parameters=array("accesskey"=>$this->access_key,"currency"=>"ltc","id"=>$OrderID,"method"=>"getOrder");
117 | $url= 'https://trade.zb.com/api/getOrder';
118 | $post=$this->createSign($parameters);
119 | $res=$this->httpRequest($url,$post);
120 | return $res;
121 | }
122 |
123 | }
124 | ?>
125 |
126 |
127 |
128 |
--------------------------------------------------------------------------------
/PYTHON/rest 接口/python3/test.py:
--------------------------------------------------------------------------------
1 |
2 | from zapi import ZApi
3 |
4 |
5 |
6 |
7 |
8 | if __name__ == '__main__':
9 | zb = ZApi(access_key='ffff', secret_key='ddddd')
10 | # a = zb.all_ticker()
11 | a = zb.order( "bts_usdt", 1, 0.1, 0.1)
12 | print(a)
13 |
14 |
15 |
--------------------------------------------------------------------------------
/PYTHON/rest 接口/python3/zapi.py:
--------------------------------------------------------------------------------
1 | import hashlib
2 | import struct
3 | # import sha
4 | import time
5 | import requests
6 |
7 |
8 | suc_codes = ["1000"]
9 |
10 | DEBUG = True
11 |
12 | errcode = {
13 | "1000": "success",
14 | "1001": "normal error",
15 | "1002": "internal error",
16 | "1003": "verify not passed",
17 | "1004": "fund security password locked",
18 | "1005": "fund security password not right",
19 | "1006": "real-name authentication verifying or not passed",
20 | "1009": "current api not in service",
21 | "2001": "RMB not sufficient",
22 | "2002": "BTC not sufficient",
23 | "2003": "LTC not sufficient",
24 | "2005": "ETH not sufficient",
25 | "2006": "ETC not sufficient",
26 | "2007": "BTS not sufficient",
27 | "2009": "balance not sufficient",
28 | "3001": "order not found",
29 | "3002": "invalid amount of money",
30 | "3003": "invalid count",
31 | "3004": "user not exists",
32 | "3005": "illegal argument",
33 | "3006": "IP error",
34 | "3007": "time expired",
35 | "3008": "trade history not found",
36 | "4001": "API locked or not opened",
37 | "4002": "requests too frequently"
38 | }
39 |
40 | ORDER_TYPE_BUY = 1
41 | ORDER_TYPE_SELL = 0
42 |
43 | ORDER_STATUS_CANCELED = 1
44 | ORDER_STATUS_DONE = 2
45 | ORDER_STATUS_WAITING = 3
46 |
47 | TPL_MARKETS = 'http://api.zb.com/data/v1/markets'
48 | TPL_ALL_MARKET = 'http://api.zb.cn/data/v1/allTicker'
49 | TPL_MARKET = 'http://api.zb.com/data/v1/ticker?market={MARKET}'
50 | TPL_DEPTH = 'http://api.zb.com/data/v1/depth?market={MARKET}&size={SIZE}'
51 | TPL_TRADES = 'http://api.zb.com/data/v1/trades?market={MARKET}'
52 | TPL_KLINE = 'http://api.zb.com/data/v1/kline?market={MARKET}'
53 |
54 | URL_ORDER = 'https://trade.zb.com/api/order'
55 | URL_CANCEL_ORDER = 'https://trade.zb.com/api/cancelOrder'
56 | URL_GET_ORDER = 'https://trade.zb.com/api/getOrder'
57 | URL_GET_ORDERS = 'https://trade.zb.com/api/getOrders'
58 | URL_GET_ORDERS_NEW = 'https://trade.zb.com/api/getOrdersNew'
59 | URL_GET_ORDERS_IGNORE_TRADE_TYPE = 'https://trade.zb.com/api/getOrdersIgnoreTradeType'
60 | URL_GET_UNFINISHED_ORDERS_IGNORE_TRADE_TYPE = 'https://trade.zb.com/api/getUnfinishedOrdersIgnoreTradeType'
61 | URL_GET_ACCOUNT_INFO = 'https://trade.zb.com/api/getAccountInfo'
62 | URL_GET_USER_ADDRESS = 'https://trade.zb.com/api/getUserAddress'
63 | URL_GET_WITHDRAW_ADDRESS = 'https://trade.zb.com/api/getWithdrawAddress'
64 | URL_GET_WITHDRAW_RECORD = 'https://trade.zb.com/api/getWithdrawRecord'
65 | URL_GET_CHARGE_RECORD = 'https://trade.zb.com/api/getChargeRecord'
66 | URL_WITHDRAW = 'https://trade.zb.com/api/withdraw'
67 |
68 | URL_doTransferFunds = 'https://trade.zb.cn/api/doTransferFunds'
69 |
70 | class ZApi:
71 | def __init__(self, access_key, secret_key):
72 | """
73 | opened markets and status, format:
74 | {
75 | "btc_usdt": {
76 | "amountScale": 4,
77 | "priceScale": 2
78 | },
79 | "ltc_usdt": {
80 | "amountScale": 3,
81 | "priceScale": 2
82 | }
83 | ...
84 | }
85 | """
86 | self._access_key_ = access_key
87 | self._secret_key_ = secret_key
88 | self._markets_ = self.markets()
89 | if len(self._markets_) < 1:
90 | raise Exception("Get markets status failed")
91 |
92 | def get(self, url):
93 | while True:
94 | try:
95 | r = requests.get(url)
96 | except Exception:
97 | time.sleep(0.5)
98 | continue
99 | if r.status_code != 200:
100 | time.sleep(0.5)
101 | continue
102 | r_info = r.json()
103 | r.close()
104 | return r_info
105 |
106 | def check_market_code(self, market):
107 | if not market:
108 | return False
109 | if market not in self._markets_:
110 | return False
111 | else:
112 | return True
113 |
114 | def markets(self):
115 | """
116 | markets data, result format:
117 | {
118 | "btc_usdt": {
119 | "amountScale": 4,
120 | "priceScale": 2
121 | },
122 | "ltc_usdt": {
123 | "amountScale": 3,
124 | "priceScale": 2
125 | }
126 | ...
127 | }
128 | :return: result data of markets
129 | """
130 | url = TPL_MARKETS
131 | return self.get(url)
132 | def all_ticker(self,):
133 | """
134 | ticker data, result format:
135 | {
136 | "ticker": {
137 | "vol": "40.463",
138 | "last": "0.899999",
139 | "sell": "0.5",
140 | "buy": "0.225",
141 | "high": "0.899999",
142 | "low": "0.081"
143 | },
144 | "date": "1507875747359"
145 | }
146 | :param market: market code string
147 | :return: ticker result
148 | """
149 | url = TPL_ALL_MARKET
150 | return self.get(url)
151 |
152 | def ticker(self, market):
153 | """
154 | ticker data, result format:
155 | {
156 | "ticker": {
157 | "vol": "40.463",
158 | "last": "0.899999",
159 | "sell": "0.5",
160 | "buy": "0.225",
161 | "high": "0.899999",
162 | "low": "0.081"
163 | },
164 | "date": "1507875747359"
165 | }
166 | :param market: market code string
167 | :return: ticker result
168 | """
169 | url = TPL_MARKET.format(MARKET=market)
170 | return self.get(url)
171 |
172 | def depth(self, market, size):
173 | """
174 | depth data of specific market, result format:
175 | {
176 | "asks": [
177 | [
178 | 83.28,
179 | 11.8
180 | ]...
181 | ],
182 | "bids": [
183 | [
184 | 81.91,
185 | 3.65
186 | ]...
187 | ],
188 | "timestamp" : timestamp
189 | }
190 | :param market: market code string
191 | :param size: depth size
192 | :return: result depth data
193 | """
194 | url = TPL_DEPTH.format(MARKET=market, SIZE=str(size))
195 | return self.get(url)
196 |
197 | def trades(self, market):
198 | """
199 | trade history, result format:
200 | [
201 | {
202 | "amount": 0.541,
203 | "date": 1472711925,
204 | "price": 81.87,
205 | "tid": 16497097,
206 | "trade_type": "ask",
207 | "type": "sell"
208 | }...
209 | ]
210 | :return: trade history data
211 | """
212 | url = TPL_TRADES.format(MARKET=market)
213 | return self.get(url)
214 |
215 | def kline(self, market):
216 | """
217 | kline data, result format:
218 | {
219 | "data": [
220 | [
221 | 1472107500000,
222 | 3840.46,
223 | 3843.56,
224 | 3839.58,
225 | 3843.3,
226 | 492.456
227 | ]...
228 | ],
229 | "moneyType": "btc",
230 | "symbol": "ltc"
231 | }
232 | :param market: market code
233 | :return: kline data
234 | """
235 | url = TPL_KLINE.format(MARKET=market)
236 | return self.get(url)
237 |
238 | def order(self, market, type, amount, price):
239 | """
240 | order api, result format:
241 | {
242 | "code": "1000",
243 | "message": "***",
244 | "id": "20131228361867"
245 | }
246 | :param market: currency
247 | :param type: ORDER_TYPE_BUY or ORDER_TYPE_SELL
248 | :param amount: order amount
249 | :param price: order price
250 | :return: order result
251 | """
252 | params = 'accesskey=%s&amount=%s¤cy=%s&method=order&price=%s&tradeType=%s' % (self._access_key_, amount, market, price, type)
253 | return self.call_api(url=URL_ORDER, params=params)
254 |
255 | def cancel_order(self, market, order_id):
256 | """
257 | cancel an order, result format:
258 | {
259 | "code": "1000",
260 | "message": "***"
261 | }
262 | :param market: currency
263 | :param order_id: order id
264 | :return: result
265 | """
266 | params = 'accesskey=%s¤cy=%s&id=%s&method=cancelOrder' % (self._access_key_, market, order_id)
267 | return self.call_api(url=URL_CANCEL_ORDER, params=params)
268 |
269 | def cancel_allorder(self,market,page_index=1, page_size=5):
270 | flag = False
271 | orders = self.get_unfinished_orders_ignore_trade_type(market,page_index, page_size)
272 | #print('order',orders)
273 | if isinstance(orders,list) and len(orders) > 0 and 'id' in orders[0].keys():
274 | flag = True
275 | while flag :
276 | time.sleep(0.1)
277 | for order in orders:
278 | #print(market,orders)
279 | self.cancel_order(market,order['id'])
280 | orders = self.get_unfinished_orders_ignore_trade_type(market,page_index, page_size)
281 | if isinstance(orders,list) and len(orders) > 0 and 'id' in orders[0].keys():
282 | flag = True
283 | else :
284 | print('%s撤销所有订单完成!返回%s:'%(market,orders))
285 | flag = False
286 |
287 | def get_order(self, market, order_id):
288 | """
289 | get order detail, result format:
290 | {
291 | "currency": "btc",
292 | "id": "20150928158614292",
293 | "price": 1560,
294 | "status": 3,
295 | "total_amount": 0.1,
296 | "trade_amount": 0,
297 | "trade_price" : 6000,
298 | "trade_date": 1443410396717,
299 | "trade_money": 0,
300 | "type": 0,
301 | }
302 | :param market: currency
303 | :param order_id: order id
304 | :return: result
305 | """
306 | params = 'accesskey=%s¤cy=%s&id=%s&method=getOrder' % (self._access_key_, market, order_id)
307 | return self.call_api(url=URL_GET_ORDER, params=params)
308 |
309 | def get_orders(self, market, page, type):
310 | """
311 | get multiple orders, result format:
312 | [
313 | {
314 | "currency": "btc",
315 | "id": "20150928158614292",
316 | "price": 1560,
317 | "status": 3,
318 | "total_amount": 0.1,
319 | "trade_amount": 0,
320 | "trade_price" : 6000,
321 | "trade_date": 1443410396717,
322 | "trade_money": 0,
323 | "type": 0
324 | }...
325 | ]
326 | :param market: currency
327 | :param page: page index
328 | :param type: order type
329 | :return: result
330 | """
331 | params = 'accesskey=%s¤cy=%s&method=getOrders&pageIndex=%s&tradeType=%s' % (self._access_key_, market, page, type)
332 | return self.call_api(url=URL_GET_ORDERS, params=params)
333 |
334 | def get_orders_new(self, market, page_index, page_size, type):
335 | """
336 | get multiple orders, result format same as get_orders
337 | :param market: currency
338 | :param page_index: page index
339 | :param page_size: page size
340 | :param type: order type
341 | :return: result
342 | """
343 | params = 'accesskey=%s¤cy=%s&method=getOrdersNew&pageIndex=%s&pageSize=%s&tradeType=%s' % (self._access_key_, market, page_index, page_size, type)
344 | return self.call_api(url=URL_GET_ORDERS_NEW, params=params)
345 |
346 | def get_orders_ignore_tader_type(self, market, page_index, page_size):
347 | """
348 | get multiple orders ignore type, result format same as get_orders
349 | :param market: currency
350 | :param page_index: page index
351 | :param page_size: page size
352 | :return: result
353 | """
354 | params = 'accesskey=%s¤cy=%s&method=getOrdersIgnoreTradeType&pageIndex=%s&pageSize=%s' % (self._access_key_, market, page_index, page_size)
355 | return self.call_api(url=URL_GET_ORDERS_IGNORE_TRADE_TYPE, params=params)
356 |
357 | def get_unfinished_orders_ignore_trade_type(self, market, page_index, page_size):
358 | """
359 | get multiple unfinished orders ignore type, result format same as get_orders
360 | :param market: currency
361 | :param page_index: page index
362 | :param page_size: page size
363 | :return: result
364 | """
365 | params = 'accesskey=%s¤cy=%s&method=getUnfinishedOrdersIgnoreTradeType&pageIndex=%s&pageSize=%s' % (self._access_key_, market, page_index, page_size)
366 | # print(params)
367 | return self.call_api(url=URL_GET_UNFINISHED_ORDERS_IGNORE_TRADE_TYPE, params=params)
368 |
369 | def zhuanzhang_zi(self,amount,currency,fromUerName,toUserName):
370 | """
371 | get multiple unfinished orders ignore type, result format same as get_orders
372 | :param market: currency
373 | :param page_index: page index
374 | :param page_size: page size
375 | :return: result
376 | """
377 | params = 'accesskey=%s&amount=%s¤cy=%s&fromUserName=%s&method=doTransferFunds&toUserName=%s' % (self._access_key_, amount,currency,fromUerName,toUserName)
378 | return self.call_api(url='https://trade.zb.cn/api/doTransferFunds', params=params)
379 | def huoquzizhanghao(self):
380 | """:
381 | """
382 | # params = 'accesskey=%s&method=getAccountInfo' % self._access_key_
383 | params = 'accesskey=%s&method=getSubUserList' % self._access_key_
384 |
385 | return self.call_api(url='https://trade.zb.cn/api/getSubUserList', params=params)
386 |
387 | def chuangjianzi(self):
388 | """:
389 | """
390 | # params = 'accesskey=%s&method=getAccountInfo' % self._access_key_
391 | params = 'accesskey=%s&method=getSubUserList' % self._access_key_
392 | params = 'accesskey=%s&memo=%s&password=%s&method=addSubUser&subUserName=ceshi11' % (self._access_key_, 'ceshi11', '1234qwer')
393 | return self.call_api(url='https://trade.zb.cn/api/addSubUser', params=params)
394 |
395 |
396 | def get_account_info(self):
397 | """
398 | get account information, result format:
399 | {
400 | "result": {
401 | "coins": [
402 | {
403 | "freez": "0.00000000",
404 | "enName": "BTC",
405 | "unitDecimal": 8,
406 | "cnName": "BTC",
407 | "unitTag": "*",
408 | "available": "0.00000000",
409 | "key": "btc"
410 | },
411 | {
412 | "freez": "0.00000000",
413 | "enName": "LTC",
414 | "unitDecimal": 8,
415 | "cnName": "LTC",
416 | "unitTag": "*",
417 | "available": "0.00000000",
418 | "key": "ltc"
419 | },
420 | ...
421 | ],
422 | "base": {
423 | "username": "134150***",
424 | "trade_password_enabled": true,
425 | "auth_google_enabled": false,
426 | "auth_mobile_enabled": true
427 | }
428 | }
429 | }
430 | :return: result
431 | """
432 | params = 'accesskey=%s&method=getAccountInfo' % self._access_key_
433 | return self.call_api(url=URL_GET_ACCOUNT_INFO, params=params)
434 |
435 | def get_user_address(self, currency):
436 | """
437 | get user address, result format:
438 | {
439 | "code": 1000,
440 | "message": {
441 | "des": "success",
442 | "isSuc": true,
443 | "datas": {
444 | "key": "0x0af7f36b8f09410f3df62c81e5846da673d4d9a9"
445 | }
446 | }
447 | }
448 | :param currency: currency
449 | :return: result
450 | """
451 | params = 'accesskey=%s¤cy=%s&method=getUserAddress' % (self._access_key_, currency)
452 | return self.call_api(url=URL_GET_USER_ADDRESS, params=params)
453 |
454 | def get_withdraw_address(self, currency):
455 | """
456 | get withdraw address, result format:
457 | {
458 | "code": 1000,
459 | "message": {
460 | "des": "success",
461 | "isSuc": true,
462 | "datas": {
463 | "key": "0x0af7f36b8f09410f3df62c81e5846da673d4d9a9"
464 | }
465 | }
466 | }
467 | :param currency: currency
468 | :return: result
469 | """
470 | params = 'accesskey=%s¤cy=%s&method=getWithdrawAddress' % (self._access_key_, currency)
471 | return self.call_api(url=URL_GET_WITHDRAW_ADDRESS, params=params)
472 |
473 | def get_withdraw_record(self, currency, page_index, page_size):
474 | """
475 | get withdraw record, result format:
476 | {
477 | "code": 1000,
478 | "message": {
479 | "des": "success",
480 | "isSuc": true,
481 | "datas": {
482 | "list": [
483 | {
484 | "amount": 0.01,
485 | "fees": 0.001,
486 | "id": 2016042556231,
487 | "manageTime": 1461579340000,
488 | "status": 3,
489 | "submitTime": 1461579288000,
490 | "toAddress": "14fxEPirL9fyfw1i9EF439Pq6gQ5xijUmp"
491 | }...
492 | ],
493 | "pageIndex": 1,
494 | "pageSize": 10,
495 | "totalCount": 4,
496 | "totalPage": 1
497 | }
498 | }
499 | }
500 | :param currency:
501 | :param page_index:
502 | :param page_size:
503 | :return:
504 | """
505 | params = 'accesskey=%s¤cy=%s&method=getWithdrawRecord&pageIndex=%s&pageSize=%s' % (self._access_key_, currency, page_index, page_size)
506 | return self.call_api(url=URL_GET_WITHDRAW_RECORD, params=params)
507 |
508 | def get_charge_record(self, currency, page_index, page_size):
509 | """
510 | get charge record, result format:
511 | {
512 | "code": 1000,
513 | "message": {
514 | "des": "success",
515 | "isSuc": true,
516 | "datas": {
517 | "list": [
518 | {
519 | "address": "1FKN1DZqCm8HaTujDioRL2Aezdh7Qj7xxx",
520 | "amount": "1.00000000",
521 | "confirmTimes": 1,
522 | "currency": "BTC",
523 | "description": "***",
524 | "hash": "7ce842de187c379abafadd64a5fe66c5c61c8a21fb04edff9532234a1dae6xxx",
525 | "id": 558,
526 | "itransfer": 1,
527 | "status": 2,
528 | "submit_time": "2016-12-07 18:51:57"
529 | }...
530 | ],
531 | "pageIndex": 1,
532 | "pageSize": 10,
533 | "total": 8
534 | }
535 | }
536 | }
537 | :param currency: currency
538 | :param page_index: page index
539 | :param page_size: page size
540 | :return: result
541 | """
542 | params = 'accesskey=%s¤cy=%s&method=getChargeRecord&pageIndex=%s&pageSize=%s' % (self._access_key_, currency, page_index, page_size)
543 | return self.call_api(url=URL_GET_CHARGE_RECORD, params=params)
544 |
545 | def withdraw(self, currency, amount, fees, itransfer, addr, pwd):
546 | """
547 | withdraw coins, result format:
548 | {
549 | "code": 1000,
550 | "message": "success",
551 | "id": "***"
552 | }
553 | :param currency: currency
554 | :param amount: amount
555 | :param fees: fees
556 | :param itransfer: itransfer
557 | :param addr: receive address
558 | :param pwd: safe password of current account
559 | :return: result
560 | """
561 | params = 'accesskey=%s&amount=%s¤cy=%s&fees=%s&itransfer=%s&method=withdraw&receiveAddr=%s&safePwd=%s' % (self._access_key, amount, currency, fees, itransfer, addr, pwd)
562 | return self.call_api(url=URL_WITHDRAW, params=params)
563 |
564 | def call_api(self, url, params=''):
565 | full_url = url
566 | if params:
567 | sha_secret = self.digest(self._secret_key_)
568 | sign = self.hmac_sign(params, sha_secret)
569 | req_time = int(round(time.time() * 1000))
570 | params += '&sign=%s&reqTime=%d' % (sign, req_time)
571 | full_url += '?' + params
572 | result = {}
573 | while True:
574 | try:
575 | r = requests.get(full_url, timeout=2)
576 | except Exception:
577 | time.sleep(0.5)
578 | continue
579 | if r.status_code != 200:
580 | time.sleep(0.5)
581 | r.close()
582 | continue
583 | else:
584 | result = r.json()
585 | r.close()
586 | break
587 | return result
588 |
589 | @staticmethod
590 | def fill(value, lenght, fill_byte):
591 | if len(value) >= lenght:
592 | return value
593 | else:
594 | fill_size = lenght - len(value)
595 | return value + chr(fill_byte) * fill_size
596 |
597 | @staticmethod
598 | def xor(s, value):
599 | slist = list(s.decode('utf-8'))
600 | for index in range(len(slist)):
601 | slist[index] = chr(ord(slist[index]) ^ value)
602 | return "".join(slist)
603 |
604 | def hmac_sign(self, arg_value, arg_key):
605 | keyb = struct.pack("%ds" % len(arg_key), arg_key.encode('utf-8'))
606 | value = struct.pack("%ds" % len(arg_value), arg_value.encode('utf-8'))
607 | k_ipad = self.xor(keyb, 0x36)
608 | k_opad = self.xor(keyb, 0x5c)
609 | k_ipad = self.fill(k_ipad, 64, 54)
610 | k_opad = self.fill(k_opad, 64, 92)
611 | m = hashlib.md5()
612 | m.update(k_ipad.encode('utf-8'))
613 | m.update(value)
614 | dg = m.digest()
615 |
616 | m = hashlib.md5()
617 | m.update(k_opad.encode('utf-8'))
618 | subStr = dg[0:16]
619 | m.update(subStr)
620 | dg = m.hexdigest()
621 | return dg
622 |
623 | def digest(self, arg_value):
624 | value = struct.pack("%ds" % len(arg_value), arg_value.encode('utf-8'))
625 | h = hashlib.sha1()
626 | h.update(value)
627 | dg = h.hexdigest()
628 | return dg
629 |
630 |
631 |
632 |
--------------------------------------------------------------------------------
/PYTHON/rest 接口/zb_api_python.py:
--------------------------------------------------------------------------------
1 | import json, urllib2, hashlib,struct,sha,time
2 |
3 | class zb_api:
4 |
5 | def __init__(self, mykey, mysecret):
6 | self.mykey = mykey
7 | self.mysecret = mysecret
8 |
9 | def __fill(self, value, lenght, fillByte):
10 | if len(value) >= lenght:
11 | return value
12 | else:
13 | fillSize = lenght - len(value)
14 | return value + chr(fillByte) * fillSize
15 |
16 | def __doXOr(self, s, value):
17 | slist = list(s)
18 | for index in xrange(len(slist)):
19 | slist[index] = chr(ord(slist[index]) ^ value)
20 | return "".join(slist)
21 |
22 | def __hmacSign(self, aValue, aKey):
23 | keyb = struct.pack("%ds" % len(aKey), aKey)
24 | value = struct.pack("%ds" % len(aValue), aValue)
25 | k_ipad = self.__doXOr(keyb, 0x36)
26 | k_opad = self.__doXOr(keyb, 0x5c)
27 | k_ipad = self.__fill(k_ipad, 64, 54)
28 | k_opad = self.__fill(k_opad, 64, 92)
29 | m = hashlib.md5()
30 | m.update(k_ipad)
31 | m.update(value)
32 | dg = m.digest()
33 |
34 | m = hashlib.md5()
35 | m.update(k_opad)
36 | subStr = dg[0:16]
37 | m.update(subStr)
38 | dg = m.hexdigest()
39 | return dg
40 |
41 | def __digest(self, aValue):
42 | value = struct.pack("%ds" % len(aValue), aValue)
43 | print value
44 | h = sha.new()
45 | h.update(value)
46 | dg = h.hexdigest()
47 | return dg
48 |
49 | def __api_call(self, path, params = ''):
50 | try:
51 | SHA_secret = self.__digest(self.mysecret)
52 | sign = self.__hmacSign(params, SHA_secret)
53 | reqTime = (int)(time.time()*1000)
54 | params+= '&sign=%s&reqTime=%d'%(sign, reqTime)
55 | url = 'https://trade.zb.com/api/' + path + '?' + params
56 | request = urllib2.Request(url)
57 | response = urllib2.urlopen(request, timeout=2)
58 | doc = json.loads(response.read())
59 | return doc
60 | except Exception,ex:
61 | print >>sys.stderr, 'zb request ex: ', ex
62 | return None
63 |
64 | def query_account(self):
65 | try:
66 | params = "accesskey="+self.mykey+"&method=getAccountInfo"
67 | path = 'getAccountInfo'
68 |
69 | obj = self.__api_call(path, params)
70 | #print obj
71 | return obj
72 | except Exception,ex:
73 | print >>sys.stderr, 'zb query_account exception,',ex
74 | return None
75 |
76 |
77 | if __name__ == '__main__':
78 | access_key = 'accesskey'
79 | access_secret = 'secretkey'
80 |
81 | api = zb_api(access_key, access_secret)
82 |
83 | print api.query_account()
84 |
--------------------------------------------------------------------------------
/PYTHON/rest 接口/zb_api_python3.py:
--------------------------------------------------------------------------------
1 | __author__ = 'Ziyang'
2 |
3 | import json, hashlib,struct,time,sys
4 | import urllib.request
5 |
6 | class zb_api:
7 |
8 | def __init__(self, mykey, mysecret):
9 | self.mykey = mykey
10 | self.mysecret = mysecret
11 | self.jm = ''
12 |
13 | def __fill(self, value, lenght, fillByte):
14 | if len(value) >= lenght:
15 | return value
16 | else:
17 | fillSize = lenght - len(value)
18 | return value + chr(fillByte) * fillSize
19 |
20 | def __doXOr(self, s, value):
21 | slist = list(s.decode('utf-8'))
22 | for index in range(len(slist)):
23 | slist[index] = chr(ord(slist[index]) ^ value)
24 | return "".join(slist)
25 |
26 | def __hmacSign(self, aValue, aKey):
27 | keyb = struct.pack("%ds" % len(aKey), aKey.encode('utf-8'))
28 | value = struct.pack("%ds" % len(aValue), aValue.encode('utf-8'))
29 | k_ipad = self.__doXOr(keyb, 0x36)
30 | k_opad = self.__doXOr(keyb, 0x5c)
31 | k_ipad = self.__fill(k_ipad, 64, 54)
32 | k_opad = self.__fill(k_opad, 64, 92)
33 | m = hashlib.md5()
34 | m.update(k_ipad.encode('utf-8'))
35 | m.update(value)
36 | dg = m.digest()
37 |
38 | m = hashlib.md5()
39 | m.update(k_opad.encode('utf-8'))
40 | subStr = dg[0:16]
41 | m.update(subStr)
42 | dg = m.hexdigest()
43 | return dg
44 |
45 | def __digest(self, aValue):
46 | value = struct.pack("%ds" % len(aValue), aValue.encode('utf-8'))
47 | print(value)
48 | h = hashlib.sha1()
49 | h.update(value)
50 | dg = h.hexdigest()
51 | return dg
52 |
53 | def __api_call(self, path, params = ''):
54 | try:
55 | SHA_secret = self.__digest(self.mysecret)
56 | sign = self.__hmacSign(params, SHA_secret)
57 | self.jm = sign
58 | reqTime = (int)(time.time()*1000)
59 | params += '&sign=%s&reqTime=%d'%(sign, reqTime)
60 | url = 'https://trade.zb.com/api/' + path + '?' + params
61 | req = urllib.request.Request(url)
62 | res = urllib.request.urlopen(req, timeout=2)
63 | doc = json.loads(res.read())
64 | return doc
65 | except Exception as ex:
66 | print(sys.stderr, 'zb request ex: ', ex)
67 | return None
68 |
69 | def query_account(self):
70 | try:
71 | params = "accesskey="+self.mykey+"&method=getAccountInfo"
72 | path = 'getAccountInfo'
73 |
74 | obj = self.__api_call(path, params)
75 | #print obj
76 | return obj
77 | except Exception as ex:
78 | print(sys.stderr, 'zb query_account exception,',ex)
79 | return None
80 |
81 |
82 | if __name__ == '__main__':
83 | access_key = 'access_key'
84 | access_secret = 'access_secret'
85 |
86 | api = zb_api(access_key, access_secret)
87 |
88 | print(api.query_account())
89 |
--------------------------------------------------------------------------------
/PYTHON/websocket 接口/readme:
--------------------------------------------------------------------------------
1 | 感谢GitHub用户:ipqhjjybj,提供的技术支持
2 |
--------------------------------------------------------------------------------
/PYTHON/websocket 接口/zb.com-api-master/README.md:
--------------------------------------------------------------------------------
1 | # zb.com-api
2 | zb.com api
3 |
4 | A simple demo for zb.com .Just some useful functions.
5 | any question contact sunxuanzhi@lingdianzn.com
6 |
--------------------------------------------------------------------------------
/PYTHON/websocket 接口/zb.com-api-master/zb.comskd.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding:utf-8 -*-
3 | #author:xuanzhi
4 |
5 | import requests
6 | import json
7 | import time
8 | import hashlib
9 | import hmac
10 | try:
11 | from urllib import urlencode
12 | except:
13 | from urllib.parse import urlencode
14 |
15 |
16 |
17 |
18 | BASE_API_PUBLIC = 'http://api.zb.com/data/v1'
19 | BASE_API_PRIVATE = 'https://trade.zb.com/api'
20 |
21 | DEFAULT_HEADERS = {'Content-Type': 'application/x-www-form-urlencode'}
22 |
23 |
24 | proxies = {
25 | 'https': 'http://127.0.0.1:1087',
26 | 'http': 'http://127.0.0.1:1087'
27 | }
28 |
29 | class Client_Zb():
30 | def __init__(self, apikey, secretkey):
31 | self._public_key = str(apikey)
32 | self._private_key = str(secretkey)
33 | self.sessn = requests.Session()
34 | self.adapter = requests.adapters.HTTPAdapter(pool_connections=5,
35 | pool_maxsize=5, max_retries=5)
36 | self.sessn.mount('http://', self.adapter)
37 | self.sessn.mount('https://', self.adapter)
38 | self.order_list = []
39 |
40 | def signature(self,message):
41 | sha_secretkey = hashlib.sha1(self._private_key.encode('utf-8')).hexdigest()
42 | signature = hmac.new(sha_secretkey.encode('utf-8'),message.encode('utf-8'),digestmod='MD5').hexdigest() # 32位md5算法进行加密签名
43 | return signature
44 |
45 | def signedRequest(self, method, path, params):
46 |
47 | # create signature:
48 |
49 | params['accesskey'] = self._public_key
50 | param = ''
51 | for key in sorted(params.keys()):
52 | #print(key)
53 | param += key + '=' + str(params.get(key)) + '&'
54 | param = param.rstrip('&')
55 | #print(param)
56 | signature = self.signature(message=param)
57 | #print(signature)
58 | params['sign'] = str(signature)
59 | params['reqTime'] = int(time.time() * 1000)
60 | #print(params)
61 | resp = self.sessn.request(method,BASE_API_PRIVATE+path,headers=DEFAULT_HEADERS,data=None,params=params,proxies=proxies)
62 | data = json.loads(resp.content)
63 | return data
64 |
65 | def ticker(self,symbol='eth_btc'):
66 | symbol = symbol.lower()
67 | if 'usd' in symbol:
68 | symbol = symbol.replace('usd','usdt')
69 | params = {'market':symbol}
70 | url = BASE_API_PUBLIC + '/ticker'
71 | #print(url)
72 | resp = requests.request("GET",url,params=params,proxies=proxies)
73 | data = json.loads(resp.text)['ticker']
74 | return data
75 |
76 | def depth(self,symbol='eth_btc'):
77 | symbol = symbol.lower()
78 | if 'usd' in symbol:
79 | symbol = symbol.replace('usd','usdt')
80 | params = {'market':symbol}
81 | url = BASE_API_PUBLIC + '/depth'
82 | resp = requests.request("GET",url,params=params,proxies=proxies)
83 | data = json.loads(resp.text)
84 | temp = {'asks':data['asks'][::-1],'bids':data['bids']}
85 | return temp
86 |
87 | def balance(self):
88 | params = {'method':'getAccountInfo'}
89 | resp = self.signedRequest(method="GET",path ='/getAccountInfo',params=params)['result']['coins']
90 | avalible,frozen,total = {},{},{}
91 | for item in resp:
92 | coin = item['enName']
93 | avalible[coin] = float(item['available'])
94 | frozen[coin] = float(item['freez'])
95 | total[coin] = avalible[coin] + frozen[coin]
96 | temp = {'total':total,'avalible':avalible,'frozen':frozen}
97 | return temp
98 |
99 | def trade(self,trade_type,price,amount,symbol):
100 | '''
101 | 只存在限价买卖,limit_buy/limit_sell
102 | 对于成功的订单,返回该订单号,并将其存入订单列表,以便后续的查看与撤单
103 |
104 | '''
105 | symbol = symbol.lower()
106 | if 'usd' in symbol:
107 | symbol = symbol.replace('usd','usdt')
108 | params = {'method':'order'}
109 | order_type,side = trade_type.split('_')
110 | params = {'currency':symbol,'price':price,'amount':amount}
111 | if order_type == 'limit':
112 | if side == 'buy':
113 | params['tradeType'] = 1
114 | elif side == 'sell':
115 | params['tradeType'] = 0
116 | else:
117 | print('下单错误!!!')
118 | resp = self.signedRequest(method="GET",path ='/order',params=params)
119 | if resp['code'] == 1000:
120 | return resp['id']
121 | self.order_list.append(resp['id'])
122 | else:
123 | print('下单失败!!!')
124 |
125 |
126 | def order_info(self,symbol,order_id):
127 | symbol = symbol.lower()
128 | if 'usd' in symbol:
129 | symbol = symbol.replace('usd','usdt')
130 | params = {'id':order_id,'currency':symbol,'method':'getOrder'}
131 | resp = self.signedRequest(method="GET",path ='/getOrder',params=params)
132 | return resp
133 |
134 | def cancel_order(self,symbol,order_id):
135 | '''
136 | 传入订单Id与交易对,如撤单成功则打印‘撤单成功’,如撤单失败则打印撤单失败并返回失败的Id
137 | '''
138 | symbol = symbol.lower()
139 | if 'usd' in symbol:
140 | symbol = symbol.replace('usd','usdt')
141 | params = {'id':order_id,'currency':symbol,'method':'ancelOrder'}
142 | resp = self.signedRequest(method="GET",path ='/cancelOrder',params=params)
143 | if resp['code'] == 1000:
144 | print('撤单成功: ',order_id)
145 | self.order_list.remove(order_id)
146 | else:
147 | print('撤单失败: ',order_id)
148 | return order_id
149 |
150 | def cancel_all(self):
151 | '''
152 | 返回所有处理过的订单id,无论成功失败。
153 | '''
154 | orderid_list=self.order_list
155 | processed_id = []
156 | for i in orderid_list:
157 | processed_id.append(cancel_order(i))
158 | return processed_id
159 |
160 | def open_orders(self,symbol,side,pageIndex=1):
161 | '''
162 | 获取多个委托买单或卖单,每次请求返回10条记录
163 | side: 可选 buy 1 /sell 0
164 | pageIndex:记录页数
165 | '''
166 | symbol = symbol.lower()
167 | if 'usd' in symbol:
168 | symbol = symbol.replace('usd','usdt')
169 | params = {'currency':symbol,'tradeType':side,'pageIndex':pageIndex,'method':'getOrdersNew'}
170 | resp = self.signedRequest(method="GET",path='/getOrdersNew',params=params)
171 | return resp
172 |
173 | apikey = ''
174 | secretkey = ''
175 | client = Client_Zb(apikey,secretkey)
176 | #print(client.ticker())
177 | #print(client.depth())
178 | print(client.balance())
179 | #print(client.open_orders('eth_btc','buy'))
180 |
181 |
--------------------------------------------------------------------------------
/PYTHON/websocket 接口/zb_py_socket/reame.txt:
--------------------------------------------------------------------------------
1 | API 文档地址
2 | https://www.zb.com/i/developer/websocketApi#config
3 |
4 | 代码 描述
5 | 1000 调用成功
6 | 1001 一般错误提示
7 | 1002 内部错误
8 | 1003 验证不通过
9 | 1004 资金安全密码锁定
10 | 1005 资金安全密码错误,请确认后重新输入。
11 | 1006 实名认证等待审核或审核不通过
12 | 1007 频道为空
13 | 1008 事件为空
14 | 1009 此接口维护中
15 | 2001 人民币账户余额不足
16 | 2002 比特币账户余额不足
17 | 2003 莱特币账户余额不足
18 | 2005 以太币账户余额不足
19 | 2006 ETC币账户余额不足
20 | 2007 BTS币账户余额不足
21 | 2008 EOS币账户余额不足
22 | 2009 账户余额不足
23 | 3001 挂单没有找到
24 | 3002 无效的金额
25 | 3003 无效的数量
26 | 3004 用户不存在
27 | 3005 无效的参数
28 | 3006 无效的IP或与绑定的IP不一致
29 | 3007 请求时间已失效
30 | 3008 交易记录没有找到
31 | 4001 API接口被锁定或未启用
32 | 4002 请求过于频繁
33 |
34 |
35 | WebSocket服务地址
36 | ZB WebSocket服务连接地址:wss://api.zb.com:9999/websocket
37 |
38 | 接口 描述
39 | ticker行情
40 | depth市场深度
41 | trades历史成交
42 | 交易API
43 |
44 | 用于ZB快速进行交易
45 |
46 | 接口 描述
47 | order委托下单
48 | cancelOrder取消委托
49 | getOrder获取委托买单或卖单
50 | getorders获取多个委托买单或卖单,每次请求返回10条记录
51 | getordersignoretradetype取消tradeType字段过滤,可同时获取买单和卖单,每次请求返回pageSize<100条记录
52 | getaccountinfo获取用户信息
53 |
54 |
--------------------------------------------------------------------------------
/PYTHON/websocket 接口/zb_py_socket/test.py:
--------------------------------------------------------------------------------
1 | # encoding: UTF-8
2 |
3 | from vnzb import *
4 |
5 | # 在zb网站申请这两个Key
6 | apiKey = 'apiKey'
7 | secretKey = 'secretKey'
8 |
9 | # 创建API对象
10 | api = ZB_Sub_Spot_Api()
11 |
12 | api.connect_Subpot(apiKey, secretKey, True)
13 |
14 | sleep(3)
15 |
16 | # api.login()
17 | # api.subscribeSpotTicker("ltc_btc")
18 | # api.subscribeSpotDepth("ltc_btc")
19 | # api.subscribeSpotTrades("ltc_btc")
20 | #api.subscribeSpotKlines("bch_btc","30min")
21 |
22 | #api.spotTrade("btc_qc", 1 , "50" , "0.01")
23 | '''
24 | {"message":"操作成功","no":"0","data":"{entrustId:2017121051685}","code":1000,"channel":"btcqc_order","success":true}
25 | {"message":"操作成功","no":"0","data":"{entrustId:2017121051713}","code":1000,"channel":"btcqc_order","success":true}
26 | '''
27 | #api.spotUserInfo()
28 |
29 | #api.spotCancelOrder("btc_qc", "2017121051685")
30 |
31 | api.spotOrderInfo("btc_qc","2017121051713")
32 |
--------------------------------------------------------------------------------
/PYTHON/websocket 接口/zb_py_socket/test.py.bak:
--------------------------------------------------------------------------------
1 | # encoding: UTF-8
2 |
3 | from vnzb import *
4 |
5 | # 在ZB网站申请这两个Key,分别对应用户名和密码
6 | apiKey = 'apiKey'
7 | secretKey = 'secretKey'
8 |
9 | # 创建API对象
10 | api = ZB_Sub_Spot_Api()
11 |
12 | api.connect_Subpot(apiKey, secretKey, True)
13 |
14 | sleep(3)
15 |
16 | # api.login()
17 | # api.subscribeSpotTicker("ltc_btc")
18 | # api.subscribeSpotDepth("ltc_btc")
19 | # api.subscribeSpotTrades("ltc_btc")
20 | #api.subscribeSpotKlines("bch_btc","30min")
21 |
22 | #api.spotTrade("btc_qc", 1 , "50" , "0.01")
23 | '''
24 | {"message":"操作成功","no":"0","data":"{entrustId:2017121051685}","code":1000,"channel":"btcqc_order","success":true}
25 | {"message":"操作成功","no":"0","data":"{entrustId:2017121051713}","code":1000,"channel":"btcqc_order","success":true}
26 | '''
27 | #api.spotUserInfo()
28 |
29 | #api.spotCancelOrder("btc_qc", "2017121051685")
30 |
31 | api.spotOrderInfo("btc_qc","2017121051713")
32 |
--------------------------------------------------------------------------------
/PYTHON/websocket 接口/zb_py_socket/vnzb.py:
--------------------------------------------------------------------------------
1 | # encoding: UTF-8
2 |
3 | import hashlib
4 | import zlib
5 | import json
6 | from time import sleep
7 | from threading import Thread
8 |
9 | import websocket
10 | import urllib2, hashlib,struct,sha,time
11 |
12 |
13 | zb_usd_url = "wss://api.zb.com:9999/websocket"
14 | zb_all_symbols = ["ltc_btc"]
15 |
16 | class ZB_Sub_Spot_Api(object):
17 | """基于Websocket的API对象"""
18 | def __init__(self):
19 | """Constructor"""
20 | self.apiKey = '' # apiKey
21 | self.secretKey = '' # secretKey
22 |
23 | self.ws_sub_spot = None # websocket应用对象 现货对象
24 |
25 | #----------------------------------------------------------------------
26 | def reconnect(self):
27 | """重新连接"""
28 | # 首先关闭之前的连接
29 | self.close()
30 |
31 | # 再执行重连任务
32 | self.ws_sub_spot = websocket.WebSocketApp(self.host,
33 | on_message=self.onMessage,
34 | on_error=self.onError,
35 | on_close=self.onClose,
36 | on_open=self.onOpen)
37 |
38 | self.thread = Thread(target=self.ws_sub_spot.run_forever)
39 | self.thread.start()
40 |
41 | #----------------------------------------------------------------------
42 | def connect_Subpot(self, apiKey , secretKey , trace = False):
43 | self.host = zb_usd_url
44 | self.apiKey = apiKey
45 | self.secretKey = secretKey
46 |
47 | websocket.enableTrace(trace)
48 |
49 | self.ws_sub_spot = websocket.WebSocketApp(self.host,
50 | on_message=self.onMessage,
51 | on_error=self.onError,
52 | on_close=self.onClose,
53 | on_open=self.onOpen)
54 |
55 | self.thread = Thread(target=self.ws_sub_spot.run_forever)
56 | self.thread.start()
57 |
58 | #----------------------------------------------------------------------
59 | def readData(self, evt):
60 | """解压缩推送收到的数据"""
61 | # # 创建解压器
62 | # decompress = zlib.decompressobj(-zlib.MAX_WBITS)
63 |
64 | # # 将原始数据解压成字符串
65 | # inflated = decompress.decompress(evt) + decompress.flush()
66 |
67 | # 通过json解析字符串
68 | data = json.loads(evt)
69 |
70 | return data
71 |
72 | #----------------------------------------------------------------------
73 | def close(self):
74 | """关闭接口"""
75 | if self.thread and self.thread.isAlive():
76 | self.ws_sub_spot.close()
77 | self.thread.join()
78 |
79 | #----------------------------------------------------------------------
80 | def onMessage(self, ws, evt):
81 | """信息推送"""
82 | print evt
83 |
84 | #----------------------------------------------------------------------
85 | def onError(self, ws, evt):
86 | """错误推送"""
87 | print 'onError'
88 | print evt
89 |
90 | #----------------------------------------------------------------------
91 | def onClose(self, ws):
92 | """接口断开"""
93 | print 'onClose'
94 |
95 | #----------------------------------------------------------------------
96 | def onOpen(self, ws):
97 | """接口打开"""
98 | print 'onOpen'
99 |
100 | #----------------------------------------------------------------------
101 | def subscribeSpotTicker(self, symbol_pair):
102 | # 现货的 ticker
103 | symbol_pair = symbol_pair.replace('_','')
104 | req = "{'event':'addChannel','channel':'%s_ticker'}" % symbol_pair
105 | self.ws_sub_spot.send(req)
106 |
107 | #----------------------------------------------------------------------
108 | def subscribeSpotDepth(self, symbol_pair):
109 | # 现货的 市场深度
110 | symbol_pair = symbol_pair.replace('_','')
111 | req = "{'event':'addChannel','channel':'%s_depth'}" % symbol_pair
112 | self.ws_sub_spot.send(req)
113 |
114 | #----------------------------------------------------------------------
115 | def subscribeSpotTrades(self, symbol_pair):
116 | symbol_pair = symbol_pair.replace('_','')
117 | req = "{'event':'addChannel','channel':'%s_trades'}" % symbol_pair
118 | self.ws_sub_spot.send(req)
119 |
120 | #----------------------------------------------------------------------
121 | def __fill(self, value, lenght, fillByte):
122 | if len(value) >= lenght:
123 | return value
124 | else:
125 | fillSize = lenght - len(value)
126 | return value + chr(fillByte) * fillSize
127 | #----------------------------------------------------------------------
128 | def __doXOr(self, s, value):
129 | slist = list(s)
130 | for index in xrange(len(slist)):
131 | slist[index] = chr(ord(slist[index]) ^ value)
132 | return "".join(slist)
133 | #----------------------------------------------------------------------
134 | def __hmacSign(self, aValue, aKey):
135 | keyb = struct.pack("%ds" % len(aKey), aKey)
136 | value = struct.pack("%ds" % len(aValue), aValue)
137 | k_ipad = self.__doXOr(keyb, 0x36)
138 | k_opad = self.__doXOr(keyb, 0x5c)
139 | k_ipad = self.__fill(k_ipad, 64, 54)
140 | k_opad = self.__fill(k_opad, 64, 92)
141 | m = hashlib.md5()
142 | m.update(k_ipad)
143 | m.update(value)
144 | dg = m.digest()
145 |
146 | m = hashlib.md5()
147 | m.update(k_opad)
148 | subStr = dg[0:16]
149 | m.update(subStr)
150 | dg = m.hexdigest()
151 | return dg
152 |
153 | #----------------------------------------------------------------------
154 | def __digest(self, aValue):
155 | value = struct.pack("%ds" % len(aValue), aValue)
156 | h = sha.new()
157 | h.update(value)
158 | dg = h.hexdigest()
159 | return dg
160 |
161 | #----------------------------------------------------------------------
162 | def generateSign(self, params):
163 | """生成签名"""
164 | '''
165 | {"accesskey":"0f39fb8b-d95d-4afe-b2a9-94f5f4d9fdb5","channel":"getaccountinfo","event":"addChannel"}
166 | '''
167 | l = []
168 | for key in sorted(params.keys()):
169 | l.append('"%s":"%s"' %(key, params[key]))
170 | sign = ','.join(l)
171 | sign = '{' + sign + '}'
172 |
173 | SHA_secret = self.__digest(self.secretKey)
174 | return self.__hmacSign( sign, SHA_secret)
175 | # return hashlib.md5(sign.encode('utf-8')).hexdigest().upper()
176 |
177 | #----------------------------------------------------------------------
178 | def sendTradingRequest(self, channel, params):
179 | """发送交易请求"""
180 | # 在参数字典中加上api_key和签名字段
181 | params['accesskey'] = self.apiKey
182 | params['channel'] = channel
183 | params['event'] = "addChannel"
184 |
185 | params['sign'] = self.generateSign(params)
186 |
187 | # 使用json打包并发送
188 | j = json.dumps(params)
189 |
190 | # 若触发异常则重连
191 | try:
192 | self.ws_sub_spot.send(j)
193 | except websocket.WebSocketConnectionClosedException:
194 | pass
195 |
196 | #----------------------------------------------------------------------
197 | def spotTrade(self, symbol_pair, type_, price, amount):
198 | """现货委托"""
199 | symbol_pair = symbol_pair.replace('_','')
200 | params = {}
201 | params['tradeType'] = str(type_)
202 | params['price'] = str(price)
203 | params['amount'] = str(amount)
204 |
205 | channel = symbol_pair.lower() + "_order"
206 |
207 | self.sendTradingRequest(channel, params)
208 |
209 | #----------------------------------------------------------------------
210 | def spotCancelOrder(self, symbol_pair, orderid):
211 | """现货撤单"""
212 | symbol_pair = symbol_pair.replace('_','')
213 | params = {}
214 | params['id'] = str(orderid)
215 |
216 | channel = symbol_pair.lower() + "_cancelorder"
217 |
218 | self.sendTradingRequest(channel, params)
219 |
220 | #----------------------------------------------------------------------
221 | def spotUserInfo(self):
222 | """查询现货账户"""
223 | channel = 'getaccountinfo'
224 | self.sendTradingRequest(channel, {})
225 |
226 | #----------------------------------------------------------------------
227 | def spotOrderInfo(self, symbol_pair, orderid):
228 | """查询现货委托信息"""
229 | symbol_pair = symbol_pair.replace('_','')
230 | params = {}
231 | params['id'] = str(orderid)
232 |
233 | channel = symbol_pair.lower() + "_getorder"
234 |
235 | self.sendTradingRequest(channel, params)
236 |
237 | #----------------------------------------------------------------------
238 | def spotGetOrders(self, symbol_pair , orderid):
239 | pass
240 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # api
2 | ## 加密方式 https://gitee.com/lianlianyi/zb-api/blob/master/%E5%8A%A0%E5%AF%86.md
3 |
4 | ## java 模块化demo : https://gitee.com/lianlianyi/zb-api
5 |
6 | ## 感谢GitHub用户(ipqhjjybj)提供项目zb_py_socket 的技术支持
7 |
8 | ## 感谢开发者 小鱼(QQ和微信:49744774) 提供项目 易语言中币api示例 的技术支持
9 |
10 | ## 感谢开发者 闫瑾瑾闫(QQ:729977187) 提供项目 python项目zb.com-api-master.zip
11 |
12 |
--------------------------------------------------------------------------------
/golang/zb-api-trade-master.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zb2017/api/4927d6940c9f217c91b11c042532827897f74927/golang/zb-api-trade-master.zip
--------------------------------------------------------------------------------
/zb_api_rest_java/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/zb_api_rest_java/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | zb_api_rest_demo
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.wst.common.project.facet.core.builder
15 |
16 |
17 |
18 |
19 | org.eclipse.wst.validation.validationbuilder
20 |
21 |
22 |
23 |
24 | org.eclipse.m2e.core.maven2Builder
25 |
26 |
27 |
28 |
29 |
30 | org.eclipse.jem.workbench.JavaEMFNature
31 | org.eclipse.wst.common.modulecore.ModuleCoreNature
32 | org.eclipse.jdt.core.javanature
33 | org.eclipse.m2e.core.maven2Nature
34 | org.eclipse.wst.common.project.facet.core.nature
35 | org.eclipse.wst.jsdt.core.jsNature
36 |
37 |
38 |
--------------------------------------------------------------------------------
/zb_api_rest_java/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | rest.api.exx
5 | exx_api_rest_demo
6 | 0.0.1-SNAPSHOT
7 | war
8 |
9 |
10 | UTF-8
11 |
12 |
13 |
14 | junit
15 | junit
16 | 4.8
17 | test
18 |
19 |
20 | log4j
21 | log4j
22 | 1.2.16
23 |
24 |
25 | com.alibaba
26 | fastjson
27 | 1.2.31
28 |
29 |
30 |
31 | org.apache.httpcomponents
32 | httpcore
33 | 4.4
34 |
35 |
36 | org.apache.httpcomponents
37 | httpclient
38 | 4.4
39 |
40 |
41 | commons-io
42 | commons-io
43 | 2.5
44 |
45 |
46 |
47 |
48 | exx_api_rest_demo
49 |
50 |
--------------------------------------------------------------------------------
/zb_api_rest_java/src/main/java/com/zb/kits/EncryDigestUtil.java:
--------------------------------------------------------------------------------
1 | package com.zb.kits;
2 |
3 | import java.io.UnsupportedEncodingException;
4 | import java.math.BigInteger;
5 | import java.security.InvalidKeyException;
6 | import java.security.MessageDigest;
7 | import java.security.NoSuchAlgorithmException;
8 | import java.util.Arrays;
9 |
10 | import javax.crypto.Mac;
11 | import javax.crypto.spec.SecretKeySpec;
12 |
13 | public class EncryDigestUtil {
14 |
15 | private static String encodingCharset = "UTF-8";
16 |
17 |
18 | public static String hmacSign(String aValue, String aKey) {
19 | return hmacSign(aValue, aKey , "MD5");
20 | }
21 |
22 | /**
23 | * 生成签名消息
24 | * @param aValue 要签名的字符串
25 | * @param aKey 签名密钥
26 | * @return
27 | */
28 | public static String hmacSign(String aValue, String aKey,String jiami) {
29 | byte k_ipad[] = new byte[64];
30 | byte k_opad[] = new byte[64];
31 | byte keyb[];
32 | byte value[];
33 | try {
34 | keyb = aKey.getBytes(encodingCharset);
35 | value = aValue.getBytes(encodingCharset);
36 | } catch (UnsupportedEncodingException e) {
37 | keyb = aKey.getBytes();
38 | value = aValue.getBytes();
39 | }
40 |
41 | Arrays.fill(k_ipad, keyb.length, 64, (byte) 54);
42 | Arrays.fill(k_opad, keyb.length, 64, (byte) 92);
43 | for (int i = 0; i < keyb.length; i++) {
44 | k_ipad[i] = (byte) (keyb[i] ^ 0x36);
45 | k_opad[i] = (byte) (keyb[i] ^ 0x5c);
46 | }
47 |
48 | MessageDigest md = null;
49 | try {
50 | md = MessageDigest.getInstance(jiami);//"MD5"
51 | } catch (NoSuchAlgorithmException e) {
52 |
53 | return null;
54 | }
55 | md.update(k_ipad);
56 | md.update(value);
57 | byte dg[] = md.digest();
58 | md.reset();
59 | md.update(k_opad);
60 | md.update(dg, 0, 16);
61 | dg = md.digest();
62 | return toHex(dg);
63 | }
64 |
65 | /***
66 | * 对应python里面的hmac.new(API_SECRET, msg=message, digestmod=hashlib.sha256).hexdigest().upper()
67 | * @param key
68 | * @param value
69 | * @return
70 | */
71 | public static String hamacSha256(String key , String value){
72 | String result = null;
73 | byte[] keyBytes = key.getBytes();
74 | SecretKeySpec localMac = new SecretKeySpec(keyBytes, "HmacSHA256");
75 | try {
76 | Mac mac = Mac.getInstance("HmacSHA256");
77 | mac.init(localMac);
78 | byte[] arrayOfByte = mac.doFinal(value.getBytes());
79 | BigInteger localBigInteger = new BigInteger(1,
80 | arrayOfByte);
81 | result = String.format("%0" + (arrayOfByte.length << 1) + "x",
82 | new Object[] { localBigInteger });
83 |
84 | } catch (InvalidKeyException e) {
85 | e.printStackTrace();
86 | } catch (NoSuchAlgorithmException e) {
87 | e.printStackTrace();
88 | } catch (IllegalStateException e) {
89 | e.printStackTrace();
90 | }
91 |
92 | return result;
93 | }
94 |
95 | public static String toHex(byte input[]) {
96 | if (input == null)
97 | return null;
98 | StringBuffer output = new StringBuffer(input.length * 2);
99 | for (int i = 0; i < input.length; i++) {
100 | int current = input[i] & 0xff;
101 | if (current < 16)
102 | output.append("0");
103 | output.append(Integer.toString(current, 16));
104 | }
105 |
106 | return output.toString();
107 | }
108 |
109 | /**
110 | *
111 | * @param args
112 | * @param key
113 | * @return
114 | */
115 | public static String getHmac(String[] args, String key) {
116 | if (args == null || args.length == 0) {
117 | return (null);
118 | }
119 | StringBuffer str = new StringBuffer();
120 | for (int i = 0; i < args.length; i++) {
121 | str.append(args[i]);
122 | }
123 | return (hmacSign(str.toString(), key));
124 | }
125 |
126 | /**
127 | * SHA加密
128 | * @param aValue
129 | * @return
130 | */
131 | public static String digest(String aValue , String algorithm) {
132 | aValue = aValue.trim();
133 | byte value[];
134 | try {
135 | value = aValue.getBytes(encodingCharset);
136 | } catch (UnsupportedEncodingException e) {
137 | value = aValue.getBytes();
138 | }
139 | MessageDigest md = null;
140 | try {
141 | md = MessageDigest.getInstance("SHA");
142 | } catch (NoSuchAlgorithmException e) {
143 | e.printStackTrace();
144 | return null;
145 | }
146 | return toHex(md.digest(value));
147 |
148 | }
149 |
150 | /***
151 | * sha-1散列加密
152 | * @param aValue
153 | * @return
154 | */
155 | public static String digest(String aValue) {
156 | return digest(aValue, "SHA");
157 | }
158 | /***
159 | * sha-256散列加密
160 | * @param aValue
161 | * @return
162 | */
163 | public static String digestSha256(String aValue) {
164 | return digest(aValue, "SHA-256");
165 | }
166 |
167 | public static void main(String[] args) {
168 | // System.out.println(digest("mima123465"));
169 | System.out.println(hmacSign("method=getAccountInfo&accesskey=826afc09-58e5-4ebc-b31c-64956082c705", digest("ab391be1-c1a1-4252-83fc-8b358bd72252")));
170 | }
171 | }
172 |
--------------------------------------------------------------------------------
/zb_api_rest_java/src/main/java/com/zb/kits/HttpUtilManager.java:
--------------------------------------------------------------------------------
1 | package com.zb.kits;
2 |
3 | import java.io.IOException;
4 | import java.io.InputStream;
5 | import java.security.KeyManagementException;
6 | import java.security.NoSuchAlgorithmException;
7 | import java.util.ArrayList;
8 | import java.util.LinkedList;
9 | import java.util.List;
10 | import java.util.Map;
11 | import java.util.Map.Entry;
12 | import java.util.concurrent.TimeUnit;
13 |
14 | import javax.net.ssl.SSLContext;
15 | import javax.net.ssl.TrustManager;
16 | import javax.net.ssl.X509TrustManager;
17 |
18 | import org.apache.commons.io.IOUtils;
19 | import org.apache.http.Consts;
20 | import org.apache.http.HttpEntity;
21 | import org.apache.http.HttpException;
22 | import org.apache.http.HttpResponse;
23 | import org.apache.http.NameValuePair;
24 | import org.apache.http.client.ClientProtocolException;
25 | import org.apache.http.client.HttpClient;
26 | import org.apache.http.client.config.RequestConfig;
27 | import org.apache.http.client.entity.UrlEncodedFormEntity;
28 | import org.apache.http.client.methods.CloseableHttpResponse;
29 | import org.apache.http.client.methods.HttpGet;
30 | import org.apache.http.client.methods.HttpPost;
31 | import org.apache.http.client.methods.HttpRequestBase;
32 | import org.apache.http.config.Registry;
33 | import org.apache.http.config.RegistryBuilder;
34 | import org.apache.http.conn.ConnectionKeepAliveStrategy;
35 | import org.apache.http.conn.socket.ConnectionSocketFactory;
36 | import org.apache.http.conn.socket.PlainConnectionSocketFactory;
37 | import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
38 | import org.apache.http.impl.client.CloseableHttpClient;
39 | import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
40 | import org.apache.http.impl.client.HttpClients;
41 | import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
42 | import org.apache.http.message.BasicNameValuePair;
43 | import org.apache.http.protocol.HttpContext;
44 | import org.apache.http.util.EntityUtils;
45 |
46 | /**
47 | * 封装HTTP get post请求,简化发送http请求
48 | *
49 | * @author zhangchi
50 | *
51 | */
52 | public class HttpUtilManager {
53 |
54 | private static HttpUtilManager instance = new HttpUtilManager();
55 | private static HttpClient client;
56 | private static long startTime = System.currentTimeMillis();
57 | public static PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
58 | private static ConnectionKeepAliveStrategy keepAliveStrat = new DefaultConnectionKeepAliveStrategy() {
59 | public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
60 | long keepAlive = super.getKeepAliveDuration(response, context);
61 |
62 | if (keepAlive == -1) {
63 | keepAlive = 5000;
64 | }
65 | return keepAlive;
66 | }
67 |
68 | };
69 |
70 | private HttpUtilManager() {
71 | client = HttpClients.custom().setConnectionManager(cm).setKeepAliveStrategy(keepAliveStrat).build();
72 | }
73 |
74 | public static void IdleConnectionMonitor() {
75 |
76 | if (System.currentTimeMillis() - startTime > 30000) {
77 | startTime = System.currentTimeMillis();
78 | cm.closeExpiredConnections();
79 | cm.closeIdleConnections(30, TimeUnit.SECONDS);
80 | }
81 | }
82 |
83 | private static RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(20000).setConnectTimeout(20000)
84 | .setConnectionRequestTimeout(20000).build();
85 |
86 | public static HttpUtilManager getInstance() {
87 | return instance;
88 | }
89 |
90 | public HttpClient getHttpClient() {
91 | return client;
92 | }
93 |
94 | private HttpPost httpPostMethod(String url) {
95 | return new HttpPost(url);
96 | }
97 |
98 | private HttpRequestBase httpGetMethod(String url) {
99 | return new HttpGet(url);
100 | }
101 |
102 | public HttpResponse getResponse(String url) throws ClientProtocolException, IOException {
103 | IdleConnectionMonitor();
104 | HttpRequestBase method = this.httpGetMethod(url);
105 |
106 | method.setConfig(requestConfig);
107 | HttpResponse response = client.execute(method);
108 | return response;
109 | }
110 |
111 | public String requestHttpGet(String url, Map params) throws HttpException, IOException {
112 | List keys = new ArrayList(params.keySet());
113 | String pas = "";
114 | if (!keys.isEmpty()) {
115 | int keySize = keys.size();
116 | for (int i = 0; i < keySize; i++) {
117 | String key = keys.get(i);
118 | String value = params.get(key);
119 | pas += key + "=" + value + "&";
120 | }
121 | pas = pas.substring(0, pas.length() - 1);
122 | }
123 | return this.requestHttpGet(url, "", pas);
124 | }
125 |
126 | /**
127 | * 绕过验证
128 | *
129 | * @return
130 | * @throws NoSuchAlgorithmException
131 | * @throws KeyManagementException
132 | */
133 | public static SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException {
134 | SSLContext sc = SSLContext.getInstance("SSLv3");
135 |
136 | // 实现一个X509TrustManager接口,用于绕过验证,不用修改里面的方法
137 | X509TrustManager trustManager = new X509TrustManager() {
138 |
139 | public void checkClientTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
140 | String paramString) {
141 | }
142 |
143 | public void checkServerTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
144 | String paramString) {
145 | }
146 |
147 | public java.security.cert.X509Certificate[] getAcceptedIssuers() {
148 | return null;
149 | }
150 | };
151 |
152 | sc.init(null, new TrustManager[] { trustManager }, null);
153 | return sc;
154 | }
155 |
156 | /**
157 | * 模拟请求
158 | *
159 | * @param url
160 | * 资源地址
161 | * @param map
162 | * 参数列表
163 | * @param encoding
164 | * 编码
165 | * @return
166 | * @throws NoSuchAlgorithmException
167 | * @throws KeyManagementException
168 | * @throws IOException
169 | * @throws ClientProtocolException
170 | */
171 | public static String sendHttps(String url, Map map, String encoding) {
172 | String body = "";
173 | // 采用绕过验证的方式处理https请求
174 | SSLContext sslcontext;
175 | try {
176 | sslcontext = createIgnoreVerifySSL();
177 | // 设置协议http和https对应的处理socket链接工厂的对象
178 | Registry socketFactoryRegistry = RegistryBuilder.create()
179 | .register("http", PlainConnectionSocketFactory.INSTANCE)
180 | .register("https", new SSLConnectionSocketFactory(sslcontext)).build();
181 | PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(
182 | socketFactoryRegistry);
183 | HttpClients.custom().setConnectionManager(connManager);
184 |
185 | // 创建自定义的httpclient对象
186 | CloseableHttpClient client = HttpClients.custom().setConnectionManager(connManager).build();
187 | // CloseableHttpClient client = HttpClients.createDefault();
188 |
189 | // 创建post方式请求对象
190 | HttpPost httpPost = new HttpPost(url);
191 |
192 | // 装填参数
193 | List nvps = new ArrayList();
194 | if (map != null) {
195 | for (Entry entry : map.entrySet()) {
196 | nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
197 | }
198 | }
199 | // 设置参数到请求对象中
200 | httpPost.setEntity(new UrlEncodedFormEntity(nvps, encoding));
201 |
202 | System.out.println("请求地址:" + url);
203 | System.out.println("请求参数:" + nvps.toString());
204 |
205 | // 设置header信息
206 | // 指定报文头【Content-type】、【User-Agent】
207 | httpPost.setHeader("Content-type", "application/x-www-form-urlencoded");
208 | httpPost.setHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
209 |
210 | // 执行请求操作,并拿到结果(同步阻塞)
211 | CloseableHttpResponse response = client.execute(httpPost);
212 | // 获取结果实体
213 | HttpEntity entity = response.getEntity();
214 | if (entity != null) {
215 | // 按指定编码转换结果实体为String类型
216 | body = EntityUtils.toString(entity, encoding);
217 | }
218 | EntityUtils.consume(entity);
219 | // 释放链接
220 | response.close();
221 | } catch (KeyManagementException | NoSuchAlgorithmException e) {
222 | // TODO Auto-generated catch block
223 | e.printStackTrace();
224 | } catch (IOException e) {
225 | // TODO Auto-generated catch block
226 | e.printStackTrace();
227 | }
228 |
229 | return body;
230 | }
231 |
232 | public String requestHttpGet(String url_prex, String url, String param) throws HttpException, IOException {
233 |
234 | IdleConnectionMonitor();
235 | url = url_prex + url;
236 | if (param != null && !param.equals("")) {
237 | if (url.endsWith("?")) {
238 | url = url + param;
239 | } else {
240 | url = url + "?" + param;
241 | }
242 | }
243 | HttpRequestBase method = this.httpGetMethod(url);
244 | method.setConfig(requestConfig);
245 | HttpResponse response = client.execute(method);
246 |
247 | HttpEntity entity = response.getEntity();
248 | if (entity == null) {
249 | return "";
250 | }
251 | InputStream is = null;
252 | String responseData = "";
253 | try {
254 | is = entity.getContent();
255 | responseData = IOUtils.toString(is, "UTF-8");
256 | } finally {
257 | if (is != null) {
258 | is.close();
259 | }
260 | }
261 | // System.out.println(responseData);
262 | return responseData;
263 | }
264 |
265 | public String requestHttpPost(String url_prex, String url, Map params)
266 | throws HttpException, IOException {
267 | IdleConnectionMonitor();
268 | url = url_prex + url;
269 | HttpPost method = this.httpPostMethod(url);
270 | List valuePairs = this.convertMap2PostParams(params);
271 | UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(valuePairs, Consts.UTF_8);
272 | method.setEntity(urlEncodedFormEntity);
273 | method.setConfig(requestConfig);
274 | HttpResponse response = client.execute(method);
275 | // System.out.println(method.getURI());
276 | HttpEntity entity = response.getEntity();
277 |
278 | if (entity == null) {
279 | return "";
280 | }
281 | InputStream is = null;
282 | String responseData = "";
283 | try {
284 | is = entity.getContent();
285 | responseData = IOUtils.toString(is, "UTF-8");
286 | } finally {
287 | if (is != null) {
288 | is.close();
289 | }
290 | }
291 | return responseData;
292 |
293 | }
294 |
295 | private List convertMap2PostParams(Map params) {
296 | List keys = new ArrayList(params.keySet());
297 | if (keys.isEmpty()) {
298 | return null;
299 | }
300 | int keySize = keys.size();
301 | List data = new LinkedList();
302 | for (int i = 0; i < keySize; i++) {
303 | String key = keys.get(i);
304 | String value = params.get(key);
305 | data.add(new BasicNameValuePair(key, value));
306 | }
307 | return data;
308 | }
309 |
310 | }
311 |
--------------------------------------------------------------------------------
/zb_api_rest_java/src/main/java/com/zb/kits/JsonFormatTool.java:
--------------------------------------------------------------------------------
1 | package com.zb.kits;
2 |
3 | import java.util.ArrayList;
4 |
5 | public class JsonFormatTool {
6 | /**
7 | * json字符串的格式化
8 | * @author peiyuxin
9 | * @param json 需要格式的json串
10 | * @param fillStringUnit每一层之前的占位符号比如空格 制表符
11 | * @return
12 | */
13 | public static String formatJson(String json, String fillStringUnit) {
14 | if (json == null || json.trim().length() == 0) {
15 | return null;
16 | }
17 |
18 | int fixedLenth = 0;
19 | ArrayList tokenList = new ArrayList();
20 | {
21 | String jsonTemp = json;
22 | //预读取
23 | while (jsonTemp.length() > 0) {
24 | String token = getToken(jsonTemp);
25 | jsonTemp = jsonTemp.substring(token.length());
26 | token = token.trim();
27 | tokenList.add(token);
28 | }
29 | }
30 |
31 | for (int i = 0; i < tokenList.size(); i++) {
32 | String token = tokenList.get(i);
33 | int length = token.getBytes().length;
34 | if (length > fixedLenth && i < tokenList.size() - 1 && tokenList.get(i + 1).equals(":")) {
35 | fixedLenth = length;
36 | }
37 | }
38 |
39 | StringBuilder buf = new StringBuilder();
40 | int count = 0;
41 | for (int i = 0; i < tokenList.size(); i++) {
42 |
43 | String token = tokenList.get(i);
44 |
45 | if (token.equals(",")) {
46 | buf.append(token);
47 | doFill(buf, count, fillStringUnit);
48 | continue;
49 | }
50 | if (token.equals(":")) {
51 | buf.append(" ").append(token).append(" ");
52 | continue;
53 | }
54 | if (token.equals("{")) {
55 | String nextToken = tokenList.get(i + 1);
56 | if (nextToken.equals("}")) {
57 | i++;
58 | buf.append("{ }");
59 | } else {
60 | count++;
61 | buf.append(token);
62 | doFill(buf, count, fillStringUnit);
63 | }
64 | continue;
65 | }
66 | if (token.equals("}")) {
67 | count--;
68 | doFill(buf, count, fillStringUnit);
69 | buf.append(token);
70 | continue;
71 | }
72 | if (token.equals("[")) {
73 | String nextToken = tokenList.get(i + 1);
74 | if (nextToken.equals("]")) {
75 | i++;
76 | buf.append("[ ]");
77 | } else {
78 | count++;
79 | buf.append(token);
80 | doFill(buf, count, fillStringUnit);
81 | }
82 | continue;
83 | }
84 | if (token.equals("]")) {
85 | count--;
86 | doFill(buf, count, fillStringUnit);
87 | buf.append(token);
88 | continue;
89 | }
90 |
91 | buf.append(token);
92 | //左对齐
93 | if (i < tokenList.size() - 1 && tokenList.get(i + 1).equals(":")) {
94 | int fillLength = fixedLenth - token.getBytes().length;
95 | if (fillLength > 0) {
96 | for(int j = 0; j < fillLength; j++) {
97 | buf.append(" ");
98 | }
99 | }
100 | }
101 | }
102 | return buf.toString();
103 | }
104 |
105 | private static String getToken(String json) {
106 | StringBuilder buf = new StringBuilder();
107 | boolean isInYinHao = false;
108 | while (json.length() > 0) {
109 | String token = json.substring(0, 1);
110 | json = json.substring(1);
111 |
112 | if (!isInYinHao &&
113 | (token.equals(":") || token.equals("{") || token.equals("}")
114 | || token.equals("[") || token.equals("]")
115 | || token.equals(","))) {
116 | if (buf.toString().trim().length() == 0) {
117 | buf.append(token);
118 | }
119 |
120 | break;
121 | }
122 |
123 | if (token.equals("\\")) {
124 | buf.append(token);
125 | buf.append(json.substring(0, 1));
126 | json = json.substring(1);
127 | continue;
128 | }
129 | if (token.equals("\"")) {
130 | buf.append(token);
131 | if (isInYinHao) {
132 | break;
133 | } else {
134 | isInYinHao = true;
135 | continue;
136 | }
137 | }
138 | buf.append(token);
139 | }
140 | return buf.toString();
141 | }
142 |
143 | private static void doFill(StringBuilder buf, int count, String fillStringUnit) {
144 | buf.append("\n");
145 | for (int i = 0; i < count; i++) {
146 | buf.append(fillStringUnit);
147 | }
148 | }
149 |
150 | }
--------------------------------------------------------------------------------
/zb_api_rest_java/src/main/java/com/zb/kits/MapSort.java:
--------------------------------------------------------------------------------
1 | package com.zb.kits;
2 |
3 | import java.util.Comparator;
4 | import java.util.HashMap;
5 | import java.util.Iterator;
6 | import java.util.Map;
7 | import java.util.Map.Entry;
8 | import java.util.TreeMap;
9 |
10 | public class MapSort {
11 |
12 | public static void main(String[] args) {
13 |
14 | Map map = new HashMap();
15 |
16 | map.put("Kb", "K");
17 | map.put("Wc", "W");
18 | map.put("Ab", "A");
19 | map.put("ad", "a");
20 | map.put("Fe", "N");
21 | map.put("Bf", "B");
22 | map.put("Cg", "C");
23 | map.put("Zh", "Z");
24 |
25 | Map resultMap = sortMapByKey(map); // 按Key进行排序,根据首字母hashcode
26 |
27 | for (Map.Entry entry : resultMap.entrySet()) {
28 | System.out.println(entry.getKey() + " " + entry.getValue());
29 | }
30 |
31 | }
32 |
33 | /**
34 | * 使用 Map按key首字母hashcode进行排序
35 | *
36 | * @param map
37 | * @return
38 | */
39 | public static Map sortMapByKey(Map map) {
40 | if (map == null || map.isEmpty()) {
41 | return null;
42 | }
43 |
44 | Map sortMap = new TreeMap(new MapKeyComparator());
45 |
46 | sortMap.putAll(map);
47 |
48 | return sortMap;
49 | }
50 |
51 | public static String toStringMap(Map m) {
52 | // 按map键首字母顺序进行排序
53 | m = MapSort.sortMapByKey(m);
54 |
55 | StringBuilder sbl = new StringBuilder();
56 | for (Iterator i = m.entrySet().iterator(); i.hasNext();) {
57 | Entry e = i.next();
58 | Object o = e.getValue();
59 | String v = "";
60 | if (o == null) {
61 | v = "";
62 | } else if (o instanceof String[]) {
63 | String[] s = (String[]) o;
64 | if (s.length > 0) {
65 | v = s[0];
66 | }
67 | } else {
68 | v = o.toString();
69 | }
70 | if (!e.getKey().equals("sign") && !e.getKey().equals("reqTime") && !e.getKey().equals("tx")) {
71 | // try {
72 | // sbl.append("&").append(e.getKey()).append("=").append(URLEncoder.encode(v,
73 | // "utf-8"));
74 | // } catch (UnsupportedEncodingException e1) {
75 | // e1.printStackTrace();
76 | sbl.append("&").append(e.getKey()).append("=").append(v);
77 | // }
78 | }
79 | }
80 | String s = sbl.toString();
81 | if (s.length() > 0) {
82 | return s.substring(1);
83 | }
84 | return "";
85 | }
86 | }
87 |
88 | class MapKeyComparator implements Comparator {
89 |
90 | public int compare(String str1, String str2) {
91 |
92 | return str1.compareTo(str2);
93 | }
94 | }
--------------------------------------------------------------------------------
/zb_api_rest_java/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 | Archetype Created Web Application
8 |
9 |
--------------------------------------------------------------------------------
/zb_api_rest_java/src/test/java/com/zb/api/RestTest.java:
--------------------------------------------------------------------------------
1 | package com.zb.api;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.IOException;
5 | import java.io.InputStream;
6 | import java.io.InputStreamReader;
7 | import java.net.HttpURLConnection;
8 | import java.net.URL;
9 | import java.util.HashMap;
10 | import java.util.Map;
11 |
12 | import org.apache.http.HttpException;
13 | import org.apache.log4j.Logger;
14 | import org.junit.Test;
15 |
16 | import com.alibaba.fastjson.JSONObject;
17 | import com.zb.kits.EncryDigestUtil;
18 | import com.zb.kits.HttpUtilManager;
19 | import com.zb.kits.MapSort;
20 |
21 | public class RestTest {
22 |
23 | private static Logger log = Logger.getLogger(RestTest.class);
24 |
25 | // 正式
26 | public final String ACCESS_KEY = "";
27 | public final String SECRET_KEY = "";
28 | public final String URL_PREFIX = "https://trade.zb.com/api/";
29 | public static String API_DOMAIN = "http://api.zb.com";
30 |
31 |
32 | public final String PAY_PASS = "xxxx";
33 |
34 | /**
35 | * 委托下单 tradeType 1买,0卖
36 | */
37 | @Test
38 | public void testOrder() {
39 | try {
40 | // 需加密的请求参数, tradeType=0卖单
41 | Map params = new HashMap();
42 | params.put("method", "order");
43 | params.put("price", "1.9001");
44 | params.put("amount", "1.502");
45 | params.put("tradeType", "1");
46 | params.put("currency", "qtum_usdt");
47 |
48 | // 请求测试
49 | String json = this.getJsonPost(params);
50 | System.out.println("testOrder 结果: " + json);
51 | } catch (Exception ex) {
52 | ex.printStackTrace();
53 | }
54 | }
55 |
56 | /**
57 | * 取消下单
58 | */
59 | // @Test
60 | public void testCancelOrder() {
61 | String orderId = "201710111625";// 201710111608
62 | try {
63 | Map params = new HashMap();
64 | params.put("method", "cancelOrder");
65 | params.put("id", orderId);
66 | params.put("currency", "ltc_btc");
67 |
68 | String json = this.getJsonPost(params);
69 | System.out.println("testGetOrder 结果: " + json);
70 | } catch (Exception ex) {
71 | ex.printStackTrace();
72 | }
73 | }
74 |
75 | /**
76 | * 获取订单信息
77 | */
78 | // @Test
79 | public void testGetOrder() {
80 | String orderId = "201710122805";
81 | try {
82 | Map params = new HashMap();
83 | params.put("method", "getOrder");
84 | params.put("id", orderId);
85 | params.put("currency", "ltc_btc");
86 | String json = this.getJsonPost(params);
87 |
88 | System.out.println("testGetOrder 结果: " + json);
89 | } catch (Exception ex) {
90 | ex.printStackTrace();
91 | }
92 | }
93 |
94 | /**
95 | * 获取多个委托买单或卖单,每次请求返回10条记录
96 | */
97 | // @Test
98 | public void testGetOrders() {
99 | try {
100 | String[] currencyArr = new String[] { "ltc_btc", "eth_btc", "etc_btc" };
101 | for (String currency : currencyArr) {
102 | Map params = new HashMap();
103 | params.put("method", "getOrders");
104 | params.put("tradeType", "1");
105 | params.put("currency", currency);
106 | params.put("pageIndex", "1");
107 |
108 | String json = this.getJsonPost(params);
109 | log.info("testGetOrders 结果: " + json);
110 | }
111 | } catch (Exception ex) {
112 | ex.printStackTrace();
113 | }
114 | }
115 |
116 | /**
117 | * (新)获取多个委托买单或卖单,每次请求返回pageSize<=100条记录
118 | */
119 | // @Test
120 | public void testGetOrdersNew() {
121 | try {
122 | String[] currencyArr = new String[] { "ltc_btc", "eth_btc", "etc_btc" };
123 | for (String currency : currencyArr) {
124 | Map params = new HashMap();
125 | params.put("method", "getOrdersNew");
126 | params.put("tradeType", "1");
127 | params.put("currency", currency);
128 | params.put("pageIndex", "1");
129 | params.put("pageSize", "1");
130 | String json = this.getJsonPost(params);
131 | log.info("testGetOrdersNew 结果: " + json);
132 | }
133 | } catch (Exception ex) {
134 | ex.printStackTrace();
135 | }
136 |
137 | }
138 |
139 | /**
140 | * 与getOrdersNew的区别是取消tradeType字段过滤,可同时获取买单和卖单,每次请求返回pageSize<=100条记录
141 | */
142 | // @Test
143 | public void getOrdersIgnoreTradeType() {
144 | try {
145 | String[] currencyArr = new String[] { "ltc_btc", "eth_btc", "etc_btc" };
146 | for (String currency : currencyArr) {
147 | Map params = new HashMap();
148 | params.put("method", "getOrdersIgnoreTradeType");
149 | params.put("currency", currency);
150 | params.put("pageIndex", "1");
151 | params.put("pageSize", "1");
152 |
153 | String json = this.getJsonPost(params);
154 | log.info("getOrdersIgnoreTradeType 结果: " + json);
155 | }
156 | } catch (Exception ex) {
157 | ex.printStackTrace();
158 | }
159 |
160 | }
161 |
162 | /**
163 | * 获取未成交或部份成交的买单和卖单,每次请求返回pageSize<=100条记录
164 | */
165 | // @Test
166 | public void getUnfinishedOrdersIgnoreTradeType() {
167 | try {
168 | String[] currencyArr = new String[] { "ltc_btc", "eth_btc", "etc_btc" };
169 | for (String currency : currencyArr) {
170 | Map params = new HashMap();
171 | params.put("method", "getUnfinishedOrdersIgnoreTradeType");
172 | params.put("currency", currency);
173 | params.put("pageIndex", "1");
174 | params.put("pageSize", "10");
175 |
176 | String json = this.getJsonPost(params);
177 | log.info("getUnfinishedOrdersIgnoreTradeType 结果: " + json);
178 | }
179 | } catch (Exception ex) {
180 | ex.printStackTrace();
181 | }
182 | }
183 |
184 | /**
185 | * 获取个人信息
186 | */
187 | @Test
188 | public void testGetAccountInfo() {
189 | try {
190 | // 需加密的请求参数
191 | Map params = new HashMap();
192 | params.put("method", "getAccountInfo");
193 | String json = this.getJsonPost(params);
194 | log.info("testGetAccountInfo 结果: " + json);
195 | } catch (Exception ex) {
196 | ex.printStackTrace();
197 | }
198 | }
199 |
200 | /**
201 | * 获取个人的充值地址
202 | */
203 | // @Test
204 | public void testGetUserAddress() {
205 | try {
206 | // 需加密的请求参数
207 | Map params = new HashMap();
208 | params.put("method", "getUserAddress");
209 | params.put("currency", "btc");
210 | String json = this.getJsonPost(params);
211 | System.out.println("getUserAddress 结果: " + json);
212 | } catch (Exception ex) {
213 | ex.printStackTrace();
214 | }
215 | }
216 |
217 | /**
218 | * 获取认证的提现地址
219 | */
220 | // @Test
221 | public void testGetWithdrawAddress() {
222 | try {
223 | Map params = new HashMap();
224 | params.put("method", "getWithdrawAddress");
225 | params.put("currency", "etc");
226 |
227 | String json = this.getJsonPost(params);
228 | System.out.println("getWithdrawAddress 结果: " + json);
229 | } catch (Exception ex) {
230 | ex.printStackTrace();
231 | }
232 | }
233 |
234 | /**
235 | * 获取提现记录
236 | */
237 | // @Test
238 | public void testGetWithdrawRecord() {
239 | try {
240 | Map params = new HashMap();
241 | params.put("method", "getWithdrawRecord");
242 | params.put("currency", "eth");
243 | params.put("pageIndex", "1");
244 | params.put("pageSize", "10");
245 | String json = this.getJsonPost(params);
246 | System.out.println("getWithdrawRecord 结果: " + json);
247 | } catch (Exception ex) {
248 | ex.printStackTrace();
249 | }
250 | }
251 |
252 | /**
253 | * 获取虚拟货币充值记录
254 | */
255 | // @Test
256 | public void testGetChargeRecord() {
257 | try {
258 | Map params = new HashMap();
259 | params.put("method", "getChargeRecord");
260 | params.put("currency", "btc");
261 | params.put("pageIndex", "1");
262 | params.put("pageSize", "10");
263 | String json = this.getJsonPost(params);
264 |
265 | System.out.println("getChargeRecord 结果: " + json);
266 |
267 | } catch (Exception ex) {
268 | ex.printStackTrace();
269 | }
270 | }
271 |
272 | /**
273 | * 提现操作
274 | */
275 | // @Test
276 | public void withdraw() {
277 | try {
278 | String addr = "143GwqgnjNi5DqGv4xzwqeGTi7BGxxxxxx";
279 | String fees = "0.0003";
280 | String currency = "etc";
281 | String amount = "0.0004";
282 | String itransfer = "0";
283 |
284 | Map params = new HashMap();
285 | params.put("amount", amount);
286 | params.put("currency", currency);
287 | params.put("fees", fees);
288 | params.put("itransfer", itransfer);
289 | params.put("method", "withdraw");
290 | params.put("receiveAddr", addr);
291 | params.put("safePwd", PAY_PASS);
292 |
293 | String json= this.getJsonPost(params);
294 | System.out.println("withdraw 结果: " + json);
295 | } catch (Exception ex) {
296 | ex.printStackTrace();
297 | }
298 | }
299 |
300 |
301 |
302 |
303 | /**
304 | * 测试获取行情
305 | */
306 | // @Test
307 | public void testTicker() {
308 | try {
309 | String currency = "ltc_btc";
310 | // 请求地址
311 | String url = API_DOMAIN + "/data/v1/ticker?market=" + currency;
312 | log.info(currency + "-testTicker url: " + url);
313 | // 请求测试
314 | String callback = get(url, "UTF-8");
315 | log.info(currency + "-testTicker 结果: " + callback);
316 | } catch (Exception ex) {
317 | ex.printStackTrace();
318 | }
319 | }
320 |
321 | /**
322 | * 测试获取深度
323 | */
324 | // @Test
325 | public void testDepth() {
326 | try {
327 | String currency = "ltc_btc";
328 | String merge = "0.1";
329 | // 请求地址
330 | String url = API_DOMAIN + "/data/v1/depth?market=" + currency;
331 | // String url = API_DOMAIN+"/data/v1/depth?currency=" + currency +
332 | // "&size=3&merge=" + merge;
333 | // String url = API_DOMAIN+"/data/v1/depth?currency=" + currency +
334 | // "&size=3";
335 | log.info(currency + "-testDepth url: " + url);
336 | // 请求测试
337 | String callback = get(url, "UTF-8");
338 | log.info(currency + "-testDepth 结果: " + callback);
339 | } catch (Exception ex) {
340 | ex.printStackTrace();
341 | }
342 | }
343 |
344 | /**
345 | * 测试获取最近交易记录
346 | */
347 | // @Test
348 | public void testTrades() {
349 | try {
350 | String currency = "etc_btc";
351 | // 请求地址
352 | String url = API_DOMAIN + "/data/v1/trades?market=" + currency;
353 | log.info(currency + "-testTrades url: " + url);
354 | // 请求测试
355 | String callback = get(url, "UTF-8");
356 | log.info(currency + "-testTrades 结果: " + callback);
357 | } catch (Exception ex) {
358 | ex.printStackTrace();
359 | }
360 | }
361 |
362 | /**
363 | * 测试获取K线数据
364 | */
365 | // @Test
366 | public void testKline() {
367 | try {
368 | String currency = "etc_btc";
369 | // 请求地址
370 | String url = API_DOMAIN + "/data/v1/kline?market=" + currency + "×=1min";
371 | log.info(currency + "-testKline url: " + url);
372 | // 请求测试
373 | String callback = get(url, "UTF-8");
374 | JSONObject json = JSONObject.parseObject(callback);
375 | log.info(currency + "-testKline 结果: " + json.toJSONString());
376 | } catch (Exception ex) {
377 | ex.printStackTrace();
378 | }
379 | }
380 |
381 | /**
382 | * 获取json内容(统一加密)
383 | *
384 | * @param params
385 | * @return
386 | */
387 | private String getJsonPost(Map params) {
388 | params.put("accesskey", ACCESS_KEY);// 这个需要加入签名,放前面
389 | String digest = EncryDigestUtil.digest(SECRET_KEY);
390 |
391 | String sign = EncryDigestUtil.hmacSign(MapSort.toStringMap(params), digest); // 参数执行加密
392 | String method = params.get("method");
393 |
394 | // 加入验证
395 | params.put("sign", sign);
396 | params.put("reqTime", System.currentTimeMillis() + "");
397 | String url = "请求地址:" + URL_PREFIX + method + " 参数:" + params;
398 | System.out.println(url);
399 | String json = "";
400 | try {
401 | json = HttpUtilManager.getInstance().requestHttpPost(URL_PREFIX, method, params);
402 | } catch (HttpException | IOException e) {
403 | log.error("获取交易json异常", e);
404 | }
405 | return json;
406 | }
407 |
408 | /**
409 | *
410 | * @param urlAll
411 | * :请求接口
412 | * @param charset
413 | * :字符编码
414 | * @return 返回json结果
415 | */
416 | public String get(String urlAll, String charset) {
417 | BufferedReader reader = null;
418 | String result = null;
419 | StringBuffer sbf = new StringBuffer();
420 | String userAgent = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.66 Safari/537.36";// 模拟浏览器
421 | try {
422 | URL url = new URL(urlAll);
423 | HttpURLConnection connection = (HttpURLConnection) url.openConnection();
424 | connection.setRequestMethod("GET");
425 | connection.setReadTimeout(30000);
426 | connection.setConnectTimeout(30000);
427 | connection.setRequestProperty("User-agent", userAgent);
428 | connection.connect();
429 | InputStream is = connection.getInputStream();
430 | reader = new BufferedReader(new InputStreamReader(is, charset));
431 | String strRead = null;
432 | while ((strRead = reader.readLine()) != null) {
433 | sbf.append(strRead);
434 | sbf.append("\r\n");
435 | }
436 | reader.close();
437 | result = sbf.toString();
438 |
439 | } catch (Exception e) {
440 | e.printStackTrace();
441 | }
442 | return result;
443 | }
444 | }
445 |
--------------------------------------------------------------------------------
/zb_api_rest_java/src/test/resources/log4j.properties:
--------------------------------------------------------------------------------
1 | ##?????
2 | ## %r ?? 0
3 | ## %t ??? main
4 | ## %p ??? DEBUG/INFO/ERROR
5 | ## %c ??????(????)
6 | ## %l ?????????????
7 | ## %m ????????????log(message)??message
8 | ## %n ??????
9 |
10 |
11 |
12 | #log4j????logger
13 | #FATAL 0
14 | #ERROR 3
15 | #WARN 4
16 | #INFO 6
17 | #DEBUG 7
18 | ### set log levels ###
19 | log4j.rootLogger = INFO,stdout,file,error
20 | ###????
21 | log4j.appender.logfile.encoding=UTF-8
22 | ### ?????? ###
23 | log4j.appender.stdout = org.apache.log4j.ConsoleAppender
24 | log4j.appender.stdout.Target = System.out
25 | log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
26 | log4j.appender.stdout.layout.ConversionPattern =[%5p]\:%d{MM-dd HH\:mm\:ss} %l- %m%n
27 |
28 | ### ??????? ###
29 | log4j.appender.file = org.apache.log4j.DailyRollingFileAppender
30 | log4j.appender.file.File = logs/chbtc_rest_demo_log
31 | log4j.appender.file.DatePattern = '_'yyyy-MM-dd'.log'
32 | log4j.appender.file.Append = true
33 | ## ??DEBUG???????
34 | log4j.appender.file.Threshold = INFO
35 | log4j.appender.file.layout = org.apache.log4j.PatternLayout
36 | log4j.appender.file.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
37 |
38 | ### ??????????? ###
39 | log4j.appender.error = org.apache.log4j.DailyRollingFileAppender
40 | ## ???????
41 | log4j.appender.error.File = logs/chbtc_rest_demo_error
42 | log4j.appender.error.DatePattern = '_'yyyy-MM-dd'.log'
43 | log4j.appender.error.Append = true
44 | ## ???ERROR???????!!!
45 | log4j.appender.error.Threshold = ERROR
46 | log4j.appender.error.layout = org.apache.log4j.PatternLayout
47 | log4j.appender.error.layout.ConversionPattern =%d{yyyy-MM-dd HH\:mm\:ss} [ %t\:%r ] - [ %p ] %m%n
--------------------------------------------------------------------------------
/zb_netty_client_java/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 | com.world
4 | netty_client_demo
5 | 0.0.1-SNAPSHOT
6 | netty_client_demo
7 | http://maven.apache.org
8 |
9 |
10 | junit
11 | junit
12 | 3.8.1
13 | test
14 |
15 |
16 | com.alibaba
17 | fastjson
18 | 1.1.41
19 |
20 |
21 | log4j
22 | log4j
23 | 1.2.16
24 |
25 |
26 | io.netty
27 | netty-all
28 | 4.0.28.Final
29 |
30 |
31 |
32 |
33 | netty_client_demo
34 | src/main/java
35 |
36 |
37 | org.apache.maven.plugins
38 | maven-compiler-plugin
39 | 2.3.2
40 |
41 | 1.7
42 | 1.7
43 | UTF-8
44 |
45 |
46 |
47 | org.apache.maven.plugins
48 | maven-jar-plugin
49 |
50 |
51 |
52 | true
53 | lib/
54 | websocketx.client.WebSocketClient
55 |
56 |
57 |
61 |
62 |
63 |
64 | org.apache.maven.plugins
65 | maven-dependency-plugin
66 |
67 |
68 | copy
69 | package
70 |
71 | copy-dependencies
72 |
73 |
74 | ${project.build.directory}/lib
75 |
76 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/zb_netty_client_java/src/main/java/com/world/common/SysEnum.java:
--------------------------------------------------------------------------------
1 | package com.world.common;
2 |
3 | public interface SysEnum {
4 | public int getKey();
5 | public String getValue();
6 | }
7 |
--------------------------------------------------------------------------------
/zb_netty_client_java/src/main/java/com/world/common/SystemCode.java:
--------------------------------------------------------------------------------
1 | package com.world.common;
2 |
3 | public enum SystemCode implements SysEnum{
4 |
5 | code_1000(1000, "操作成功", "success"),
6 | code_1001(1001, "一般错误提示", "error tips"),
7 |
8 | code_1002(1002, "内部错误", "Internal Error"),
9 | code_1003(1003, "验证不通过", "Validate No Pass"),
10 | code_1004(1004, "安全密码锁定", "Safe Password Locked"),
11 | code_1005(1005, "安全密码错误", "Safe Password Error"),
12 | code_1006(1006, "实名认证等待审核或审核不通过", "Audit Or Audit No Pass"),
13 |
14 | code_2001(2001 , "人民币账户余额不足" , "Insufficient CNY Balance"),
15 | code_2002(2002 , "比特币账户余额不足" , "Insufficient BTC Balance"),
16 | code_2003(2003 , "莱特币账户余额不足" , "Insufficient LTC Balance"),
17 | code_2004(2004 , "比特权账户余额不足" , "Insufficient BTQ Balance"),
18 |
19 | code_3001(3001 , "挂单没有找到" , "Not Found Order"),
20 | code_3002(3002 , "无效的金额" , "Invalid Money"),
21 | code_3003(3003 , "无效的数量" , "Invalid Amount"),
22 | code_3004(3004 , "用户不存在" , "No Such User"),
23 | code_3005(3005 , "无效的参数" , "Invalid Arguments"),
24 | code_3006(3006 , "无效的IP或与绑定的IP不一致", "Invalid Ip Address"),
25 | code_3007(3007 , "请求时间已失效", "Invalid Ip Request Time"),
26 |
27 | code_4001(4001 , "API接口被锁定或未启用", "API Locked Or Not Enabled"),
28 | code_4002(4002 , "请求过于频繁", "Request Too Frequently");
29 |
30 | private SystemCode(int key, String value , String className) {
31 | this.key = key;
32 | this.value = value;
33 | this.className = className;
34 | }
35 |
36 | private int key;
37 | private String value;
38 | private String className;
39 |
40 | public int getKey() {
41 | return key;
42 | }
43 |
44 | public String getValue() {
45 | return value;
46 | }
47 | public String getClassName() {
48 | return className;
49 | }
50 |
51 | public void setClassName(String className){
52 | this.className = className;
53 | }
54 |
55 | public void setValue(String value){
56 | this.value = value;
57 | }
58 |
59 | public static SystemCode getCode(int key){
60 | SystemCode code = null;
61 | for (SystemCode s : SystemCode.values()){
62 | if(s.getKey() == key){
63 | code = s;
64 | break;
65 | }
66 | }
67 | return code;
68 | }
69 |
70 | public static SystemCode getSystemCode(int key){
71 | switch(key){
72 | case 2: {
73 | return SystemCode.code_1002;
74 | }
75 | case 100: {
76 | return SystemCode.code_1000;
77 | }
78 | case 130: {
79 | SystemCode code = SystemCode.code_1001;
80 | code.setClassName("委托失败-未知的委托类型");
81 | code.setValue("委托失败-未知的委托类型");
82 | return code;
83 | }
84 | case 131: {
85 | return SystemCode.code_3005;
86 | }
87 | case 132: {
88 | SystemCode code = SystemCode.code_1001;
89 | code.setClassName("委托失败-还有卖比特币委托已经达到您本次购买的报价");
90 | code.setValue("委托失败-还有卖比特币委托已经达到您本次购买的报价");
91 | return code;
92 | }
93 | case 133: {
94 | SystemCode code = SystemCode.code_1001;
95 | code.setClassName("委托失败-还有买比特币委托已经达到您本次卖出的报价");
96 | code.setValue("委托失败-还有买比特币委托已经达到您本次卖出的报价");
97 | return code;
98 | }
99 | case 135: {
100 | return SystemCode.code_2001;
101 | }
102 | case 136: {
103 | return SystemCode.code_1002;
104 | }
105 | case 137: {
106 | SystemCode code = SystemCode.code_1001;
107 | code.setClassName("委托失败-价格太高、暂不支持");
108 | code.setValue("委托失败-价格太高、暂不支持");
109 | return code;
110 | }
111 | case 200: {
112 | return SystemCode.code_1000;
113 | }
114 | case 211: {
115 | return SystemCode.code_3001;
116 | }
117 | case 212: {
118 | SystemCode code = SystemCode.code_1001;
119 | code.setClassName("委托取消单个失败-已经提交过取消请求");
120 | code.setValue("委托取消单个失败-已经提交过取消请求");
121 | return code;
122 | }
123 | case 213: {
124 | SystemCode code = SystemCode.code_1001;
125 | code.setClassName("委托取消单个失败-取消程序");
126 | code.setValue("委托取消单个失败-取消程序");
127 | return code;
128 | }
129 | case 221: {
130 | return SystemCode.code_3001;
131 | }
132 | case 222: {
133 | SystemCode code = SystemCode.code_1001;
134 | code.setClassName("委托取消区间订单失败-区间价格可能颠倒导致错误");
135 | code.setValue("委托取消区间订单失败-事物处理失败");
136 | return code;
137 | }
138 | case 300: {
139 | return SystemCode.code_1000;
140 | }
141 | case 301: {
142 | return SystemCode.code_1000;
143 | }
144 | case 311: {
145 | SystemCode code = SystemCode.code_1001;
146 | code.setClassName("委托失败-未知的委托类型");
147 | code.setValue("委托失败-未知的委托类型");
148 | return code;
149 | }
150 | case 312: {
151 | SystemCode code = SystemCode.code_1001;
152 | code.setClassName("委托失败-事物处理失败");
153 | code.setValue("委托失败-事物处理失败");
154 | return code;
155 | }
156 | case 400: {
157 | return SystemCode.code_1000;
158 | }
159 | case 411: {
160 | return SystemCode.code_3001;
161 | }
162 | case 412: {
163 | SystemCode code = SystemCode.code_1001;
164 | code.setClassName("处理取消委托失败-已经成功委托");
165 | code.setValue("处理取消委托失败-已经成功委托");
166 | return code;
167 | }
168 | case 413: {
169 | SystemCode code = SystemCode.code_1001;
170 | code.setClassName("处理取消委托失败-事物处理失败");
171 | code.setValue("处理取消委托失败-事物处理失败");
172 | return code;
173 | }
174 | }
175 | return null;
176 | }
177 | }
178 |
--------------------------------------------------------------------------------
/zb_netty_client_java/src/main/java/com/world/common/VerifiUtil.java:
--------------------------------------------------------------------------------
1 | package com.world.common;
2 | //
3 | //import java.util.HashMap;
4 | //import java.util.Map;
5 | //
6 | //import javax.servlet.http.HttpServletRequest;
7 | //
8 | //import net.sf.json.JSONObject;
9 | //
10 | //import org.apache.commons.lang.StringUtils;
11 | //
12 | //import com.chbtc.api.ChbtcResponse;
13 | //import com.chbtc.api.user.UserManager;
14 | //import com.world.cache.Cache;
15 | //import com.world.controller.Base;
16 | //import com.world.controller.api.Index;
17 | //import com.world.util.ip.IpUtil;
18 | //import com.world.util.sign.EncryDigestUtil;
19 | //
20 | ///**
21 | // * API接口验证工具
22 | // * @author guosj
23 | // */
24 | public class VerifiUtil {
25 | //
26 | // private Map map;
27 | // //API方法固定的参数
28 | // private String[] order = {"method", "accesskey", "price", "amount", "tradeType", "currency"};
29 | // private String[] cancelOrder = {"method", "accesskey", "id", "currency"};
30 | // private String[] getOrder = {"method", "accesskey", "id", "currency"};
31 | // private String[] getOrders = {"method", "accesskey", "tradeType", "currency", "pageIndex"};
32 | // private String[] getOrdersNew = {"method", "accesskey", "tradeType", "currency", "pageIndex", "pageSize"};
33 | // private String[] getOrdersIgnoreTradeType = {"method", "accesskey", "currency", "pageIndex", "pageSize"};
34 | // private String[] getUnfinishedOrdersIgnoreTradeType = {"method", "accesskey", "currency", "pageIndex", "pageSize"};
35 | // private String[] getAccountInfo = {"method", "accesskey"};
36 | //
37 | // private static VerifiUtil verifiUtil;
38 | //
39 | // public static Map users;
40 | //
41 | // //
42 | // public static VerifiUtil getInstance(){
43 | // if(verifiUtil != null)
44 | // return verifiUtil;
45 | // else
46 | // return new VerifiUtil();
47 | // }
48 | //
49 | // public VerifiUtil(){
50 | // map = new HashMap();
51 | // map.put("order", order);
52 | // map.put("cancelOrder", cancelOrder);
53 | // map.put("getOrder", getOrder);
54 | // map.put("getOrders", getOrders);
55 | // map.put("getOrdersNew", getOrdersNew);
56 | // map.put("getOrdersIgnoreTradeType", getOrdersIgnoreTradeType);
57 | // map.put("getUnfinishedOrdersIgnoreTradeType", getUnfinishedOrdersIgnoreTradeType);
58 | // map.put("getAccountInfo", getAccountInfo);
59 | // }
60 | //
61 | // /**
62 | // * 获取指定按顺序的参数
63 | // * @return
64 | // */
65 | // public String[] getFixedArguments(String method){
66 | // return (String[]) map.get(method);
67 | // }
68 | //
69 | // /**
70 | // * API访问请求验证
71 | // * @param info
72 | // * @param key
73 | // * @param secret
74 | // * @return
75 | // */
76 | // public Object validateAuthAccess(Index index, HttpServletRequest request){
77 | // boolean flag = false;
78 | // try{
79 | // String key = request.getParameter("accesskey"); //用户传递访问key
80 | // long reqTime = new Long(request.getParameter("reqTime")); //用记的请求时间
81 | // String authInfo = request.getParameter("sign"); //用户根据URL生成的加密串
82 | //
83 | // //强制参数存在为空,不通过
84 | // if(StringUtils.isEmpty(authInfo) || StringUtils.isEmpty(key) || StringUtils.isEmpty(String.valueOf(reqTime))){
85 | // return SystemCode.code_3005;
86 | // }
87 | //
88 | // //==============================Memory Cache 进行IP、访问限制验证===================================================
89 | // //用户IP过滤
90 | // boolean ipLimit = true;
91 | // if(!ipLimit){
92 | // SystemCode code = SystemCode.code_1001;
93 | // code.setClassName("当前IP请求过于频繁,已列入黑名单,API交易接口已自动关闭");
94 | // code.setValue("当前IP请求过于频繁,已列入黑名单,API交易接口已自动关闭");
95 | // //关闭API交易接口
96 | // ChbtcResponse response = UserManager.getInstance().closeUserAutoApi(key);
97 | // JSONObject json = JSONObject.fromObject(response.getMsg());
98 | // if(response.taskIsFinish()){
99 | // if(json.getBoolean("isSuc")){
100 | // return code;
101 | // }else{
102 | // return false;
103 | // }
104 | // }else{
105 | // return false;
106 | // }
107 | // }
108 | //
109 | // //用户访问时间跟次数限制(相当必要)
110 | // Object accessLimit = accessLimit(request, key);
111 | // if(accessLimit instanceof SystemCode){
112 | // return accessLimit;
113 | // }else{
114 | // if(!((Boolean)accessLimit))
115 | // return SystemCode.code_4002;
116 | // }
117 | // //================================================================================================================================================
118 | //
119 | // if(users == null) users = new HashMap();
120 | //
121 | // JSONObject userObject = (JSONObject) users.get("user_object_json_" + key);
122 | // //是否需要重新查询用户
123 | // if(userObject == null){
124 | // ChbtcResponse response = UserManager.getInstance().getUserByAccessKey(key, 0);
125 | // if(response == null || !response.getMsg().startsWith("{")){
126 | // return SystemCode.code_1003;
127 | // }
128 | // if(response.taskIsFinish()){
129 | // JSONObject json = JSONObject.fromObject(response.getMsg());
130 | // if(json.getBoolean("isSuc")){
131 | // userObject = JSONObject.fromObject(json.getString("datas"));
132 | // //最后一次查询时间
133 | // users.put("user_object_json_" + key, userObject);
134 | // }
135 | // }
136 | // }
137 | //
138 | // if(userObject == null){
139 | // return SystemCode.code_1003;
140 | // }
141 | // //System.out.println("----------用户当前状态------------" + userObject.getInt("apiStatus"));
142 | // //设置已经查询到的用户对象
143 | // index.setJsonObject(userObject);
144 | //
145 | // if(userObject.getInt("apiStatus") == 2){//API接口开放交易
146 | //// String apiIpBind = userObject.getString("apiIpBind");
147 | //// //交易IP绑定
148 | //// if(StringUtils.isNotEmpty(apiIpBind)){
149 | //// //如果申请了绑定交易IP则验证IP审核状态
150 | //// if(userObject.getInt("apiIpStatus") == 2){
151 | //// //如果请求的IP与绑定的IP不一致
152 | //// if(!apiIpBind.equals(IpUtil.getIp(request))){//IP不一致
153 | //// return SystemCode.code_3006;
154 | //// }
155 | //// }else{
156 | //// return SystemCode.code_4001;
157 | //// }
158 | //// }
159 | //
160 | // //服务器当前时间
161 | // long currTime = System.currentTimeMillis();
162 | // //用户请求时间在必须在服务器时间前后5分钟
163 | // if(reqTime >= (currTime - 5*60*1000) && reqTime <= (currTime + 5*60*1000)){
164 | // //获取用户加密的原信息
165 | // Object info = getAuthorization(request);
166 | // if(info instanceof SystemCode){
167 | // return info;
168 | // }else{
169 | // //与用户执行相同的加密方法,传入相同的secret
170 | // info = EncryDigestUtil.hmacSign((String)info, userObject.getString("apiSecret"));
171 | // //与用户的加密信息作比较
172 | // if(authInfo.equals(info)){
173 | // flag = true;
174 | //// //验证通过,记录本次请求时间
175 | //// Data.Update("update btcuser set apiAuthTime=? where userId=?", new Object[]{reqTime, userObject.getString("userId")});
176 | // }
177 | // }
178 | // }
179 | // }else{
180 | // //Cache.Set("user_"+key+"_api_locked", String.valueOf("locked"), 30*60);
181 | // return SystemCode.code_4001;
182 | // }
183 | // }catch(Exception ex){
184 | // ex.printStackTrace();
185 | // return SystemCode.code_1002;
186 | // }
187 | // return flag;
188 | // }
189 | //
190 | // /**
191 | // * 用户加密原信息
192 | // * @param request
193 | // * @return
194 | // */
195 | // private Object getAuthorization(HttpServletRequest request){
196 | // String method = request.getRequestURI().substring(request.getRequestURI().lastIndexOf("/") + 1);
197 | // String[] fixedArguments = getFixedArguments(method);
198 | // StringBuffer buffer = new StringBuffer();
199 | // int i = 0;
200 | // String value = "";
201 | // for (String string : fixedArguments) {
202 | // if(i != 0){
203 | // buffer.append("&");
204 | // }
205 | // value = request.getParameter(string);
206 | // if(StringUtils.isEmpty(value)){
207 | // return SystemCode.code_3005;
208 | // }
209 | // buffer.append(string).append("=").append(value);
210 | // i++;
211 | // }
212 | // return buffer.toString();
213 | // }
214 | //
215 | // /**
216 | // * 访问限制
217 | // * 请求同一个方法,1s内只能请求一次
218 | // * 请求不同的方法,1s可以请求多次
219 | // * 请求同一个方法,1m内超过规定次数,视为恶意攻击,自动关闭API交易接口
220 | // * @param request
221 | // * @return
222 | // */
223 | // public Object accessLimit(HttpServletRequest request, String key) throws Exception{
224 | // //请求method
225 | // String method = request.getRequestURI().substring(request.getRequestURI().lastIndexOf("/") + 1);
226 | // //上一次的请求时间
227 | // String oldReqTime = Cache.Get(method + "_"+key);
228 | // //服务器当前时间
229 | // long currTime = System.currentTimeMillis();
230 | // //缓存时间周期
231 | // int cycle = 30*60;
232 | // //一分钟内限制次数
233 | // int limitTimes = 1000;
234 | // //限制时间1分钟
235 | // int limitTime = 60 * 1000;
236 | // //一秒钟内限制次数
237 | // int slimitTimes = 20;
238 | // //还未请求过,或缓存已失效
239 | // if(StringUtils.isEmpty(oldReqTime)){
240 | // Cache.Set(method+"_"+key, String.valueOf(currTime), cycle);
241 | // Cache.Set(method+"_"+key+"_one_min_times", "1", cycle);
242 | // Cache.Set(method+"_"+key+"_one_sec_times", "1", cycle);
243 | // Cache.Set(method+"_"+key+"_one_min_startTime", String.valueOf(currTime), cycle);
244 | // //Cache.Set("user_"+key+"_api_locked", String.valueOf("unlocked"), cycle);
245 | // return true;
246 | // }else{
247 | // //判断该用户是否被锁住API了
248 | //// if("locked".equals(Cache.Get("user_"+key+"_api_locked"))){
249 | //// return SystemCode.code_4001;
250 | //// }
251 | //
252 | // //上一次的请求时间
253 | // long old = new Long(oldReqTime);
254 | // //--------------------------------------限制一分钟内请求次数------------------------------------
255 | // //请求次数
256 | // String times = Cache.Get(method+"_"+key+"_one_min_times");
257 | // //根据用户建议,method=order其实需要分开为2个方法BTC/LTC
258 | // if(method.equalsIgnoreCase("order")){
259 | // //限制次数增加300次
260 | // limitTimes += 300;
261 | // }
262 | // //第一次请求开始时间
263 | // String startTime = Cache.Get(method+"_"+key+"_one_min_startTime");
264 | //
265 | // if(StringUtils.isEmpty(startTime)){
266 | // //重新设置请求次数
267 | // Cache.Set(method+"_"+key+"_one_min_times", "1", cycle);
268 | // return true;
269 | // }
270 | //
271 | // //1分钟内请求超过limitTimes次,关闭该用户API交易接口,并清空缓存
272 | // if(Integer.parseInt(times) > limitTimes && currTime - new Long(startTime) < limitTime){
273 | // Cache.Delete(method+"_"+key);
274 | // Cache.Delete(method+"_"+key+"_one_min_times");
275 | // Cache.Delete(method+"_"+key+"_one_sec_times");
276 | // Cache.Delete(method+"_"+key+"_one_min_startTime");
277 | // //Cache.Set("user_"+key+"_api_locked", String.valueOf("locked"), cycle);
278 | // //关闭API交易接口
279 | // ChbtcResponse response = UserManager.getInstance().closeUserAutoApi(key);
280 | // JSONObject json = JSONObject.fromObject(response.getMsg());
281 | // if(response.taskIsFinish()){
282 | // if(json.getBoolean("isSuc")){
283 | // return SystemCode.code_4001;
284 | // }
285 | // }
286 | // }else{
287 | // int t = 0;
288 | // //如果缓存时间与当前请求时间超过1分钟,则更新缓存的开始时间,请求次数归0
289 | // if(currTime - new Long(startTime) >= limitTime){
290 | // Cache.Set(method+"_"+key+"_one_min_startTime", String.valueOf(currTime), cycle);
291 | // t = 1;
292 | // }else{
293 | // //如果请求次数到达limitTimes次,则重新数数
294 | // if(Integer.parseInt(times) == (limitTimes + 1)){
295 | // t = 1;
296 | // }else{
297 | // t = Integer.parseInt(times) + 1;
298 | // }
299 | // }
300 | // //重新设置请求次数
301 | // Cache.Set(method+"_"+key+"_one_min_times", String.valueOf(t), cycle);
302 | // }
303 | // //===========================================================================================
304 | // //如果当前求比上一次请求时间>=1s
305 | // if(currTime - old >= 1000){
306 | // Cache.Set(method + "_"+key, String.valueOf(currTime), cycle);
307 | // Cache.Set(method + "_"+key+"_one_sec_times", "1", cycle);
308 | // return true;
309 | // }else{
310 | // //1秒钟内请求次数
311 | // int ost = Integer.parseInt(Cache.Get(method + "_"+key+"_one_sec_times"));
312 | // if(ost > slimitTimes){
313 | // //请求过于频繁
314 | // return SystemCode.code_4002;
315 | // }else{
316 | // Cache.Set(method + "_"+key, String.valueOf(currTime), cycle);
317 | // Cache.Set(method + "_"+key+"_one_sec_times", String.valueOf(ost+1), cycle);
318 | // return true;
319 | // }
320 | // }
321 | // }
322 | // }
323 | }
324 |
--------------------------------------------------------------------------------
/zb_netty_client_java/src/main/java/com/world/model/entitys/Balance.java:
--------------------------------------------------------------------------------
1 | package com.world.model.entitys;
2 |
3 | /**
4 | * 可用资金、货币
5 | * @author guosj
6 | */
7 | public class Balance {
8 | //货币标识
9 | private String currency;
10 | //货币符号
11 | private String symbol;
12 | //货币总量
13 | private double amount;
14 |
15 | public String getCurrency() {
16 | return currency;
17 | }
18 | public void setCurrency(String currency) {
19 | this.currency = currency;
20 | }
21 | public String getSymbol() {
22 | return symbol;
23 | }
24 | public void setSymbol(String symbol) {
25 | this.symbol = symbol;
26 | }
27 | public double getAmount() {
28 | return amount;
29 | }
30 | public void setAmount(double amount) {
31 | this.amount = amount;
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/zb_netty_client_java/src/main/java/com/world/model/entitys/Base.java:
--------------------------------------------------------------------------------
1 | package com.world.model.entitys;
2 |
3 | /**
4 | * 基础信息
5 | * @author guosj
6 | */
7 | public class Base {
8 | //用户名
9 | private String username;
10 | //是否开启安全密码
11 | private boolean trade_password_enabled;
12 | //是否启用手机认证
13 | private boolean auth_mobile_enabled;
14 | //是否启用谷歌认证
15 | private boolean auth_google_enabled;
16 | //private double trade_fee;
17 |
18 |
19 |
20 | public String getUsername() {
21 | return username;
22 | }
23 | public void setUsername(String username) {
24 | this.username = username;
25 | }
26 | public boolean isTrade_password_enabled() {
27 | return trade_password_enabled;
28 | }
29 | public void setTrade_password_enabled(boolean tradePasswordEnabled) {
30 | trade_password_enabled = tradePasswordEnabled;
31 | }
32 | public boolean isAuth_mobile_enabled() {
33 | return auth_mobile_enabled;
34 | }
35 | public void setAuth_mobile_enabled(boolean authMobileEnabled) {
36 | auth_mobile_enabled = authMobileEnabled;
37 | }
38 | public boolean isAuth_google_enabled() {
39 | return auth_google_enabled;
40 | }
41 | public void setAuth_google_enabled(boolean authGoogleEnabled) {
42 | auth_google_enabled = authGoogleEnabled;
43 | }
44 | // public double getTrade_fee() {
45 | // return trade_fee;
46 | // }
47 | // public void setTrade_fee(double tradeFee) {
48 | // trade_fee = tradeFee;
49 | // }
50 | //
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/zb_netty_client_java/src/main/java/com/world/model/entitys/Frozen.java:
--------------------------------------------------------------------------------
1 | package com.world.model.entitys;
2 |
3 | /**
4 | * 冻结资金、货币
5 | * @author guosj
6 | */
7 | public class Frozen {
8 | //货币标识
9 | private String currency;
10 | //货币符号
11 | private String symbol;
12 | //货币总量
13 | private double amount;
14 | public String getCurrency() {
15 | return currency;
16 | }
17 | public void setCurrency(String currency) {
18 | this.currency = currency;
19 | }
20 | public String getSymbol() {
21 | return symbol;
22 | }
23 | public void setSymbol(String symbol) {
24 | this.symbol = symbol;
25 | }
26 | public double getAmount() {
27 | return amount;
28 | }
29 | public void setAmount(double amount) {
30 | this.amount = amount;
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/zb_netty_client_java/src/main/java/com/world/model/entitys/Order.java:
--------------------------------------------------------------------------------
1 | package com.world.model.entitys;
2 |
3 | /**
4 | * 委托订单
5 | * @author guosj
6 | */
7 | public class Order {
8 |
9 | //挂单ID
10 | private String id;
11 | //挂单类型 1/0 buy/sell
12 | private int type;
13 | //单价
14 | private double price;
15 | //挂单货币类型 btc/ltc
16 | private String currency;
17 | //已成交数量
18 | private double trade_amount;
19 | //已成交总金额
20 | private double trade_money;
21 | //挂单总数量
22 | private double total_amount;
23 | //挂单交易日期
24 | private long trade_date;
25 | //挂单状态
26 | private int status;
27 |
28 | public String getId() {
29 | return id;
30 | }
31 | public void setId(String id) {
32 | this.id = id;
33 | }
34 | public int getType() {
35 | return type;
36 | }
37 | public void setType(int type) {
38 | this.type = type;
39 | }
40 | public double getPrice() {
41 | return price;
42 | }
43 | public void setPrice(double price) {
44 | this.price = price;
45 | }
46 | public String getCurrency() {
47 | return currency;
48 | }
49 | public void setCurrency(String currency) {
50 | this.currency = currency;
51 | }
52 |
53 | public double getTrade_amount() {
54 | return trade_amount;
55 | }
56 | public void setTrade_amount(double tradeAmount) {
57 | trade_amount = tradeAmount;
58 | }
59 | public double getTotal_amount() {
60 | return total_amount;
61 | }
62 | public void setTotal_amount(double totalAmount) {
63 | total_amount = totalAmount;
64 | }
65 | public long getTrade_date() {
66 | return trade_date;
67 | }
68 | public void setTrade_date(long tradeDate) {
69 | trade_date = tradeDate;
70 | }
71 | public int getStatus() {
72 | return status;
73 | }
74 | public void setStatus(int status) {
75 | this.status = status;
76 | }
77 | public double getTrade_money() {
78 | return trade_money;
79 | }
80 | public void setTrade_money(double trade_money) {
81 | this.trade_money = trade_money;
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/zb_netty_client_java/src/main/java/com/world/model/market/Arith.java:
--------------------------------------------------------------------------------
1 | package com.world.model.market;
2 | import java.math.BigDecimal;
3 | /**
4 | * 由于Java的简单类型不能够精确的对浮点数进行运算,这个工具类提供精
5 | * 确的浮点数运算,包括加减乘除和四舍五入。
6 | */
7 | public class Arith {
8 | //默认除法运算精度
9 | private static final int DEF_DIV_SCALE = 10;
10 | //这个类不能实例化
11 | private Arith(){
12 | }
13 |
14 | /**
15 | * 提供精确的加法运算。
16 | * @param v1 被加数
17 | * @param v2 加数
18 | * @return 两个参数的和
19 | */
20 | public static double add(double v1,double v2){
21 | BigDecimal b1 = new BigDecimal(Double.toString(v1));
22 | BigDecimal b2 = new BigDecimal(Double.toString(v2));
23 | return b1.add(b2).doubleValue();
24 | }
25 | /**
26 | * 提供精确的减法运算。
27 | * @param v1 被减数
28 | * @param v2 减数
29 | * @return 两个参数的差
30 | */
31 | public static double sub(double v1,double v2){
32 | BigDecimal b1 = new BigDecimal(Double.toString(v1));
33 | BigDecimal b2 = new BigDecimal(Double.toString(v2));
34 | return b1.subtract(b2).doubleValue();
35 | }
36 | /**
37 | * 提供精确的乘法运算。
38 | * @param v1 被乘数
39 | * @param v2 乘数
40 | * @return 两个参数的积
41 | */
42 | public static double mul(double v1,double v2){
43 | BigDecimal b1 = new BigDecimal(Double.toString(v1));
44 | BigDecimal b2 = new BigDecimal(Double.toString(v2));
45 | return b1.multiply(b2).doubleValue();
46 | }
47 |
48 | /**
49 | * 提供精确的乘法运算。
50 | * @param v1 被乘数
51 | * @param v2 乘数
52 | * @return 两个参数的积
53 | */
54 | public static long mul(double v1,long v2,int dian){
55 | v1=round(v1,dian);//进行一个小数位的取舍,这样避免跑到外面
56 | BigDecimal b1 = new BigDecimal(Double.toString(v1));
57 | BigDecimal b2 = new BigDecimal(Long.toString(v2));
58 | return b1.multiply(b2).longValue();
59 | }
60 | /**
61 | * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
62 | * 小数点以后10位,以后的数字四舍五入。
63 | * @param v1 被除数
64 | * @param v2 除数
65 | * @return 两个参数的商
66 | */
67 | public static double div(double v1,double v2){
68 | return div(v1,v2,DEF_DIV_SCALE);
69 | }
70 |
71 | /**
72 | * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
73 | * 定精度,以后的数字四舍五入。
74 | * @param v1 被除数
75 | * @param v2 除数
76 | * @param scale 表示表示需要精确到小数点以后几位。
77 | * @return 两个参数的商
78 | */
79 | public static double div(double v1,double v2,int scale){
80 | if(scale<0){
81 | throw new IllegalArgumentException(
82 | "The scale must be a positive integer or zero");
83 | }
84 | BigDecimal b1 = new BigDecimal(Double.toString(v1));
85 | BigDecimal b2 = new BigDecimal(Double.toString(v2));
86 | return b1.divide(b2,scale,BigDecimal.ROUND_DOWN).doubleValue();
87 |
88 | }
89 |
90 | /**
91 | * 提供精确的小数位四舍五入处理。
92 | * @param v 需要四舍五入的数字
93 | * @param scale 小数点后保留几位
94 | * @return 四舍五入后的结果
95 | */
96 | public static double round(double v,int scale){
97 | if(scale<0){
98 | throw new IllegalArgumentException(
99 | "The scale must be a positive integer or zero");
100 | }
101 | BigDecimal b = new BigDecimal(Double.toString(v));
102 | BigDecimal one = new BigDecimal("1");
103 | return b.divide(one,scale,BigDecimal.ROUND_DOWN).doubleValue();
104 | }
105 | public static void main(String args[]){
106 | // System.out.println(add(0.05,0.01));
107 | // System.out.println(1.0-0.42);
108 | // System.out.println(4.015*100);
109 | // System.out.println(123.3/100);
110 | // System.out.println(div(10,3));
111 | // System.out.println(10/3);
112 | System.out.println(mul(23.89943,10000000,2));
113 |
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/zb_netty_client_java/src/main/java/com/world/model/market/Market.java:
--------------------------------------------------------------------------------
1 | package com.world.model.market;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 | import java.util.ResourceBundle;
6 |
7 | public class Market {
8 |
9 | public String numberBi;
10 | public String numberBiEn;
11 | public String numberBiNote;
12 | public long numberBixNormal;
13 | public long numberBixShow;//"+//显示的计量单位是最小存储单位的倍数,不相等的时候会缩小到指定单位(等于小数点位数)
14 | public int numberBixDian;//=3;"+//小数点后几位,如果有小数的话
15 | public String exchangeBi;//=\"比特币\";"+
16 | public String exchangeBiEn;//=\"BTC\";"+
17 | public String exchangeBiNote;//=\"฿\";"+
18 | public String market;//=\"btqdefault\";"+
19 | public long exchangeBixNormal;//=100000000;"+//标准单位是最小存储单位的位数
20 | public long exchangeBixShow;//=100000000;"+//显示的计量单位是最小存储单位的倍数
21 | public int exchangeBixDian;//=4;"+//小数点后几位,如果有小数的话
22 | public String entrustUrlBase;//=\"/\";"+
23 |
24 | public int maxPrice;//最大的档位
25 |
26 | public int webId;
27 | public String ip;
28 | public int port;
29 | public String hashSec;//加密公钥
30 |
31 | /**
32 | * 是否是简化版
33 | * @param isSimple
34 | * @return
35 | */
36 | public String toString(){
37 | String ls="var numberBi=\""+numberBi+"\";"+
38 | "var numberBiEn=\""+numberBiEn+"\";"+
39 | "var numberBiNote=\""+numberBiNote+"\";"+
40 | "var numberBixNormal="+numberBixNormal+";"+//标准单位是最小存储单位的位数
41 | "var numberBixShow="+numberBixShow+";"+//显示的计量单位是最小存储单位的倍数,不相等的时候会缩小到指定单位(等于小数点位数)
42 | "var numberBixDian="+numberBixDian+";"+//小数点后几位,如果有小数的话
43 | "var exchangeBi=\""+exchangeBi+"\";"+
44 | "var exchangeBiEn=\""+exchangeBiEn+"\";"+
45 | "var exchangeBiNote=\""+exchangeBiNote+"\";"+
46 | "var market=\""+market+"\";"+
47 | "var exchangeBixNormal="+exchangeBixNormal+";"+//标准单位是最小存储单位的位数
48 | "var exchangeBixShow="+exchangeBixShow+";"+//显示的计量单位是最小存储单位的倍数
49 | "var exchangeBixDian="+exchangeBixDian+";"+//小数点后几位,如果有小数的话
50 | "var entrustUrlBase=\""+entrustUrlBase+"\";";
51 | return ls;
52 | }
53 |
54 | static Map makets = new HashMap();
55 |
56 | public static final String btcdefault = getBtcDefault().toString();
57 | public static final String ltcdefault = getLtcDefault().toString();
58 | public static final String btqdefault = getBtqDefault().toString();
59 |
60 | private static Market marketObj = null;
61 |
62 | public static Market getInstance(){
63 | if(marketObj == null){
64 | marketObj = new Market();
65 | }
66 | return marketObj;
67 | }
68 |
69 |
70 | public static Market getBtcDefault(){
71 | return getMarket("btcdefault");
72 | }
73 |
74 | public static Market getLtcDefault(){
75 | return getMarket("ltcdefault");
76 | }
77 |
78 | public static Market getBtqDefault(){
79 | return getMarket("btqdefault");
80 | }
81 |
82 | /**
83 | * 获取一个市场
84 | * @return
85 | */
86 | public static synchronized Market getMarket(String name){
87 | try{
88 | Market m = makets.get(name);
89 | if(m != null){
90 | return m;
91 | }
92 | ResourceBundle rb= ResourceBundle.getBundle(name);
93 | m=new Market();
94 | if(name.equals("btcdefault")){
95 | m.numberBi="比特币";
96 | m.numberBiNote="฿";
97 | m.exchangeBi="人民币";
98 | m.exchangeBiNote="¥";
99 | }else if(name.equals("ltcdefault")){
100 | m.numberBi="莱特币";
101 | m.numberBiNote="Ł";
102 | m.exchangeBi="人民币";
103 | m.exchangeBiNote="¥";
104 | }else if(name.equals("btqdefault")){
105 | m.numberBi="比特权";
106 | m.numberBiNote="BTQ";
107 | m.exchangeBi="比特币";
108 | m.exchangeBiNote="฿";
109 | }
110 |
111 | //m.numberBi=new String(rb.getString("numberBi").getBytes("ISO-8859-1"), "UTF-8");
112 | m.numberBiEn=rb.getString("numberBiEn");
113 | //m.numberBiNote=new String(rb.getString("numberBiNote").getBytes("ISO-8859-1"), "GBK");
114 | m.numberBixNormal=Long.parseLong(rb.getString("numberBixNormal"));
115 | m.numberBixShow=Long.parseLong(rb.getString("numberBixShow"));
116 | m.numberBixDian=Integer.parseInt((rb.getString("numberBixDian")));
117 | //m.exchangeBi=new String(rb.getString("exchangeBi").getBytes("ISO-8859-1"), "UTF-8");
118 | m.exchangeBiEn=new String(rb.getString("exchangeBiEn").getBytes("ISO-8859-1"), "UTF-8");
119 | //m.exchangeBiNote=rb.getString("exchangeBiNote");
120 | m.market=rb.getString("market");
121 | m.exchangeBixNormal=Long.parseLong(rb.getString("exchangeBixNormal"));
122 | m.exchangeBixShow=Long.parseLong(rb.getString("exchangeBixShow"));
123 | m.exchangeBixDian=Integer.parseInt(rb.getString("exchangeBixDian"));
124 | m.entrustUrlBase=rb.getString("entrustUrlBase");
125 | m.webId=Integer.parseInt(rb.getString("webId"));
126 | m.ip=rb.getString("ip");
127 | m.port=Integer.parseInt(rb.getString("port"));
128 | m.hashSec=rb.getString("hashSec");
129 | m.maxPrice=Integer.parseInt(rb.getString("maxPrice"));
130 | makets.put(name, m);
131 | return m;
132 | }catch(Exception ex){
133 | ex.printStackTrace();
134 | return null;
135 | }
136 | }
137 |
138 |
139 | //双重格式化,保留应有的小数点位数,避免麻烦
140 | public double formatNumber(double num){
141 | double numNew=Arith.div(num, numberBixNormal,numberBixDian);
142 |
143 | return numNew;
144 | }
145 |
146 | //反向格式化商品,用来将部分double类型的传值转化成long类型进行委托
147 | public long formatNumberLong(double num){
148 | long numNew=Arith.mul(num, numberBixNormal,numberBixDian);
149 |
150 | return numNew;
151 | }
152 |
153 |
154 | //格式化商品,用于显示,将基础整数位的商品格式化成需要的显示
155 | public long ffNumber(long num){
156 | double numNew=Arith.div(num, numberBixNormal,numberBixDian);
157 | numNew=Arith.mul(numNew, numberBixNormal);
158 |
159 | return Math.round(numNew);
160 | }
161 | //比如给出2345554.返回2345000
162 | public long ffMoney(long num){
163 | double numNew=Arith.div(num, exchangeBixNormal,exchangeBixDian);
164 | numNew=Arith.mul(numNew, exchangeBixNormal);
165 |
166 | return Math.round(numNew);
167 | }
168 |
169 | //格式化金钱 3.456 变成3.45
170 | public double formatMoney(double num){
171 | double numNew=Arith.div(num, exchangeBixNormal,exchangeBixDian);
172 | // num=parseFloat(num)/exchangeBixNormal;
173 | // if(exchangeBixNormal!=exchangeBixShow)//不等于就说明取整数的位数
174 | // return Math.floor(Math.pow(10,exchangeBixDian)*parseFloat(num));
175 | // else
176 | // return parseFloat(num.toFixed(exchangeBixDian));
177 | return numNew;
178 | }
179 |
180 | /**
181 | * 格式化出来一个资金和数量乘积之后的结果
182 | * @param num
183 | * @return 12300*100100000=1231230000000 格式化后为123.123
184 | */
185 | public double formatMoneyAndNumber(double num){
186 | double numNew=Arith.div(num, exchangeBixNormal*numberBixNormal,exchangeBixDian+numberBixDian);
187 |
188 | return numNew;
189 | }
190 |
191 | //反向格式化商品,用来将部分double类型的传值转化成long类型进行委托 3.45变成345
192 | public long formatMoneyLong(double num){
193 | long numNew=Arith.mul(num, exchangeBixNormal,exchangeBixDian);
194 |
195 | return numNew;
196 | }
197 |
198 | /**
199 | * 格式化出来总价long形长的
200 | * @param unitPrice
201 | * @param numbers
202 | * @return
203 | */
204 | public long formatTotalMoney(long unitPrice,long numbers){
205 | return unitPrice*numbers;
206 | // double unitP=formatMoney(unitPrice);
207 | //
208 | // double numb=formatNumber(numbers);
209 | //
210 | // double t=Arith.mul(unitP,numb);
211 | //
212 | // t=Arith.round(t, Market.exchangeBixDian);
213 | //
214 | // t=Arith.mul(t,Market.exchangeBixNormal);
215 | //
216 | // long rt=Arith.mul(t,Market.numberBixNormal,0);
217 | // return rt;
218 | }
219 |
220 | /**
221 | * 格式化出来总价 double形用的短的
222 | * @param unitPrice
223 | * @param numbers
224 | * @return
225 | */
226 | public double formatTotalMoneyDoule(long unitPrice,long numbers){
227 | double unitP=formatMoney(unitPrice);
228 |
229 | double numb=formatNumber(numbers);
230 |
231 | double t=Arith.mul(unitP,numb);
232 |
233 | t=Arith.round(t, exchangeBixDian+numberBixDian);
234 |
235 | return t;
236 | }
237 | }
238 |
--------------------------------------------------------------------------------
/zb_netty_client_java/src/main/java/com/zb/kits/MapSort.java:
--------------------------------------------------------------------------------
1 | package com.zb.kits;
2 |
3 | import java.net.URLEncoder;
4 | import java.util.ArrayList;
5 | import java.util.Collections;
6 | import java.util.Comparator;
7 | import java.util.HashMap;
8 | import java.util.Iterator;
9 | import java.util.List;
10 | import java.util.Map;
11 | import java.util.Map.Entry;
12 | import java.util.TreeMap;
13 |
14 | import com.sun.xml.internal.ws.util.StringUtils;
15 |
16 | public class MapSort {
17 |
18 | /**
19 | *
20 | * 方法用途: 对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序),并且生成url参数串
21 | * 实现步骤:
22 | *
23 | * @param paraMap
24 | * 要排序的Map对象
25 | * @param urlEncode
26 | * 是否需要URLENCODE
27 | * @param keyToLower
28 | * 是否需要将Key转换为全小写 true:key转化成小写,false:不转化
29 | * @return
30 | */
31 | public static String formatUrlMap(Map paraMap, boolean urlEncode, boolean keyToLower) {
32 | String buff = "";
33 | Map tmpMap = paraMap;
34 | try {
35 | List> infoIds = new ArrayList>(tmpMap.entrySet());
36 | // 对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序)
37 | Collections.sort(infoIds, new Comparator>() {
38 |
39 | @Override
40 | public int compare(Map.Entry o1, Map.Entry o2) {
41 | return (o1.getKey()).toString().compareTo(o2.getKey());
42 | }
43 | });
44 | // 构造URL 键值对的格式
45 | StringBuilder buf = new StringBuilder();
46 | for (Map.Entry item : infoIds) {
47 |
48 | String key = item.getKey();
49 | String val = item.getValue();
50 | if (urlEncode) {
51 | val = URLEncoder.encode(val, "utf-8");
52 | }
53 | if (keyToLower) {
54 | buf.append(key.toLowerCase() + "=" + val);
55 | } else {
56 | buf.append(key + "=" + val);
57 | }
58 | buf.append("&");
59 |
60 |
61 | }
62 | buff = buf.toString();
63 | if (buff.isEmpty() == false) {
64 | buff = buff.substring(0, buff.length() - 1);
65 | }
66 | } catch (Exception e) {
67 | return null;
68 | }
69 | return buff;
70 | }
71 |
72 | public static void main(String[] args) {
73 |
74 | Map map = new HashMap();
75 |
76 | map.put("Kb", "K");
77 | map.put("Wc", "W");
78 | map.put("Ab", "A");
79 | map.put("ad", "a");
80 | map.put("Fe", "N");
81 | map.put("Bf", "B");
82 | map.put("Cg", "C");
83 | map.put("Zh", "Z");
84 |
85 | Map resultMap = sortMapByKey(map); // 按Key进行排序,根据首字母hashcode
86 |
87 | for (Map.Entry entry : resultMap.entrySet()) {
88 | System.out.println(entry.getKey() + " " + entry.getValue());
89 | }
90 |
91 | }
92 |
93 | /**
94 | * 使用 Map按key首字母hashcode进行排序
95 | *
96 | * @param map
97 | * @return
98 | */
99 | public static Map sortMapByKey(Map map) {
100 | if (map == null || map.isEmpty()) {
101 | return null;
102 | }
103 |
104 | Map sortMap = new TreeMap(new MapKeyComparator());
105 |
106 | sortMap.putAll(map);
107 |
108 | return sortMap;
109 | }
110 |
111 | public static String toStringMap(Map m) {
112 | // 按map键首字母顺序进行排序
113 | m = MapSort.sortMapByKey(m);
114 |
115 | StringBuilder sbl = new StringBuilder();
116 | for (Iterator i = m.entrySet().iterator(); i.hasNext();) {
117 | Entry e = i.next();
118 | Object o = e.getValue();
119 | String v = "";
120 | if (o == null) {
121 | v = "";
122 | } else if (o instanceof String[]) {
123 | String[] s = (String[]) o;
124 | if (s.length > 0) {
125 | v = s[0];
126 | }
127 | } else {
128 | v = o.toString();
129 | }
130 | if (!e.getKey().equals("sign") && !e.getKey().equals("reqTime") && !e.getKey().equals("tx")) {
131 | // try {
132 | // sbl.append("&").append(e.getKey()).append("=").append(URLEncoder.encode(v,
133 | // "utf-8"));
134 | // } catch (UnsupportedEncodingException e1) {
135 | // e1.printStackTrace();
136 | sbl.append("&").append(e.getKey()).append("=").append(v);
137 | // }
138 | }
139 | }
140 | String s = sbl.toString();
141 | if (s.length() > 0) {
142 | return s.substring(1);
143 | }
144 | return "";
145 | }
146 | }
147 |
148 | class MapKeyComparator implements Comparator {
149 |
150 | public int compare(String str1, String str2) {
151 |
152 | return str1.compareTo(str2);
153 | }
154 | }
--------------------------------------------------------------------------------
/zb_netty_client_java/src/main/java/websocketx/client/EncryDigestUtil.java:
--------------------------------------------------------------------------------
1 | package websocketx.client;
2 |
3 | import java.io.UnsupportedEncodingException;
4 | import java.security.MessageDigest;
5 | import java.security.NoSuchAlgorithmException;
6 | import java.util.Arrays;
7 |
8 | public class EncryDigestUtil {
9 |
10 | private final static String encodingCharset = "UTF-8";
11 |
12 | /**
13 | * 生成签名消息
14 | * @param aValue 要签名的字符
15 | * @param aKey 签名密钥
16 | * @return
17 | */
18 | public static String hmacSign(String aValue, String aKey) {
19 | byte k_ipad[] = new byte[64];
20 | byte k_opad[] = new byte[64];
21 | byte keyb[];
22 | byte value[];
23 | try {
24 | keyb = aKey.getBytes(encodingCharset);
25 | value = aValue.getBytes(encodingCharset);
26 | } catch (UnsupportedEncodingException e) {
27 | keyb = aKey.getBytes();
28 | value = aValue.getBytes();
29 | }
30 |
31 | Arrays.fill(k_ipad, keyb.length, 64, (byte) 54);
32 | Arrays.fill(k_opad, keyb.length, 64, (byte) 92);
33 | for (int i = 0; i < keyb.length; i++) {
34 | k_ipad[i] = (byte) (keyb[i] ^ 0x36);
35 | k_opad[i] = (byte) (keyb[i] ^ 0x5c);
36 | }
37 |
38 | MessageDigest md = null;
39 | try {
40 | md = MessageDigest.getInstance("MD5");
41 | } catch (NoSuchAlgorithmException e) {
42 |
43 | return null;
44 | }
45 | md.update(k_ipad);
46 | md.update(value);
47 | byte dg[] = md.digest();
48 | md.reset();
49 | md.update(k_opad);
50 | md.update(dg, 0, 16);
51 | dg = md.digest();
52 | return toHex(dg);
53 | }
54 |
55 | public static String toHex(byte input[]) {
56 | if (input == null)
57 | return null;
58 | StringBuffer output = new StringBuffer(input.length * 2);
59 | for (int i = 0; i < input.length; i++) {
60 | int current = input[i] & 0xff;
61 | if (current < 16)
62 | output.append("0");
63 | output.append(Integer.toString(current, 16));
64 | }
65 |
66 | return output.toString();
67 | }
68 |
69 | /**
70 | *
71 | * @param args
72 | * @param key
73 | * @return
74 | */
75 | public static String getHmac(String[] args, String key) {
76 | if (args == null || args.length == 0) {
77 | return (null);
78 | }
79 | StringBuffer str = new StringBuffer();
80 | for (int i = 0; i < args.length; i++) {
81 | str.append(args[i]);
82 | }
83 | return (hmacSign(str.toString(), key));
84 | }
85 |
86 | /**
87 | * SHA加密
88 | * @param aValue
89 | * @return
90 | */
91 | public static String digest(String aValue) {
92 | aValue = aValue.trim();
93 | byte value[];
94 | try {
95 | value = aValue.getBytes(encodingCharset);
96 | } catch (UnsupportedEncodingException e) {
97 | value = aValue.getBytes();
98 | }
99 | MessageDigest md = null;
100 | try {
101 | md = MessageDigest.getInstance("SHA");
102 | } catch (NoSuchAlgorithmException e) {
103 | e.printStackTrace();
104 | return null;
105 | }
106 | return toHex(md.digest(value));
107 |
108 | }
109 |
110 | // public static void main(String[] args) {
111 | // System.out.println(hmacSign("AnnulCard1000043252120080620160450.0http://localhost/SZXpro/callback.asp�?4564868265473632445648682654736324511","8UPp0KE8sq73zVP370vko7C39403rtK1YwX40Td6irH216036H27Eb12792t"));
112 | // }
113 | }
114 |
--------------------------------------------------------------------------------
/zb_netty_client_java/src/main/java/websocketx/client/RunExample.java:
--------------------------------------------------------------------------------
1 | package websocketx.client;
2 |
3 | import org.apache.log4j.Logger;
4 |
5 | public class RunExample {
6 |
7 | private static Logger log = Logger.getLogger(RunExample.class);
8 |
9 | public static WebSocketClient client;
10 |
11 | public static void main(String[] args) {
12 | try {
13 | if(client==null){
14 | log.info("链接到"+WebSocketClient.serverUrl);
15 | client = new WebSocketClient( WebSocketClient.serverUrl );
16 | }
17 | client.connect();
18 | log.info("================================"+client.isAlive());
19 | client.doTask();
20 | } catch (Exception e) {
21 | // TODO Auto-generated catch block
22 | e.printStackTrace();
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/zb_netty_client_java/src/main/java/websocketx/client/WebSocketClient.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 The Netty Project
3 | *
4 | * The Netty Project licenses this file to you under the Apache License,
5 | * version 2.0 (the "License"); you may not use this file except in compliance
6 | * with the License. You may obtain a copy of the License at:
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations
14 | * under the License.
15 | */
16 | package websocketx.client;
17 |
18 | import io.netty.bootstrap.Bootstrap;
19 | import io.netty.channel.Channel;
20 | import io.netty.channel.ChannelException;
21 | import io.netty.channel.ChannelInitializer;
22 | import io.netty.channel.ChannelPipeline;
23 | import io.netty.channel.EventLoopGroup;
24 | import io.netty.channel.nio.NioEventLoopGroup;
25 | import io.netty.channel.socket.SocketChannel;
26 | import io.netty.channel.socket.nio.NioSocketChannel;
27 | import io.netty.handler.codec.http.DefaultHttpHeaders;
28 | import io.netty.handler.codec.http.HttpClientCodec;
29 | import io.netty.handler.codec.http.HttpObjectAggregator;
30 | import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
31 | import io.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory;
32 | import io.netty.handler.codec.http.websocketx.WebSocketVersion;
33 | import io.netty.handler.ssl.SslContext;
34 | import io.netty.handler.ssl.SslContextBuilder;
35 | import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
36 |
37 | import java.math.BigDecimal;
38 | import java.net.URI;
39 | import java.nio.channels.UnsupportedAddressTypeException;
40 | import java.util.HashMap;
41 | import java.util.Map;
42 |
43 | import com.alibaba.fastjson.JSONObject;
44 | import com.zb.kits.MapSort;
45 |
46 | public class WebSocketClient {
47 | private String url;
48 | private EventLoopGroup group;
49 | private Channel channel;
50 |
51 | public final String accessKey = "";
52 | public final String secretKey = "";
53 | public static String serverUrl = "wss://api.zb.com:9999/websocket";
54 | public static String payPass = "xxxxxxxxx";
55 |
56 | public WebSocketClient(String url){
57 | this.url=url;
58 | }
59 |
60 | public void connect() throws Exception {
61 | if (url == null || "".equals(url.trim())) {
62 | throw new NullPointerException("the url can not be empty");
63 | }
64 | URI uri = new URI(url);
65 | String scheme = uri.getScheme() == null ? "http" : uri.getScheme();
66 | final String host = uri.getHost() == null ? "127.0.0.1" : uri.getHost();
67 | final int port;
68 | if (uri.getPort() == -1) {
69 | if ("http".equalsIgnoreCase(scheme)) {
70 | port = 80;
71 | } else if ("wss".equalsIgnoreCase(scheme)) {
72 | port = 443;
73 | } else {
74 | port = -1;
75 | }
76 | } else {
77 | port = uri.getPort();
78 | }
79 |
80 | if (!"ws".equalsIgnoreCase(scheme) && !"wss".equalsIgnoreCase(scheme)) {
81 | System.err.println("Only WS(S) is supported.");
82 | throw new UnsupportedAddressTypeException();
83 | }
84 | final boolean ssl = "wss".equalsIgnoreCase(scheme);
85 | final SslContext sslCtx;
86 | if (ssl) {
87 | sslCtx = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build();
88 | } else {
89 | sslCtx = null;
90 | }
91 | group = new NioEventLoopGroup();
92 | try {
93 | final WebSocketClientHandler handler = new WebSocketClientHandler(
94 | WebSocketClientHandshakerFactory.newHandshaker(uri,
95 | WebSocketVersion.V13, null, false,
96 | new DefaultHttpHeaders())) {
97 | @Override
98 | public void onReceive(String msg) {
99 | System.out.println("channel获取消息:" + msg);
100 | }
101 | };
102 | Bootstrap b = new Bootstrap();
103 | b.group(group).channel(NioSocketChannel.class)
104 | .handler(new ChannelInitializer() {
105 | @Override
106 | protected void initChannel(SocketChannel ch) {
107 | ChannelPipeline p = ch.pipeline();
108 | if (sslCtx != null) {
109 | p.addLast(sslCtx.newHandler(ch.alloc(), host,
110 | port));
111 | }
112 | p.addLast(new HttpClientCodec(),
113 | new HttpObjectAggregator(8192), handler);
114 | }
115 | });
116 |
117 | channel = b.connect(uri.getHost(), port).sync().channel();
118 | // ChannelFuture f = channel.closeFuture().await();
119 | handler.handshakeFuture().sync();
120 | } catch (Exception e) {
121 | this.cancel();
122 | throw e;
123 | }
124 | }
125 |
126 | /**
127 | * 订阅频道(仅限公共频道)
128 | * @param channel
129 | * @throws ChannelException
130 | */
131 | public void addChannel(String channel)throws ChannelException{
132 | if(!isAlive())throw new ChannelException("the channel is not active");
133 | JSONObject data=new JSONObject();
134 | data.put("event", "addChannel");
135 | data.put("channel", channel);
136 |
137 | System.out.println(data);
138 |
139 | this.channel.writeAndFlush(new TextWebSocketFrame(data.toString()));
140 | }
141 |
142 | /**
143 | * 取消订阅(仅限公共频道)
144 | * @param channel
145 | * @param currency
146 | * @throws ChannelException
147 | */
148 | public void removeChannel(String channel,String currency)throws ChannelException{
149 | if(!isAlive())throw new ChannelException("the channel is not active");
150 | this.channel.writeAndFlush(new TextWebSocketFrame("{'event':'removeChannel','channel':'"+channel+"'}"));
151 | }
152 |
153 | /**
154 | * 委托下单
155 | * @param accessKey
156 | * @param secretKey
157 | * @param price
158 | * @param amount
159 | * @param coin
160 | * @param tradeType 1buy
161 | * @throws Exception
162 | */
163 | public void order(double price,double amount,String coin, int tradeType)throws Exception{
164 | if(!isAlive())throw new ChannelException("the channel is not active");
165 |
166 | JSONObject data=new JSONObject();
167 | data.put("event", "addChannel");
168 | data.put("channel", coin.toLowerCase()+"_order");
169 | data.put("accesskey", accessKey);
170 | data.put("price", price);
171 | data.put("amount", amount);
172 | data.put("tradeType", tradeType);
173 |
174 | String secret = EncryDigestUtil.digest(secretKey);
175 | String sign = EncryDigestUtil.hmacSign(data.toString(), secret);
176 |
177 | data.put("sign", sign);
178 |
179 | System.out.println(data.toString());
180 |
181 | this.channel.writeAndFlush(new TextWebSocketFrame(data.toString()));
182 | }
183 |
184 | /**
185 | * 取消委托
186 | * @param accessKey
187 | * @param secretKey
188 | * @param id
189 | * @param coin
190 | * @throws Exception
191 | */
192 | public void cancelOrder(long id,String coin) throws Exception{
193 | if(!isAlive())throw new ChannelException("the channel is not active");
194 |
195 | JSONObject data=new JSONObject();
196 | data.put("event", "addChannel");
197 | data.put("channel", coin.toLowerCase()+"_cancelorder");
198 | data.put("accesskey", accessKey);
199 | data.put("id", id);
200 |
201 | String secret = EncryDigestUtil.digest(secretKey);
202 | String sign = EncryDigestUtil.hmacSign(data.toString(), secret);
203 |
204 | data.put("sign", sign);
205 |
206 | System.out.println(data);
207 | this.channel.writeAndFlush(new TextWebSocketFrame(data.toString()));
208 | }
209 |
210 | /**
211 | * 获取委托买单或卖单
212 | * @param accessKey
213 | * @param secretKey
214 | * @param id
215 | * @param coin
216 | * @throws Exception
217 | */
218 | public void getOrder(long id,String coin) throws Exception{
219 | if(!isAlive())throw new ChannelException("the channel is not active");
220 |
221 | JSONObject data=new JSONObject();
222 | data.put("event", "addChannel");
223 | data.put("channel", coin.toLowerCase()+"_getorder");
224 | data.put("accesskey", accessKey);
225 | data.put("id", id);
226 |
227 | String secret = EncryDigestUtil.digest(secretKey);
228 | String sign = EncryDigestUtil.hmacSign(data.toString(), secret);
229 |
230 | data.put("sign", sign);
231 |
232 | System.out.println(data);
233 | this.channel.writeAndFlush(new TextWebSocketFrame(data.toString()));
234 | }
235 |
236 | /**
237 | * 获取多个委托买单或卖单,每次请求返回10条记录
238 | * @param accessKey
239 | * @param secretKey
240 | * @param pageIndex
241 | * @param coin
242 | * @throws Exception
243 | */
244 | public void getOrders(int pageIndex,int tradeType, String coin) throws Exception{
245 | if(!isAlive())throw new ChannelException("the channel is not active");
246 |
247 | JSONObject data=new JSONObject();
248 | data.put("event", "addChannel");
249 | data.put("channel", coin.toLowerCase()+"_getorders");
250 | data.put("accesskey", accessKey);
251 | data.put("tradeType", tradeType);
252 | data.put("pageIndex", pageIndex);
253 |
254 | String secret = EncryDigestUtil.digest(secretKey);
255 | String sign = EncryDigestUtil.hmacSign(data.toString(), secret);
256 |
257 | data.put("sign", sign);
258 |
259 | System.out.println(data);
260 | this.channel.writeAndFlush(new TextWebSocketFrame(data.toString()));
261 | }
262 |
263 | /**
264 | * (新)获取多个委托买单或卖单,每次请求返回pageSize<=100条记录
265 | * @param accessKey
266 | * @param secretKey
267 | * @param pageIndex
268 | * @param pageSize
269 | * @param coin
270 | * @throws Exception
271 | */
272 | public void getOrdersNew(int pageIndex,int pageSize,int tradeType,String coin) throws Exception{
273 | if(!isAlive())throw new ChannelException("the channel is not active");
274 |
275 | JSONObject data=new JSONObject();
276 | data.put("event", "addChannel");
277 | data.put("channel", coin.toLowerCase()+"_getordersnew");
278 | data.put("accesskey", accessKey);
279 | data.put("tradeType", tradeType);
280 | data.put("pageIndex", pageIndex);
281 | data.put("pageSize", pageSize);
282 |
283 | String secret = EncryDigestUtil.digest(secretKey);
284 | String sign = EncryDigestUtil.hmacSign(data.toString(), secret);
285 |
286 | data.put("sign", sign);
287 |
288 | System.out.println(data);
289 | this.channel.writeAndFlush(new TextWebSocketFrame(data.toString()));
290 | }
291 |
292 | /**
293 | * 与getOrdersNew的区别是取消tradeType字段过滤,可同时获取买单和卖单,每次请求返回pageSize<=100条记录
294 | * @param accessKey
295 | * @param secretKey
296 | * @param pageIndex
297 | * @param pageSize
298 | * @param coin
299 | * @throws Exception
300 | */
301 | public void getOrdersIgnoreTradeType(int pageIndex,int pageSize,String coin) throws Exception{
302 | if(!isAlive())throw new ChannelException("the channel is not active");
303 |
304 | JSONObject data=new JSONObject();
305 | data.put("event", "addChannel");
306 | data.put("channel", coin.toLowerCase()+"_getordersignoretradetype");
307 | data.put("accesskey", accessKey);
308 | data.put("pageIndex", pageIndex);
309 | data.put("pageSize", pageSize);
310 |
311 | String secret = EncryDigestUtil.digest(secretKey);
312 | System.out.println("getOrdersIgnoreTradeType:" + data.toString());
313 | String sign = EncryDigestUtil.hmacSign(data.toString(), secret);
314 |
315 | data.put("sign", sign);
316 |
317 | System.out.println(data);
318 | this.channel.writeAndFlush(new TextWebSocketFrame(data.toString()));
319 | }
320 |
321 | /**
322 | * 获取未成交或部份成交的买单和卖单,每次请求返回pageSize<=100条记录
323 | * @param accessKey
324 | * @param secretKey
325 | * @param pageIndex
326 | * @param pageSize
327 | * @param coin
328 | * @throws Exception
329 | */
330 | public void getUnfinishedOrdersIgnoreTradeType(int pageIndex,int pageSize,String coin) throws Exception{
331 | if(!isAlive())throw new ChannelException("the channel is not active");
332 |
333 | JSONObject data=new JSONObject();
334 | data.put("event", "addChannel");
335 | data.put("channel", coin.toLowerCase()+"_getunfinishedordersignoretradetype");
336 | data.put("accesskey", accessKey);
337 | data.put("pageIndex", pageIndex);
338 | data.put("pageSize", pageSize);
339 |
340 | String secret = EncryDigestUtil.digest(secretKey);
341 | String sign = EncryDigestUtil.hmacSign(data.toString(), secret);
342 |
343 | data.put("sign", sign);
344 |
345 | System.out.println(data);
346 | this.channel.writeAndFlush(new TextWebSocketFrame(data.toString()));
347 | }
348 |
349 | /**
350 | * 获取某个币种的充值地址
351 | * @param accessKey
352 | * @param coin
353 | * @throws Exception
354 | */
355 | public void getUserAddress(String coin) throws Exception{
356 | if(!isAlive())throw new ChannelException("the channel is not active");
357 |
358 | JSONObject data=new JSONObject();
359 | data.put("event", "addChannel");
360 | data.put("channel", coin.toLowerCase()+"_getuseraddress");
361 | data.put("accesskey", accessKey);
362 |
363 | String secret = EncryDigestUtil.digest(secretKey);
364 | String sign = EncryDigestUtil.hmacSign(data.toString(), secret);
365 |
366 | data.put("sign", sign);
367 |
368 | System.out.println(data);
369 | this.channel.writeAndFlush(new TextWebSocketFrame(data.toString()));
370 | }
371 |
372 | /**
373 | * 获取认证的提现地址
374 | * @param accessKey
375 | * @param coin
376 | * @throws Exception
377 | */
378 | public void getWithdrawAddress(String coin) throws Exception{
379 | if(!isAlive())throw new ChannelException("the channel is not active");
380 |
381 | JSONObject data=new JSONObject();
382 | data.put("event", "addChannel");
383 | data.put("channel", coin.toLowerCase()+"_getwithdrawaddress");
384 | data.put("accesskey", accessKey);
385 |
386 | String secret = EncryDigestUtil.digest(secretKey);
387 | String sign = EncryDigestUtil.hmacSign(data.toString(), secret);
388 |
389 | data.put("sign", sign);
390 |
391 | System.out.println(data);
392 | this.channel.writeAndFlush(new TextWebSocketFrame(data.toString()));
393 | }
394 |
395 | /**
396 | * 获取提现的记录
397 | * @param accessKey
398 | * @param coin
399 | * @throws Exception
400 | */
401 | public void getWithdrawRecord(String coin, int pageIndex, int pageSize) throws Exception{
402 | if(!isAlive())throw new ChannelException("the channel is not active");
403 |
404 | JSONObject data=new JSONObject();
405 | data.put("event", "addChannel");
406 | data.put("channel", coin.toLowerCase()+"_getwithdrawrecord");
407 | data.put("accesskey", accessKey);
408 | data.put("pageIndex", pageIndex);
409 | data.put("pageSize", pageSize);
410 |
411 | String secret = EncryDigestUtil.digest(secretKey);
412 | String sign = EncryDigestUtil.hmacSign(data.toString(), secret);
413 |
414 | data.put("sign", sign);
415 |
416 | System.out.println(data);
417 | this.channel.writeAndFlush(new TextWebSocketFrame(data.toString()));
418 | }
419 |
420 | /**
421 | * 取消提现
422 | * @param accessKey
423 | * @param coin
424 | * @throws Exception
425 | */
426 | public void cancelWithdraw(String coin, String downloadId) throws Exception{
427 | if(!isAlive())throw new ChannelException("the channel is not active");
428 |
429 | JSONObject data=new JSONObject();
430 | data.put("event", "addChannel");
431 | data.put("channel", coin.toLowerCase()+"_cancelwithdraw");
432 | data.put("accesskey", accessKey);
433 | data.put("downloadId", downloadId);
434 | data.put("safePwd", payPass);
435 |
436 | String secret = EncryDigestUtil.digest(secretKey);
437 | String sign = EncryDigestUtil.hmacSign(data.toString(), secret);
438 |
439 | data.put("sign", sign);
440 |
441 | System.out.println(data);
442 | this.channel.writeAndFlush(new TextWebSocketFrame(data.toString()));
443 | }
444 |
445 | /**
446 | * 提现
447 | * @param coin 币种
448 | * @param amount 提现金额
449 | * @param fees 提现矿工费
450 | * @param receiveAddr 提现地址
451 | * @throws Exception
452 | */
453 | public void withdraw(String coin, BigDecimal amount, BigDecimal fees, String receiveAddr) throws Exception{
454 | if(!isAlive())throw new ChannelException("the channel is not active");
455 |
456 | JSONObject data=new JSONObject();
457 | data.put("event", "addChannel");
458 | data.put("channel", coin.toLowerCase()+"_withdraw");
459 | data.put("accesskey", accessKey);
460 | data.put("amount", amount+"");
461 | data.put("fees", fees+"");
462 | data.put("receiveAddr", receiveAddr);
463 | data.put("safePwd", payPass);
464 |
465 | String secret = EncryDigestUtil.digest(secretKey);
466 | String sign = EncryDigestUtil.hmacSign(data.toString(), secret);
467 |
468 | data.put("sign", sign);
469 |
470 | System.out.println(data);
471 | this.channel.writeAndFlush(new TextWebSocketFrame(data.toString()));
472 | }
473 |
474 | /**
475 | * 获取用户资金信息
476 | * @param accessKey
477 | * @param secretKey
478 | */
479 | public void getAccountInfo(){
480 | JSONObject data=new JSONObject();
481 | data.put("event", "addChannel");
482 | data.put("channel","getaccountinfo");
483 | data.put("accesskey", accessKey);
484 | data.put("no", null);
485 |
486 | String secret = EncryDigestUtil.digest(secretKey);
487 | String sign = EncryDigestUtil.hmacSign(data.toString(), secret);
488 |
489 | data.put("sign", sign);
490 |
491 | System.out.println(data);
492 | this.channel.writeAndFlush(new TextWebSocketFrame(data.toString()));
493 | }
494 |
495 | /**
496 | * 注销客户端
497 | */
498 | public void cancel(){
499 | if(group!=null)group.shutdownGracefully();
500 | }
501 | /**
502 | * 判断客户端是否保持激活状态
503 | * @return
504 | */
505 | public boolean isAlive(){
506 | return this.channel!=null&&this.channel.isActive()?true:false;
507 | }
508 |
509 | /**
510 | * 测试帐号:
511 | * API访问密匙(Access Key): d31f15d5-xxxx-xxxx-xxxx-5ab5e6326b2e
512 | * API私有密匙(Secret Key): c1639fa5-xxxx-xxxx-xxxx-f42759830a19[仅显示一次]
513 | * @param args
514 | * @throws Exception
515 | */
516 | public void doTask() throws Exception {
517 | System.out.println("websocket通讯地址:" + serverUrl);
518 | WebSocketClient client=new WebSocketClient(System.getProperty ("url", serverUrl));
519 | try {
520 | client.connect();
521 | System.out.println("================================"+client.isAlive());
522 | // client.addChannel("ltcbtc_ticker");//通过
523 | // client.addChannel("ltcbtc_depth");//通过
524 | // client.addChannel("ltcbtc_trades");//通过
525 |
526 | // client.order( 0.019258, 1, "ethbtc", 0);
527 | // client.order( 0.009258, 1, "ltcbtc", 1);
528 | // client.cancelOrder(20151006160133624L , "ethbtc");
529 | // client.getOrder(20151006160133556L , "ethbtc");
530 | // client.getOrders(1,1 , "ethbtc");
531 | // client.getOrdersIgnoreTradeType(1,10 , "ethbtc");
532 | // client.getUnfinishedOrdersIgnoreTradeType(1,10 , "ethbtc");
533 | // client.getOrdersNew( 1,10, 1, "ethbtc");
534 | client.cancelWithdraw("ethbtc", "20160425916");
535 |
536 | // client.getAccountInfo();
537 | } catch (Exception e) {
538 | // TODO Auto-generated catch block
539 | e.printStackTrace();
540 | }
541 | // }
542 | }
543 |
544 | }
545 |
--------------------------------------------------------------------------------
/zb_netty_client_java/src/main/java/websocketx/client/WebSocketClientHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012 The Netty Project
3 | *
4 | * The Netty Project licenses this file to you under the Apache License,
5 | * version 2.0 (the "License"); you may not use this file except in compliance
6 | * with the License. You may obtain a copy of the License at:
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations
14 | * under the License.
15 | */
16 | //The MIT License
17 | //
18 | //Copyright (c) 2009 Carl Bystršm
19 | //
20 | //Permission is hereby granted, free of charge, to any person obtaining a copy
21 | //of this software and associated documentation files (the "Software"), to deal
22 | //in the Software without restriction, including without limitation the rights
23 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
24 | //copies of the Software, and to permit persons to whom the Software is
25 | //furnished to do so, subject to the following conditions:
26 | //
27 | //The above copyright notice and this permission notice shall be included in
28 | //all copies or substantial portions of the Software.
29 | //
30 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
36 | //THE SOFTWARE.
37 |
38 | package websocketx.client;
39 |
40 | import io.netty.channel.Channel;
41 | import io.netty.channel.ChannelFuture;
42 | import io.netty.channel.ChannelHandlerContext;
43 | import io.netty.channel.ChannelPromise;
44 | import io.netty.channel.SimpleChannelInboundHandler;
45 | import io.netty.handler.codec.http.FullHttpResponse;
46 | import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
47 | import io.netty.handler.codec.http.websocketx.PongWebSocketFrame;
48 | import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
49 | import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
50 | import io.netty.handler.codec.http.websocketx.WebSocketFrame;
51 | import io.netty.util.CharsetUtil;
52 |
53 | public abstract class WebSocketClientHandler extends SimpleChannelInboundHandler