2017-02-07 15 views
5

Próbuję użyć Pythona, aby uzyskać dostęp do handlowego API na poloniex.com, giełdzie kryptowalut. Aby to zrobić, muszę obserwować tą receptę:Jak mogę podpisać żądanie POST za pomocą HMAC-SHA512 i biblioteki żądań Pythona?

wszystkich wywołań API handlu są wysyłane za pośrednictwem HTTP POST do https://poloniex.com/tradingApi i musi zawierać następujące nagłówki:

Key - Twój klucz API.
Znak - dane POST zapytania są podpisane kluczem tajnym klucza zgodnie z metodą HMAC-SHA512.

Ponadto wszystkie zapytania muszą zawierać parametr POST "jednorazowy". Parametr nonce jest liczbą całkowitą, która zawsze musi być większa od poprzedniej wartości.

Oto, co mam do tej pory. Mój obecny problem polega na tym, że nie wiem, jak skompilować URL POST, aby można go było podpisać bez uprzedniego wysłania niekompletnego żądania. To oczywiście nie działa.

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) 

Odpowiedz

11

Utwórz prepared request; można dodać nagłówki że po jednostka została utworzona:

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) 

zmieniłem swój params argument data; dla żądania POST zwykle wysyłane są parametry w treści, a nie URL.

Dla nonce, użyłbym itertools.count() object, rozstawionego z bieżącego czasu, więc ponowne uruchomienie nie ma na niego wpływu. Według Poloniex API documentation (którego cytowany w swoim pytaniu), przy czym nonce jest częścią ciała POST, a nie nagłówki, więc umieścić go w słowniku 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) 

Korzystanie int(time.time()) będzie ponownie użyć tego samego numeru jeśli utworzyłeś więcej niż jedno żądanie na sekundę. Model example code provided by Poloniex używa int(time.time()*1000), aby umożliwić tworzenie żądań w każdym mikrosekundie, ale użycie własnego monotonicznie rosnącego licznika (rozstawionego z time.time()) jest znacznie bardziej niezawodne.

Można również enkapsulować proces podpisywania digest w custom authentication object; taki obiekt zostanie przekazany w przygotowanej żądanie jako ostatni krok w przygotowaniu:

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 

użyć ich połączeń requests:

response = requests.post(
    'https://poloniex.com/tradingApi', 
    data=payload, headers=headers, auth=BodyDigestSignature(secret)) 

Argument przekazany jest tajemnicą stosowany w HMAC trawienia; możesz również przekazać inną nazwę nagłówka.

+0

To było takie szybkie, wielkie dzięki! – Werhli

+0

@MartijnPieters po uruchomieniu tego otrzymuję komunikat o błędzie: Obiekt "Żądanie" nie ma atrybutu "treść". dla tej linii: signature = hmac.new (secret, request.body, digestmod = hashlib.sha512) –

+0

@abcla corrected –

Powiązane problemy