如何签署OKEx API请求?

2024-05-13 02:45:35 发布

您现在位置:Python中文网/ 问答频道 /正文

在尝试对OKEx API进行身份验证时,我不断收到一个无效的签名错误,但我无法理解为什么我的签名无法通过。再看一眼可能有用吗

以下是OKEx API文档中的一些上下文:

*---签名消息--

  1. OK-ACCESS-SIGN标头生成如下:创建预灰烬 时间戳+方法+请求路径+正文的字符串(其中+ 表示字符串连接)准备预灰化的秘密签名 使用HMAC SHA256将签名编码为 Base64格式示例: sign=CryptoJS.enc.Base64.stringify(CryptoJS.HmacSHA256(timestamp + 'GET' + '/users/self/verify', SecretKey))

  2. 时间戳值与OK-ACCESS-timestamp报头相同,精度为纳秒

  3. 请求方法应该是大写的,即GET和POST

  4. requestPath是请求端点的路径。例子: /orders?before=2&limit=30

  5. 正文引用请求正文的字符串。如果没有请求主体,则可以省略它 (通常是GET请求的情况)。例子: {"product_id":"BTC-USD-0309","order_id":"377454671037440"}

  6. 创建APIKey时会生成SecretKey。例子: 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()

Tags: keyimportjsongetsecretaccesstimerequest
2条回答

问题是,在计算OK-ACCESS-SIGNOK-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)

还要注意的是,目前在{}中,您询问OKEx的服务器现在几点了。但是,如果您的计算机的本地时间是合理正确的(例如,您可以在https://time.is检查),您可以避免执行HTTP请求,而只使用本地时间

import datetime

def get_time():
    now = datetime.datetime.utcnow()
    t = now.isoformat("T", "milliseconds")
    return t + "Z"

这是我对OKEx API的签名请求的解决方案。 感谢zoe-fleischerrok-povsic


APIKEY = "xxxxx"
APISECRET = "xxxx"
PASS = "xxxx"
BASE_URL = 'https://aws.okex.com'

def send_signed_request(http_method, url_path, payload={}):
    '''
    See https://stackoverflow.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={})

相关问题 更多 >