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'
验证修复后的完整流程
- 确认实例变量引用正确,避免全局变量混淆
- 请求体仅在签名生成和发送请求时各做一次JSON编码(签名时由
signature方法处理,发送时由requests.post的json参数自动处理) - 签名结果转为字符串类型
- 确保本地时间与OKEx服务器时间偏差在5秒内
内容的提问来源于stack exchange,提问作者Kacper
相关产品推荐
相关产品推荐

