Bitget Restful API POST请求签名错误问题求助
Bitget期货API POST请求签名错误排查求助
参考Stack Overflow相关文章后,已成功实现Bitget期货Rest API的GET请求,但按官方文档配置POST请求签名时,始终收到error sign signature错误。
官方签名规则
- 当queryString为空时,签名内容为:
timestamp + method.toUpperCase() + requestPath + body- 当queryString不为空时,签名内容为:
timestamp + method.toUpperCase() + requestPath + "?" + queryString + body
我的代码
def parse_params_to_str(params): url = '?' for key, value in params.items(): url = url + str(key) + '=' + str(value) + '&' return url[0:-1] def get_signature(message): mac = hmac.new(bytes(api_sec, encoding='utf8'), bytes( message, encoding='utf-8'), digestmod='sha256') d = mac.digest() return base64.b64encode(d) def get(request_path, body, query, method): std_time = time.time() * 1000 new_time = int(std_time) if str(body) == '{}' or str(body) == 'None': converted_body = '' else: converted_body = json.dumps(body) message = str(new_time) + method + request_path + \ parse_params_to_str(query) + converted_body print(message) headers = {"ACCESS-KEY": api_key, "ACCESS-SIGN": get_signature(message), "ACCESS-TIMESTAMP": str(new_time), "ACCESS-PASSPHRASE": api_passphrase, "Content-Type": "application/json", "Locale": "en-US" } if method == "GET": request_resp = requests.get( (api_url + request_path), headers=headers, params=query) return request_resp def post(request_path, body, method): std_time = time.time() * 1000 new_time = int(std_time) if str(body) == '{}' or str(body) == 'None': converted_body = '' else: converted_body = json.dumps(body) message = str(new_time) +method + request_path + converted_body print(message) headers = {"ACCESS-KEY": api_key, "ACCESS-SIGN": get_signature(message), "ACCESS-TIMESTAMP": str(new_time), "ACCESS-PASSPHRASE": api_passphrase, "Content-Type": "application/json", "Locale": "en-US" } if method == "POST": request_resp = requests.post( (api_url + request_path), headers=headers, params=body) return request_resp query = { "symbol": symbol, "marginCoin": "USDT" } order_resp = get("/api/mix/v1/account/account", None, query, "GET") print(order_resp.json()) para= {"symbol": "BTCUSDT_UMCBL", "marginCoin": "USDT", "openPrice": "23189.5", "leverage": "20", "openAmount": "5000"} test = post("/api/mix/v1/account/open-count", para, "POST") print(test.json())
问题原因及解决方法
Method未转大写
官方要求签名时必须使用大写的请求方法(如POST),但当前代码中拼接签名字符串时直接使用了原method变量,未转大写。
修复:将签名字符串中的method替换为method.upper(),GET和POST方法都需要修改。POST请求参数传递方式错误
代码中POST请求使用params=body将参数放在URL中,但Bitget的POST接口要求参数放在请求体(JSON格式)中,这会导致签名计算的body内容与实际发送的不一致。
修复:将requests.post中的params=body改为json=body。JSON序列化格式不一致
默认json.dumps(body)会生成带空格的JSON字符串(如{"key": "value"}),而Bitget服务器可能要求紧凑格式(无空格),导致签名不匹配。
修复:修改JSON序列化代码为converted_body = json.dumps(body, separators=(',', ':')),确保生成无空格的JSON字符串。代码冗余与扩展性问题
GET和POST方法的签名逻辑重复,容易出现遗漏。建议将签名计算逻辑抽为公共函数,统一处理query参数和body的拼接。
优化示例:def generate_signature(timestamp, method, request_path, query=None, body=None): method_upper = method.upper() query_str = parse_params_to_str(query) if query and query != {} else "" if query_str: query_str = f"?{query_str}" converted_body = json.dumps(body, separators=(',', ':')) if body and body != {} else "" message = f"{timestamp}{method_upper}{request_path}{query_str}{converted_body}" return get_signature(message)
修复后的关键代码示例
修改后的post函数:
def post(request_path, body, method): std_time = time.time() * 1000 new_time = int(std_time) if str(body) == '{}' or str(body) == 'None': converted_body = '' else: converted_body = json.dumps(body, separators=(',', ':')) # 方法转大写 message = str(new_time) + method.upper() + request_path + converted_body print(message) headers = {"ACCESS-KEY": api_key, "ACCESS-SIGN": get_signature(message), "ACCESS-TIMESTAMP": str(new_time), "ACCESS-PASSPHRASE": api_passphrase, "Content-Type": "application/json", "Locale": "en-US" } if method == "POST": # 使用json参数传递请求体 request_resp = requests.post( (api_url + request_path), headers=headers, json=body) return request_resp
内容的提问来源于stack exchange,提问作者trista
相关产品推荐
相关产品推荐

