python - Coinbase API 标准 python 示例返回“无效签名”
问题描述
我正在尝试将 Coinbase API 与 Python 一起使用,从 Coinbase Developer API 页面上的标准示例开始:https ://developers.coinbase.com/docs/wallet/api-key-authentication#
这段代码只给了我错误,例如:
TypeError: key: expected bytes or bytearray, but got 'str'
经过一些谷歌搜索后,我做了一些调整,让我更进一步,但我仍然不在那里。API文档页面是否提供了一个过时的示例?
现在返回给我的主要信息是:{"id":"authentication_error","message":"invalid signature"}
我正在使用以下代码(用 xxxxxx 替换我的密钥):
import json, hmac, hashlib, time, requests
from requests.auth import AuthBase
# Before implementation, set environmental variables with the names API_KEY and API_SECRET
API_KEY = 'xxxxxxx'
API_SECRET = b'xxxxxxx'
def get_timestamp():
return int(time.time() * 1000)
# Create custom authentication for Coinbase API
class CoinbaseWalletAuth(AuthBase):
def __init__(self, api_key, secret_key):
self.api_key = api_key
self.secret_key = secret_key
def __call__(self, request):
timestamp = str(int(time.time()))
print(timestamp)
message = timestamp + request.method + request.path_url + (request.body or b'').decode()
hmac_key = base64.b64decode(self.secret_key)
signature = hmac.new(hmac_key, message.encode(), hashlib.sha256)
signature_b64 = base64.b64encode(signature.digest()).decode()
request.headers.update({
'CB-ACCESS-SIGN': signature_b64,
'CB-ACCESS-TIMESTAMP': timestamp,
'CB-ACCESS-KEY': self.api_key,
'Content-Type': 'application/json'
})
return request
api_url = 'https://api.coinbase.com/v2/'
auth = CoinbaseWalletAuth(API_KEY, API_SECRET)
# Get current user
r = requests.get(api_url + 'user', auth=auth)
print(r.json())
# {u'data': {u'username': None, u'resource': u'user', u'name': u'User'...
希望你能帮我解决这个问题。看起来这只是让基础知识正确......
解决方案
首先要提到的是,您链接的页面中的代码是 python2,如果您使用它运行他们的代码,它可以立即运行。
我今天遇到了同样的问题,并意识到您的代码有多个问题(因为我假设您尝试了所有方法来修复它)所以我为您修复了这些问题,并且截至今天(21 年 4 月 28 日),python3 或 API 中的请求库) 有问题。我想出了一个解决办法。
import json, hmac, hashlib, time, requests
from requests.auth import AuthBase
# Before implementation, set environmental variables with the names API_KEY and API_SECRET
API_KEY = 'xxxxxxx'
API_SECRET = 'xxxxxxx'
# Create custom authentication for Coinbase API
class CoinbaseWalletAuth(AuthBase):
def __init__(self, api_key, secret_key):
self.api_key = api_key
self.secret_key = secret_key
def __call__(self, request):
timestamp = str(int(time.time()))
# the following try statement will fix the bug
try:
body = request.body.decode()
if body == "{}":
request.body = b""
body = ''
except AttributeError:
request.body = b""
body = ''
message = timestamp + request.method + request.path_url + body
signature = hmac.new(self.secret_key.encode(), message.encode(), hashlib.sha256).hexdigest()
request.headers.update({
'CB-ACCESS-SIGN': signature,
'CB-ACCESS-TIMESTAMP': timestamp,
'CB-ACCESS-KEY': self.api_key,
})
return request
api_url = 'https://api.coinbase.com/v2/'
auth = CoinbaseWalletAuth(API_KEY, API_SECRET)
# Get current user
r = requests.get(api_url + 'user', auth=auth)
print(r.json())
# {u'data': {u'username': None, u'resource': u'user', u'name': u'User'...
现在将其另存为test.py
并运行python3 test.py
,假设您已在环境/系统中安装了库。
至于为什么有错误?
故障排除我发现request.body
API 必须为空才能喜欢它(我的意思是空的''
),因为它不希望该特定端点的主体。这是关于请求库的假设,当您将内容类型设置为 JSON 或json=
在调用中使用时,它会看到您有一个空正文,它会自动使用{}
. 这是有道理的,因为你不想通过说你要发送 json 但没有发送任何东西来欺骗服务器,所以 python3 中的请求对服务器来说很好。在 python2 中,请求库不会自动执行此操作。这对我们来说是一个问题,因为如果端点不接受主体,API 喜欢主体完全为空。
为什么这会修复它?
我不知道,因为这不是签名认证问题。我检查了工作 python2 版本和 python3 版本,并且签名相同,因此不是身份验证问题。看起来服务器不灵活,他们的请求正文是一个空的 JSON 对象。
因此,作为解决此问题的回顾,我们必须在看到请求主体设置为 时清除请求主体{}
。
TLDR:
服务器误导认为这是一个签名/身份验证问题,而实际上这是一个错误的请求。看看代码。
推荐阅读
- android - MPAndroidChart Marker 的 TextView 外观
- c# - 仅返回一项时在变量中获取 JSON 数据
- python-3.x - 无监督异常值检测
- android - “所有 com.android.support 库必须使用完全相同的版本规范”不想走开
- docker - 在容器输出中设置行缓冲
- bitbucket-pipelines - 使用 bitbucket-pipelines 将相同的分支部署到多个环境
- sql - 如何使用 SQL 按升序对包含 varchar 和 numeric 的列进行排序?
- c# - 将画布转换为图像时 UWP 应用程序挂起
- c++ - 有条件地在 C++ 类中启用构造函数
- selenium - 无法在硒的框架内定位元素