github.com/frankrap/okex-api@v1.0.4/utils.go (about) 1 package okex 2 3 /* 4 utils 5 @author Tony Tian 6 @date 2018-03-17 7 @version 1.0.0 8 */ 9 10 import ( 11 "bytes" 12 "compress/flate" 13 "crypto/hmac" 14 "crypto/md5" 15 "crypto/sha256" 16 "encoding/base64" 17 "errors" 18 "fmt" 19 "io/ioutil" 20 "net/http" 21 "net/url" 22 "sort" 23 "strconv" 24 "strings" 25 "time" 26 ) 27 28 /* 29 signing a message 30 using: hmac sha256 + base64 31 eg: 32 message = Pre_hash function comment 33 secretKey = E65791902180E9EF4510DB6A77F6EBAE 34 35 return signed string = TO6uwdqz+31SIPkd4I+9NiZGmVH74dXi+Fd5X0EzzSQ= 36 */ 37 func HmacSha256Base64Signer(message string, secretKey string) (string, error) { 38 mac := hmac.New(sha256.New, []byte(secretKey)) 39 _, err := mac.Write([]byte(message)) 40 if err != nil { 41 return "", err 42 } 43 return base64.StdEncoding.EncodeToString(mac.Sum(nil)), nil 44 } 45 46 /* 47 the pre hash string 48 eg: 49 timestamp = 2018-03-08T10:59:25.789Z 50 method = POST 51 request_path = /orders?before=2&limit=30 52 body = {"product_id":"BTC-USD-0309","order_id":"377454671037440"} 53 54 return pre hash string = 2018-03-08T10:59:25.789ZPOST/orders?before=2&limit=30{"product_id":"BTC-USD-0309","order_id":"377454671037440"} 55 */ 56 func PreHashString(timestamp string, method string, requestPath string, body string) string { 57 return timestamp + strings.ToUpper(method) + requestPath + body 58 } 59 60 /* 61 md5 sign 62 */ 63 func Md5Signer(message string) string { 64 data := []byte(message) 65 has := md5.Sum(data) 66 return fmt.Sprintf("%x", has) 67 } 68 69 /* 70 int convert string 71 */ 72 func Int2String(arg int) string { 73 return strconv.Itoa(arg) 74 } 75 76 /* 77 int64 convert string 78 */ 79 func Int642String(arg int64) string { 80 return strconv.FormatInt(int64(arg), 10) 81 } 82 83 /* 84 json string convert struct 85 */ 86 func JsonString2Struct(jsonString string, result interface{}) error { 87 jsonBytes := []byte(jsonString) 88 err := json.Unmarshal(jsonBytes, result) 89 return err 90 } 91 92 /* 93 json byte array convert struct 94 */ 95 func JsonBytes2Struct(jsonBytes []byte, result interface{}) error { 96 err := json.Unmarshal(jsonBytes, result) 97 return err 98 } 99 100 /* 101 struct convert json string 102 */ 103 func Struct2JsonString(structt interface{}) (jsonString string, err error) { 104 data, err := json.Marshal(structt) 105 if err != nil { 106 return "", err 107 } 108 return string(data), nil 109 } 110 111 /* 112 ternary operator replace language: a == b ? c : d 113 */ 114 func T3O(condition bool, trueValue, falseValue interface{}) interface{} { 115 if condition { 116 return trueValue 117 } 118 return falseValue 119 } 120 121 /* 122 Get a epoch time 123 eg: 1521221737.376 124 */ 125 func EpochTime() string { 126 millisecond := time.Now().UnixNano() / 1000000 127 epoch := strconv.Itoa(int(millisecond)) 128 epochBytes := []byte(epoch) 129 epoch = string(epochBytes[:10]) + "." + string(epochBytes[10:]) 130 return epoch 131 } 132 133 /* 134 Get a iso time 135 eg: 2018-03-16T18:02:48.284Z 136 */ 137 func IsoTime() string { 138 utcTime := time.Now().UTC() 139 iso := utcTime.String() 140 isoBytes := []byte(iso) 141 iso = string(isoBytes[:10]) + "T" + string(isoBytes[11:23]) + "Z" 142 return iso 143 } 144 145 /* 146 Get utc +8 -- 1540365300000 -> 2018-10-24 15:15:00 +0800 CST 147 */ 148 func LongTimeToUTC8(longTime int64) time.Time { 149 timeString := Int64ToString(longTime) 150 sec := timeString[0:10] 151 nsec := timeString[10:len(timeString)] 152 return time.Unix(StringToInt64(sec), StringToInt64(nsec)) 153 } 154 155 /* 156 1540365300000 -> 2018-10-24 15:15:00 157 */ 158 func LongTimeToUTC8Format(longTime int64) string { 159 return LongTimeToUTC8(longTime).Format("2006-01-02 15:04:05") 160 } 161 162 /* 163 iso time change to time.Time 164 eg: "2018-11-18T16:51:55.933Z" -> 2018-11-18 16:51:55.000000933 +0000 UTC 165 */ 166 func IsoToTime(iso string) (time.Time, error) { 167 nilTime := time.Now() 168 if iso == "" { 169 return nilTime, errors.New("illegal parameter") 170 } 171 // "2018-03-18T06:51:05.933Z" 172 isoBytes := []byte(iso) 173 year, err := strconv.Atoi(string(isoBytes[0:4])) 174 if err != nil { 175 return nilTime, errors.New("illegal year") 176 } 177 month, err := strconv.Atoi(string(isoBytes[5:7])) 178 if err != nil { 179 return nilTime, errors.New("illegal month") 180 } 181 day, err := strconv.Atoi(string(isoBytes[8:10])) 182 if err != nil { 183 return nilTime, errors.New("illegal day") 184 } 185 hour, err := strconv.Atoi(string(isoBytes[11:13])) 186 if err != nil { 187 return nilTime, errors.New("illegal hour") 188 } 189 min, err := strconv.Atoi(string(isoBytes[14:16])) 190 if err != nil { 191 return nilTime, errors.New("illegal min") 192 } 193 sec, err := strconv.Atoi(string(isoBytes[17:19])) 194 if err != nil { 195 return nilTime, errors.New("illegal sec") 196 } 197 nsec, err := strconv.Atoi(string(isoBytes[20 : len(isoBytes)-1])) 198 if err != nil { 199 return nilTime, errors.New("illegal nsec") 200 } 201 return time.Date(year, time.Month(month), day, hour, min, sec, nsec, time.UTC), nil 202 } 203 204 /* 205 Get a http request body is a json string and a byte array. 206 */ 207 func ParseRequestParams(params interface{}) (string, *bytes.Reader, error) { 208 if params == nil { 209 return "", nil, errors.New("illegal parameter") 210 } 211 data, err := json.Marshal(params) 212 if err != nil { 213 return "", nil, errors.New("json convert string error") 214 } 215 jsonBody := string(data) 216 binBody := bytes.NewReader(data) 217 return jsonBody, binBody, nil 218 } 219 220 /* 221 Set http request headers: 222 Accept: application/json 223 Content-Type: application/json; charset=UTF-8 (default) 224 Cookie: locale=en_US (English) 225 OK-ACCESS-KEY: (Your setting) 226 OK-ACCESS-SIGN: (Use your setting, auto sign and add) 227 OK-ACCESS-TIMESTAMP: (Auto add) 228 OK-ACCESS-PASSPHRASE: Your setting 229 */ 230 func Headers(request *http.Request, config Config, timestamp string, sign string) { 231 request.Header.Add(ACCEPT, APPLICATION_JSON) 232 request.Header.Add(CONTENT_TYPE, APPLICATION_JSON_UTF8) 233 request.Header.Add(COOKIE, LOCALE+config.I18n) 234 request.Header.Add(OK_ACCESS_KEY, config.ApiKey) 235 request.Header.Add(OK_ACCESS_SIGN, sign) 236 request.Header.Add(OK_ACCESS_TIMESTAMP, timestamp) 237 request.Header.Add(OK_ACCESS_PASSPHRASE, config.Passphrase) 238 } 239 240 /* 241 Get a new map.eg: {string:string} 242 */ 243 func NewParams() map[string]string { 244 return make(map[string]string) 245 } 246 247 /* 248 build http get request params, and order 249 eg: 250 params := make(map[string]string) 251 params["bb"] = "222" 252 params["aa"] = "111" 253 params["cc"] = "333" 254 return string: eg: aa=111&bb=222&cc=333 255 */ 256 func BuildOrderParams(params map[string]string) string { 257 var keys []string 258 for k := range params { 259 keys = append(keys, k) 260 } 261 sort.Strings(keys) 262 urlParams := url.Values{} 263 for k := range params { 264 urlParams.Add(k, params[k]) 265 } 266 return urlParams.Encode() 267 } 268 269 /* 270 Get api requestPath + requestParams 271 params := NewParams() 272 params["depth"] = "200" 273 params["conflated"] = "0" 274 url := BuildParams("/api/futures/v3/products/BTC-USD-0310/book", params) 275 return eg:/api/futures/v3/products/BTC-USD-0310/book?conflated=0&depth=200 276 */ 277 func BuildParams(requestPath string, params map[string]string) string { 278 urlParams := url.Values{} 279 for k := range params { 280 urlParams.Add(k, params[k]) 281 } 282 return requestPath + "?" + urlParams.Encode() 283 } 284 285 /* 286 Get api v1 requestPath + requestParams 287 params := okex.NewParams() 288 params["symbol"] = "btc_usd" 289 params["contract_type"] = "this_week" 290 params["status"] = "1" 291 requestPath := "/api/v1/future_explosive.do" 292 return eg: /api/v1/future_explosive.do?api_key=88af5759-61f2-47e9-b2e9-17ce3a390488&contract_type=this_week&status=1&symbol=btc_usd&sign=966ACD0DE5F729BC9C9C03D92ABBEB68 293 */ 294 func BuildAPIV1Params(requestPath string, params map[string]string, config Config) string { 295 params["api_key"] = config.ApiKey 296 sortParams := BuildOrderParams(params) 297 preMd5Params := sortParams + "&secret_key=" + config.SecretKey 298 md5Sign := Md5Signer(preMd5Params) 299 requestParams := sortParams + "&sign=" + strings.ToUpper(md5Sign) 300 return requestPath + "?" + requestParams 301 } 302 303 func GetResponseDataJsonString(response *http.Response) string { 304 return response.Header.Get(ResultDataJsonString) 305 } 306 func GetResponsePageJsonString(response *http.Response) string { 307 return response.Header.Get(ResultPageJsonString) 308 } 309 310 /* 311 ternary operator biz extension 312 */ 313 func T3Ox(err error, value interface{}) (interface{}, error) { 314 if err != nil { 315 return nil, err 316 } 317 return value, nil 318 } 319 320 /* 321 return decimalism string 9223372036854775807 -> "9223372036854775807" 322 */ 323 func Int64ToString(arg int64) string { 324 return strconv.FormatInt(arg, 10) 325 } 326 327 func IntToString(arg int) string { 328 return strconv.Itoa(arg) 329 } 330 331 func StringToInt64(arg string) int64 { 332 value, err := strconv.ParseInt(arg, 10, 64) 333 if err != nil { 334 return 0 335 } else { 336 return value 337 } 338 } 339 340 func StringToInt(arg string) int { 341 value, err := strconv.Atoi(arg) 342 if err != nil { 343 return 0 344 } else { 345 return value 346 } 347 } 348 349 /* 350 call fmt.Println(...) 351 */ 352 func FmtPrintln(flag string, info interface{}) { 353 fmt.Print(flag) 354 if info != nil { 355 jsonString, err := Struct2JsonString(info) 356 if err != nil { 357 fmt.Println(err) 358 } 359 fmt.Println(jsonString) 360 } else { 361 fmt.Println("{}") 362 } 363 } 364 365 func GetInstrumentIdUri(uri, instrumentId string) string { 366 return strings.Replace(uri, "{instrument_id}", instrumentId, -1) 367 } 368 369 func GetCurrencyUri(uri, currency string) string { 370 return strings.Replace(uri, "{currency}", currency, -1) 371 } 372 373 func GetInstrumentIdOrdersUri(uri, instrumentId string, orderId string) string { 374 uri = strings.Replace(uri, "{instrument_id}", instrumentId, -1) 375 uri = strings.Replace(uri, "{order_id}", orderId, -1) 376 return uri 377 } 378 379 func GetUnderlyingUri(uri, underlying string) string { 380 return strings.Replace(uri, "{underlying}", underlying, -1) 381 } 382 383 func FlateUnCompress(data []byte) ([]byte, error) { 384 return ioutil.ReadAll(flate.NewReader(bytes.NewReader(data))) 385 } 386 387 // "socks5://127.0.0.1:1080" 388 func ParseProxy(proxyURL string) (res func(*http.Request) (*url.URL, error), err error) { 389 var purl *url.URL 390 purl, err = url.Parse(proxyURL) 391 if err != nil { 392 return 393 } 394 res = http.ProxyURL(purl) 395 return 396 }