如何签署 OKEx API 请求?
Posted
技术标签:
【中文标题】如何签署 OKEx API 请求?【英文标题】:How to sign an OKEx API request? 【发布时间】:2021-06-03 18:28:35 【问题描述】:我在尝试向 OKEx API 进行身份验证时不断收到无效签名错误,但我无法看到为什么我的签名没有通过。另一只眼睛可能有帮助吗?
以下是 OKEx API 文档中的一些上下文:
*---签名消息---
OK-ACCESS-SIGN 标头生成如下:创建一个 prehash
时间戳字符串 + 方法 + requestPath + 正文(其中 +
表示字符串连接)准备 Secret 签名 prehash
使用 HMAC SHA256 将签名编码为 Secret 的字符串
Base64 格式示例:
sign=CryptoJS.enc.Base64.stringify(CryptoJS.HmacSHA256(timestamp + 'GET' + '/users/self/verify', SecretKey))
时间戳值与 OK-ACCESS-TIMESTAMP 标头相同,精度为纳秒。
请求方法应为大写,即 GET 和 POST。
requestPath 是请求端点的路径。例子:
/orders?before=2&limit=30
body 指的是请求体的String。如果没有请求体可以省略
(通常是 GET 请求的情况)。例子:
"product_id":"BTC-USD-0309","order_id":"377454671037440"
SecretKey 是在您创建 APIKey 时生成的。例子:
22582BD0CFF14C41EDBF1AB98506286D*
import hmac
import base64
import requests
import json
from Secrets import okex_key
from Secrets import okex_secret
from Secrets import okex_pass
#get time
def get_time():
urltime= 'https://www.okex.com/api/general/v3/time'
response=requests.get(urltime)
time=response.json()
time=time['iso']
return time
# signature
def signature(timestamp, method, request_path, body,secret_key):
if str(body) == '' or str(body) == 'None':
body = ''
message = str(timestamp) + str.upper(method) + request_path + str(body)
mac = hmac.new(bytes(secret_key, encoding='utf8'), bytes(message, encoding='utf-8'), digestmod='sha256')
d = mac.digest()
return base64.b64encode(d)
# set request header
def get_header():
body=
request= 'GET'
endpoint= '/api/spot/v3/accounts'
header = dict()
header['CONTENT-TYPE'] = 'application/json'
header['OK-ACCESS-KEY'] = okex_key
header['OK-ACCESS-SIGN'] = signature(get_time(), request, endpoint , body, okex_secret)
header['OK-ACCESS-TIMESTAMP'] = str(get_time())
header['OK-ACCESS-PASSPHRASE'] = okex_pass
return header
url = 'http://www.okex.com/api/spot/v3/accounts'
header = get_header()
response= requests.get(url, headers=header)
response.json()
【问题讨论】:
【参考方案1】:问题是您在计算OK-ACCESS-SIGN
和OK-ACCESS-TIMESTAMP
的值时给出了两个不同的时间值。将get_time()
放入一个变量中并在两个地方都使用它。
current_time = get_time()
header['OK-ACCESS-SIGN'] = signature(current_time, request, endpoint , body, okex_secret)
header['OK-ACCESS-TIMESTAMP'] = str(current_time)
另外请注意,目前,在get_time
,您询问 OKEx 的服务器现在几点。但是,如果您计算机的本地时间相当正确(例如,您可以在 https://time.is 检查),您可以避免执行该 HTTP 请求而只使用本地时间。
import datetime
def get_time():
now = datetime.datetime.utcnow()
t = now.isoformat("T", "milliseconds")
return t + "Z"
【讨论】:
【参考方案2】:这是我为 OKEx API 签名请求的解决方案。 感谢zoe-fleischer 和rok-povsic。
APIKEY = "xxxxx"
APISECRET = "xxxx"
PASS = "xxxx"
BASE_URL = 'https://aws.okex.com'
def send_signed_request(http_method, url_path, payload=):
'''
See https://***.com/questions/66486374/how-to-sign-an-okex-api-request
'''
def get_time():
return dt.datetime.utcnow().isoformat()[:-3]+'Z'
def signature(timestamp, method, request_path, body, secret_key):
if str(body) == '' or str(body) == 'None':
body = ''
message = str(timestamp) + str.upper(method) + request_path + str(body)
mac = hmac.new(bytes(secret_key, encoding='utf8'), bytes(message, encoding='utf-8'), digestmod='sha256')
d = mac.digest()
return base64.b64encode(d)
# set request header
def get_header(request='GET', endpoint='', body:dict=dict()):
cur_time = get_time()
header = dict()
header['CONTENT-TYPE'] = 'application/json'
header['OK-ACCESS-KEY'] = APIKEY
header['OK-ACCESS-SIGN'] = signature(cur_time, request, endpoint , body, APISECRET)
header['OK-ACCESS-TIMESTAMP'] = str(cur_time)
header['OK-ACCESS-PASSPHRASE'] = PASS
return header
url = BASE_URL + url_path
header = get_header(http_method, url_path, payload)
print(url)
print(header)
response= requests.get(url, headers=header)
response.json()
return response.json()
send_signed_request("GET", "/api/v5/account/balance", payload=)
【讨论】:
【参考方案3】:我正在 Postman 中执行 REST API,它对我来说运行良好。以下是步骤。 (您需要使用来自 okex time api 的时间戳)
获取:https://www.okex.com/api/v5/account/balance
标题:
OK-ACCESS-KEY:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (API_KEY)
OK-ACCESS-SIGN:sign
OK-ACCESS-TIMESTAMP:timestamp
OK-ACCESS-PASSPHRASE:YOUR_PASSPHRASE
Content-Type:application/json
预请求脚本
pm.sendRequest('https://www.okex.com/api/general/v3/time', function (err, res)
console.log('Response_ISO: '+res.json().iso);
pm.expect(err).to.not.be.ok;
var timestamp = res.json().iso;
var sign = CryptoJS.enc.Base64.stringify(CryptoJS.HmacSHA256(timestamp + 'GET' + '/api/v5/account/balance', 'YOUR_SECRET_KEY'));
console.log(sign);
postman.setEnvironmentVariable('timestamp',timestamp)
postman.setGlobalVariable('timestamp',timestamp)
postman.setEnvironmentVariable('sign',sign)
postman.setGlobalVariable('sign',sign)
);
【讨论】:
以上是关于如何签署 OKEx API 请求?的主要内容,如果未能解决你的问题,请参考以下文章
Google Cloud Api Gateway 是不是提供请求签名和验证 sdk,例如使用 Signature 4 签署 AWS API Gateway 请求?
验证/签署对我的 API 的请求来自我的应用程序并且没有被欺骗(React Native)
如何在 Swift 中固定 certificate.pem 和 private_key.pem 文件以签署 http 请求