在Python 3.3中使用requests和requests-oauthlib进行API调用认证
我正在尝试用Python 3写一个自己的Cryptsy API封装,使用的是requests和requests-oauthlib这两个库。我对API调用和Python都很陌生。目前,我遇到了这个错误:
{'error': 'Unable to Authorize Request - Check Your Post Data', 'success': '0'}
这并不奇怪,因为我很难找到关于如何使用这些库进行调用和签名认证API请求的文档。我不知道该从哪里开始。
这是我代码的一部分:
import time
import requests
from requests-oauthlib import OAuth1Session
class Cryptsy:
def __init__(self, APIKey, Secret):
self.APIKey = APIKey
self.Secret = Secret
self.privateBaseURL = 'https://api.cryptsy.com/api'
def private_api_query(self, method, payload={}):
url = self.privateBaseURL
session = OAuth1Session(self.APIKey, client_secret=self.Secret)
payload['method'] = method
payload['nonce'] = int(time.time())
response = session.post(url, data=payload)
js = response.json()
return js
def getMarkets(self):
return self.private_api_query('getmarkets')
如你所见,我对nonce有点了解,但不确定在使用这些库时它是否必要。我知道请求需要被签名,但不太清楚如何让这些库按照我需要的方式去做。
当然,我也可以尝试使用urllib,但自从切换到Python 3后,我在使用它时遇到了麻烦,我更喜欢requests库(据说)更简单易用。
关于Cryptsy的API的更多信息可以在这里找到: https://www.cryptsy.com/pages/api
任何帮助都将非常感激。
1 个回答
2
Cryptsy并没有使用OAuth(至少他们的文档没有说他们在用)。相反,他们自己开发了认证方式。暂时不讨论这种方法的安全性,我们来看看你需要什么。
他们的文档不是很好,但根据我的理解,你需要:
- 两个额外的头信息:Key(里面放你的公共API密钥)和Sign(里面放一个HMAC-SHA512的签名,用于请求体)
- 一个请求体,内容类型为
application/x-www-form-urlencoded
,里面包含方法名称、方法参数和一个随机数(nonce)。
在请求中实现这一点比平常稍微复杂一些,但最简单的方法可能是自己写一个自定义的认证处理器。下面是一个例子:
from requests.auth import AuthBase
import hmac
import hashlib
import time
class CryptsyAuth(AuthBase):
"""Authenticates a given HTTP request using the Cryptsy Auth scheme"""
def __init__(self, api_key, api_secret):
self.key = api_key
self.secret = api_secret
def __call__(self, r):
r.body += '&nonce=%d' % int(time.time())
h = hmac.new(self.secret, r.body, hashlib.sha512).hexdigest()
r.headers['Key'] = self.key
r.headers['Sign'] = h
return r
请注意,如果你不提供请求体,这个认证处理器会出错,但没关系,因为Cryptsy要求你必须提供。下面是如何使用它的:
class Cryptsy:
def __init__(self, APIKey, Secret):
self.APIKey = APIKey
self.Secret = Secret
self.privateBaseURL = 'https://api.cryptsy.com/api'
self.session = requests.Session()
def private_api_query(self, method, payload={}):
url = self.privateBaseURL
payload['method'] = method
response = self.session.post(url, data=payload, auth=CryptsyAuth(self.APIKey, self.Secret))
js = response.json()
return js
def getMarkets(self):
return self.private_api_query('getmarkets')