使用Python调用Remitano API获取币账户余额时签名无效问题修复
问题
我想用Python获取Remitano平台当前用户的币账户余额,参考官方文档写了代码,但运行后一直返回{"error":"invalid signature"},代码如下:
import requests import hashlib import hmac import base64 import time ACCESS_KEY = "my_key" SECRET_KEY = "my_SECRET" # The API endpoint API_ENDPOINT = "https://api.remitano.com/api/v1/users/coin_accounts" def sign_request(method, url, body=""): # Set the Content-Type header to "application/json" headers = { "Content-Type": "application/json", } # Hash the request body with MD5, base64 encode the hash, and set the Content-MD5 header if body: m = hashlib.md5() m.update(body.encode()) headers["Content-MD5"] = base64.b64encode(m.digest()).decode() # Set the "date" header to the current UTC time in the format "Wed, 21 Oct 2015 07:28:00 GMT" headers["date"] = time.strftime("%a, %d %b %Y %H:%M:%S %Z", time.gmtime()) # Construct the request string request_string = f"{method},application/json,{headers.get('Content-MD5', '')},{url},{headers['date']}" # Use the SECRET_KEY to create a hash of the request string using the HMAC-SHA1 algorithm, base64 encode the hash, and set the "Authorization" header sig = hmac.new(SECRET_KEY.encode(), request_string.encode(), hashlib.sha1).digest() headers["Authorization"] = f"APIAuth {ACCESS_KEY}:{base64.b64encode(sig).decode()}" return headers def make_request(method, url, body=""): headers = sign_request(method, url, body) return requests.request(method, url, headers=headers, data=body) # Make a signed GET request response = make_request("GET", API_ENDPOINT) print(response.text)
修复方案
签名无效主要是以下几个问题导致的,逐一修复即可:
日期格式不规范:
%Z在不同系统环境下可能不会返回标准的GMT标识,而Remitano要求日期必须严格遵循Wed, 21 Oct 2015 07:28:00 GMT格式,直接硬编码替换:headers["date"] = time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime())URL使用错误:签名计算时需要使用URL的路径部分(例如
/api/v1/users/coin_accounts),而非带域名的完整URL。需要提取路径部分:from urllib.parse import urlparse parsed_url = urlparse(url) url_path = parsed_url.path # 构造请求字符串时用url_path代替原完整url request_string = f"{method},application/json,{headers.get('Content-MD5', '')},{url_path},{headers['date']}"密钥校验:检查
SECRET_KEY是否复制正确,确认没有多余的空格、换行符,这是最容易忽略的细节。
修改后的完整代码
import requests import hashlib import hmac import base64 import time from urllib.parse import urlparse ACCESS_KEY = "my_key" SECRET_KEY = "my_SECRET" API_ENDPOINT = "https://api.remitano.com/api/v1/users/coin_accounts" def sign_request(method, url, body=""): headers = { "Content-Type": "application/json", } content_md5 = "" if body: m = hashlib.md5() m.update(body.encode()) content_md5 = base64.b64encode(m.digest()).decode() headers["Content-MD5"] = content_md5 # 生成标准GMT格式的日期 headers["date"] = time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime()) # 提取URL的路径部分 parsed_url = urlparse(url) url_path = parsed_url.path # 构造签名用的请求字符串 request_string = f"{method},application/json,{content_md5},{url_path},{headers['date']}" # 生成HMAC-SHA1签名并编码 sig = hmac.new(SECRET_KEY.encode(), request_string.encode(), hashlib.sha1).digest() headers["Authorization"] = f"APIAuth {ACCESS_KEY}:{base64.b64encode(sig).decode()}" return headers def make_request(method, url, body=""): headers = sign_request(method, url, body) # GET请求不需要传body return requests.request(method, url, headers=headers, data=body if method != "GET" else None) response = make_request("GET", API_ENDPOINT) print(response.text)
内容的提问来源于stack exchange,提问作者Philip
相关产品推荐
相关产品推荐

