forked from LiChenYang23/REST-GO-demo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Utils.go
264 lines (217 loc) · 7.27 KB
/
Utils.go
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
package utils
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/url"
"sort"
"strings"
"time"
"github.com/shaodan/go-huobi/config"
)
// Http Get请求基础函数, 通过封装Go语言Http请求, 支持火币网REST API的HTTP Get请求
// strUrl: 请求的URL
// strParams: string类型的请求参数, user=lxz&pwd=lxz
// return: 请求结果
func HttpGetRequest(strUrl string, mapParams map[string]string) string {
httpClient := &http.Client{}
var strRequestUrl string
if nil == mapParams {
strRequestUrl = strUrl
} else {
strParams := Map2UrlQuery(mapParams)
strRequestUrl = strUrl + "?" + strParams
}
// 构建Request, 并且按官方要求添加Http Header
request, err := http.NewRequest("GET", strRequestUrl, nil)
if nil != err {
return err.Error()
}
request.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36")
// 发出请求
response, err := httpClient.Do(request)
if nil != err {
return err.Error()
}
defer response.Body.Close()
// 解析响应内容
body, err := ioutil.ReadAll(response.Body)
if nil != err {
return err.Error()
}
return string(body)
}
// Http POST请求基础函数, 通过封装Go语言Http请求, 支持火币网REST API的HTTP POST请求
// strUrl: 请求的URL
// mapParams: map类型的请求参数
// return: 请求结果
func HttpPostRequest(strUrl string, mapParams map[string]string) string {
httpClient := &http.Client{}
jsonParams := ""
if nil != mapParams {
bytesParams, _ := json.Marshal(mapParams)
jsonParams = string(bytesParams)
}
request, err := http.NewRequest("POST", strUrl, strings.NewReader(jsonParams))
if nil != err {
return err.Error()
}
request.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36")
request.Header.Add("Content-Type", "application/json")
request.Header.Add("Accept-Language", "zh-cn")
response, err := httpClient.Do(request)
if nil != err {
return err.Error()
}
defer response.Body.Close()
body, err := ioutil.ReadAll(response.Body)
if nil != err {
return err.Error()
}
return string(body)
}
// 进行签名后的HTTP GET请求, 参考官方Python Demo写的
// mapParams: map类型的请求参数, key:value
// strRequest: API路由路径
// return: 请求结果
func ApiKeyGet(cfg *config.HuobiRestConfig, mapParams map[string]string, strRequestPath string) string {
if !cfg.Logon {
log.Fatal("Please config HuobiAPI AccessKey and SecretKey")
}
strMethod := "GET"
timestamp := time.Now().UTC().Format("2006-01-02T15:04:05")
mapParams["AccessKeyId"] = cfg.AccessKey
mapParams["SignatureMethod"] = "HmacSHA256"
mapParams["SignatureVersion"] = "2"
mapParams["Timestamp"] = timestamp
hostName := cfg.HostName
mapParams["Signature"] = CreateSign(mapParams, strMethod, hostName, strRequestPath, cfg.SecretKey)
if cfg.EnablePrivateSignature == true {
privateSignature, err := CreatePrivateSignByJWT(cfg.PrivateKeyPrime256, mapParams["Signature"])
if nil == err {
mapParams["PrivateSignature"] = privateSignature
} else {
fmt.Println("signed error: ", err)
}
}
strUrl := cfg.TradeUrl + strRequestPath
return HttpGetRequest(strUrl, MapValueEncodeURI(mapParams))
}
// 进行签名后的HTTP POST请求, 参考官方Python Demo写的
// mapParams: map类型的请求参数, key:value
// strRequest: API路由路径
// return: 请求结果
func ApiKeyPost(cfg *config.HuobiRestConfig, mapParams map[string]string, strRequestPath string) string {
if !cfg.Logon {
log.Fatal("Please config HuobiAPI AccessKey and SecretKey")
}
strMethod := "POST"
timestamp := time.Now().UTC().Format("2006-01-02T15:04:05")
mapParams2Sign := make(map[string]string)
mapParams2Sign["AccessKeyId"] = cfg.AccessKey
mapParams2Sign["SignatureMethod"] = "HmacSHA256"
mapParams2Sign["SignatureVersion"] = "2"
mapParams2Sign["Timestamp"] = timestamp
hostName := cfg.HostName
mapParams2Sign["Signature"] = CreateSign(mapParams2Sign, strMethod, hostName, strRequestPath, cfg.SecretKey)
if cfg.EnablePrivateSignature == true {
privateSignature, err := CreatePrivateSignByJWT(cfg.PrivateKeyPrime256, mapParams2Sign["Signature"])
if nil == err {
mapParams2Sign["PrivateSignature"] = privateSignature
} else {
fmt.Println("signed error:", err)
}
}
strUrl := cfg.TradeUrl + strRequestPath + "?" + Map2UrlQuery(MapValueEncodeURI(mapParams2Sign))
return HttpPostRequest(strUrl, mapParams)
}
// 构造签名
// mapParams: 送进来参与签名的参数, Map类型
// strMethod: 请求的方法 GET, POST......
// strHostUrl: 请求的主机
// strRequestPath: 请求的路由路径
// strSecretKey: 进行签名的密钥
func CreateSign(mapParams map[string]string, strMethod, strHostUrl, strRequestPath, strSecretKey string) string {
// 参数处理, 按API要求, 参数名应按ASCII码进行排序(使用UTF-8编码, 其进行URI编码, 16进制字符必须大写)
mapCloned := make(map[string]string)
for key, value := range mapParams {
mapCloned[key] = url.QueryEscape(value)
}
strParams := Map2UrlQueryBySort(mapCloned)
strPayload := strMethod + "\n" + strHostUrl + "\n" + strRequestPath + "\n" + strParams
return ComputeHmac256(strPayload, strSecretKey)
}
func CreatePrivateSignByJWT(prime256, sign string) (string, error) {
return SignByJWT(prime256, sign)
}
// 对Map按着ASCII码进行排序
// mapValue: 需要进行排序的map
// return: 排序后的map
func MapSortByKey(mapValue map[string]string) map[string]string {
var keys []string
for key := range mapValue {
keys = append(keys, key)
}
sort.Strings(keys)
mapReturn := make(map[string]string)
for _, key := range keys {
mapReturn[key] = mapValue[key]
}
return mapReturn
}
// 对Map的值进行URI编码
// mapParams: 需要进行URI编码的map
// return: 编码后的map
func MapValueEncodeURI(mapValue map[string]string) map[string]string {
for key, value := range mapValue {
valueEncodeURI := url.QueryEscape(value)
mapValue[key] = valueEncodeURI
}
return mapValue
}
// 将map格式的请求参数转换为字符串格式的
// mapParams: map格式的参数键值对
// return: 查询字符串
func Map2UrlQuery(mapParams map[string]string) string {
var strParams string
for key, value := range mapParams {
strParams += key + "=" + value + "&"
}
if 0 < len(strParams) {
strParams = string([]rune(strParams)[:len(strParams)-1])
}
return strParams
}
// 将map格式的请求参数转换为字符串格式的,并按照Map的key升序排列
// mapParams: map格式的参数键值对
// return: 查询字符串
func Map2UrlQueryBySort(mapParams map[string]string) string {
var keys []string
for key := range mapParams {
keys = append(keys, key)
}
sort.Strings(keys)
var strParams string
for _, key := range keys {
strParams += key + "=" + mapParams[key] + "&"
}
if 0 < len(strParams) {
strParams = string([]rune(strParams)[:len(strParams)-1])
}
return strParams
}
// HMAC SHA256加密
// strMessage: 需要加密的信息
// strSecret: 密钥
// return: BASE64编码的密文
func ComputeHmac256(strMessage string, strSecret string) string {
key := []byte(strSecret)
h := hmac.New(sha256.New, key)
h.Write([]byte(strMessage))
return base64.StdEncoding.EncodeToString(h.Sum(nil))
}