Coinbase API标准python示例返回“无效签名”

2024-04-24 18:42:39 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图将Coinbase API与Python结合使用,从Coinbase开发者API页面上的标准示例开始:https://developers.coinbase.com/docs/wallet/api-key-authentication#

这段代码只给了我一些错误,比如:

TypeError: key: expected bytes or bytearray, but got 'str'

在谷歌搜索之后,我做了一些调整,这让我走得更远了,但我仍然不在那里。是否API文档页面给出了一个过时的示例

现在返回给我的主要消息是:{“id”:“authentication\u 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'...

希望你能帮我解决这个问题。看起来这只是把基本的东西弄对了


Tags: keyselfauthapimessagesecretauthenticationtime
1条回答
网友
1楼 · 发布于 2024-04-24 18:42:39

首先要提到的是,你链接到他们页面中的代码是python2,如果你用它运行他们的代码,它会立即工作

我今天也遇到了同样的问题,并且意识到您的代码有多个问题(因为我假设您已经尽力解决了),所以我为您解决了这些问题,并且python3中的请求库或截至今天(04/28/21)的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一起运行,因为您的环境/系统中已经安装了库

至于为什么会有bug?
疑难解答我发现request.body必须是空的,API才会喜欢它(我说的空是指''),因为它不希望该特定端点有主体。这是一个关于请求库的假设,当您在调用中指定内容类型设置为JSON或使用json=时,它会看到您有一个空的正文,它会自动用{}填充正文。这是有道理的,因为您不想通过说您要发送json但没有发送任何东西来控制服务器,所以python3中的请求只是为了方便服务器。在python2中,请求库不会自动执行此操作。这对我们来说是一个问题,因为如果端点不接受主体,API希望主体完全为空

为什么要这样做?
我不知道,因为这不是一个签名验证问题。我检查了工作的python2版本和python3版本,签名结果是相同的,因此不是身份验证问题。服务器的请求主体是一个空的JSON对象,这似乎是不灵活的

因此,为了解决这个问题,我们必须在看到请求主体设置为{}时清除请求主体

TLDR:
服务器错误地认为这是一个签名/身份验证问题,而实际上是一个错误的请求。看看代码

相关问题 更多 >