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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 15:55:20