Как мне подписать POST-запрос, используя HMAC-SHA512 и библиотеку запросов Python?
Я пытаюсь использовать Python для доступа к торговому API на бирже криптовалюты poloniex.com. Для этого я должен следовать этому рецепту:
Все вызовы торгового API отправляются через HTTP POST на https://poloniex.com/tradingApi и должны содержать следующие заголовки:
Ключ - Ваш ключ API.
Знак - данные запроса POST, подписанные "секретом" вашего ключа в соответствии с методом HMAC-SHA512.Кроме того, все запросы должны включать параметр "nonce" POST. Параметр nonce - это целое число, которое всегда должно быть больше предыдущего использованного nonce.
Вот что у меня так далеко. Моя текущая проблема заключается в том, что я не знаю, как скомпилировать URL-адрес POST, чтобы он мог быть подписан без предварительной отправки неполного запроса. Это, очевидно, не работает.
import requests
import hmac
import hashlib
import time
headers = { 'nonce': '',
'Key' : 'myKey',
'Sign': '',}
payload = { 'command': 'returnCompleteBalances',
'account': 'all'}
secret = 'mySecret'
headers['nonce'] = int(time.time())
response = requests.post( 'https://poloniex.com/tradingApi', params= payload, headers= headers )
headers['Sign'] = hmac.new( secret, response.url, hashlib.sha512)
1 ответ
Создать подготовленный запрос; Вы можете добавить к нему заголовки после создания тела:
import requests
import hmac
import hashlib
request = requests.Request(
'POST', 'https://poloniex.com/tradingApi',
data=payload, headers=headers)
prepped = request.prepare()
signature = hmac.new(secret, prepped.body, digestmod=hashlib.sha512)
prepped.headers['Sign'] = signature.hexdigest()
with requests.Session() as session:
response = session.send(prepped)
Я изменил твой params
аргумент data
; для запроса POST принято отправлять параметры в теле, а не в URL.
Для одноразового использования я бы использовал itertools.count()
Объект, посеянный с текущего времени, поэтому перезапуски не влияют на него. Согласно документации API Poloniex (которую вы цитировали в своем вопросе), nonce является частью тела POST, а не заголовков, поэтому поместите его в payload
толковый словарь:
from itertools import count
import time
# store as a global variable
NONCE_COUNTER = count(int(time.time() * 1000))
# then every time you create a request
payload['nonce'] = next(NONCE_COUNTER)
С помощью int(time.time())
будет повторно использовать тот же номер, если вы создали более одного запроса в секунду. Пример кода, предоставленного Poloniex, использует int(time.time()*1000)
чтобы сделать возможным создание запроса каждую микросекунду вместо этого, но используя свой собственный монотонно увеличивающийся счетчик (отобранный из time.time()
) гораздо надежнее.
Вы также можете инкапсулировать процесс подписания дайджеста в пользовательский объект аутентификации; такой объект передается в подготовленном запросе как последний шаг в подготовке:
import hmac
import hashlib
class BodyDigestSignature(object):
def __init__(self, secret, header='Sign', algorithm=hashlib.sha512):
self.secret = secret
self.header = header
self.algorithm = algorithm
def __call__(self, request):
body = request.body
if not isinstance(body, bytes): # Python 3
body = body.encode('latin1') # standard encoding for HTTP
signature = hmac.new(self.secret, body, digestmod=self.algorithm)
request.headers[self.header] = signature.hexdigest()
return request
Используйте это с вашим requests
звонки:
response = requests.post(
'https://poloniex.com/tradingApi',
data=payload, headers=headers, auth=BodyDigestSignature(secret))
Переданный аргумент является секретом, используемым в дайджесте HMAC; Вы также можете передать другое имя заголовка.