You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OKEx API POST请求报'Invalid Sign'错误(GET请求正常)

排查OKEx API POST请求签名错误(50113)的原因及修复

核心问题分析及修复步骤

1. 错误引用全局变量而非实例变量

在get_header方法中,直接使用了APIKEY、APISECRET、PASS全局变量,但类初始化时已将这些值存入实例属性self.apikey、self.apisecret、self.password。这会导致签名使用的密钥与实际API密钥不匹配,直接引发签名无效。

修复代码:

def get_header(self, request='GET', endpoint='', body: dict = dict()):
    cur_time = self.get_time()
    header = dict()
    header['CONTENT-TYPE'] = 'application/json'
    header['OK-ACCESS-KEY'] = self.apikey  # 改为实例属性
    header['OK-ACCESS-SIGN'] = self.signature(cur_time, request, endpoint, body, self.apisecret)  # 改为实例属性
    header['OK-ACCESS-TIMESTAMP'] = str(cur_time)
    header['OK-ACCESS-PASSPHRASE'] = self.password  # 改为实例属性
    return header

2. 请求体(body)被双重JSON编码

在place_market_order方法中,你提前将字典转为JSON字符串传给get_header,但signature方法里又会对传入的body执行json.dumps(body),导致body被两次编码,生成的签名与服务器预期不一致。

修复代码:

def place_market_order(self, pair, side, amount, tdMode='cash'):
    endpoint = '/api/v5/trade/order'
    url = self.baseURL + endpoint
    request = 'POST'
    body = {
        "instId": pair,
        "tdMode": tdMode,
        "side": side,
        "ordType": "market",
        "sz": str(amount)
    }

    # 直接传字典给get_header,不提前转JSON
    header = self.get_header(endpoint=endpoint, request=request, body=body)
    # 发送请求时用requests的json参数自动处理编码
    response = requests.post(url=url, headers=header, json=body)
    return response

3. 签名结果未转为字符串

signature方法返回的base64.b64encode(output)是bytes对象,而HTTP请求头要求字符串类型,直接传入会导致签名格式错误。

修复代码:

@staticmethod
def signature(timestamp, method, request_path, body, secret_key):
    if str(body) == '{}' or str(body) == 'None':
        body = ''
    else:
        body = json.dumps(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')
    output = mac.digest()
    return base64.b64encode(output).decode('utf-8')  # 转为字符串

4. 额外验证:确保时间同步

OKEx API对时间戳要求严格,若本地时间与服务器时间偏差超过5秒,也会触发签名错误。可改用OKEx提供的服务器时间接口获取准确时间:

@staticmethod
def get_time():
    # 调用OKEx公共时间接口获取精准时间
    response = requests.get('https://www.okex.com/api/v5/public/time')
    return response.json()['data'][0]['ts'][:-3] + 'Z'

验证修复后的完整流程

  1. 确认实例变量引用正确,避免全局变量混淆
  2. 请求体仅在签名生成和发送请求时各做一次JSON编码(签名时由signature方法处理,发送时由requests.post的json参数自动处理)
  3. 签名结果转为字符串类型
  4. 确保本地时间与OKEx服务器时间偏差在5秒内

内容的提问来源于stack exchange,提问作者Kacper

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 21:25:21