2017-04-22 105 views
3

我正在寫https://poloniex.com/support/api/的Python 3哈希HMAC-SHA512

公共方法都做工精細一個機器人,但交易API方法需要一些額外的技巧:

All calls to the trading API are sent via HTTP POST to https://poloniex.com/tradingApi and must contain the following headers:
Key - Your API key.
Sign - The query's POST data signed by your key's "secret" according to the HMAC-SHA512 method.
Additionally, all queries must include a "nonce" POST parameter. The nonce parameter is an integer which must always be greater than the previous nonce used.
All responses from the trading API are in JSON format.

我對returnBalances長相碼像這樣:

import hashlib 
import hmac 
from time import time 

import requests 


class Poloniex: 
    def __init__(self, APIKey, Secret): 
     self.APIKey = APIKey 
     self.Secret = Secret 

    def returnBalances(self): 
     url = 'https://poloniex.com/tradingApi' 
     payload = { 
      'command': 'returnBalances', 
      'nonce': int(time() * 1000), 
     } 

     headers = { 
      'Key': self.APIKey, 
      'Sign': hmac.new(self.Secret, payload, hashlib.sha512).hexdigest(), 
     } 

     r = requests.post(url, headers=headers, data=payload) 
     return r.json() 

trading.py:

APIkey = 'AAA-BBB-CCC' 
secret = b'123abc' 

polo = Poloniex(APIkey, secret) 
print(polo.returnBalances()) 

而且我得到了以下錯誤:

Traceback (most recent call last): 
    File "C:/Python/Poloniex/trading.py", line 5, in <module> 
    print(polo.returnBalances()) 
    File "C:\Python\Poloniex\poloniex.py", line 22, in returnBalances 
    'Sign': hmac.new(self.Secret, payload, hashlib.sha512).hexdigest(), 
    File "C:\Users\Balazs91\AppData\Local\Programs\Python\Python35-32\lib\hmac.py", line 144, in new 
    return HMAC(key, msg, digestmod) 
    File "C:\Users\Balazs91\AppData\Local\Programs\Python\Python35-32\lib\hmac.py", line 84, in __init__ 
    self.update(msg) 
    File "C:\Users\Balazs91\AppData\Local\Programs\Python\Python35-32\lib\hmac.py", line 93, in update 
    self.inner.update(msg) 
TypeError: object supporting the buffer API required 

Process finished with exit code 1 

我也試圖執行以下,但它並沒有幫助: https://stackoverflow.com/a/25111089/7317891

任何幫助,不勝感激!

+0

你'payload'在'returnBalances'是一個字典,它不支持緩衝的API(閱讀:便宜的字節表示)。您可能需要'payload = str(dict(command ='returnBalances',nonce = ...))',因爲字符串的表示形式類似於這種情況恰好等於JSON表示形式;它的字節編碼形式可以發送給HMAC。 – user2722968

+0

@ user2722968 Python字典的字符串表示形式不是有效的查詢字符串,所以這不起作用。 –

回答

3

您傳遞給requests.post的有效載荷必須是有效的查詢字符串或與該查詢字符串對應的字典。通常情況下,傳遞字典並獲取請求爲您構建查詢字符串會更方便,但在這種情況下,我們需要從查詢字符串構造HMAC簽名,因此我們使用標準的urlib.parse模塊構建查詢串。

令人煩惱的是,urlib.parse.urlencode函數返回一個文本字符串,所以我們需要將它編碼爲一個字節字符串,以便讓它可以接受hashlib。使用UTF-8的明顯編碼方式是:編碼一個只包含純ASCII的文本字符串,因爲UTF-8會創建一個與等效的Python 2字符串相同的字節序列(當然,urlencode只會返回純ASCII),所以此代碼的行爲與鏈接的Poloniex API頁面上的舊Python 2代碼行爲相同。

from time import time 
import urllib.parse 
import hashlib 
import hmac 

APIkey = b'AAA-BBB-CCC' 
secret = b'123abc' 

payload = { 
    'command': 'returnBalances', 
    'nonce': int(time() * 1000), 
} 

paybytes = urllib.parse.urlencode(payload).encode('utf8') 
print(paybytes) 

sign = hmac.new(secret, paybytes, hashlib.sha512).hexdigest() 
print(sign) 

輸出

b'command=returnBalances&nonce=1492868800766' 
3cd1630522382abc13f24b78138f30983c9b35614ece329a5abf4b8955429afe7d121ffee14b3c8c042fdaa7a0870102f9fb0b753ab793c084b1ad6a3553ea71 

然後你就可以這樣做

headers = { 
    'Key': APIKey, 
    'Sign': sign, 
} 

r = requests.post(url, headers=headers, data=paybytes) 
+0

非常感謝,它現在可以使用! 代碼中有一個小錯字,最後一行應該是: 'r = requests.post(url,headers = headers,data = payload)' –

+0

@BalázsMagyar這不是一個錯字!我們應該發送確切的查詢字符串'paybytes',對應'sign'。如果將'payload'字典傳遞給'requests.post',那麼它有可能會將查詢參數放在不同的順序中,因爲字典沒有固有的順序。這意味着服務器爲該查詢字符串計算的HMAC與我們在「sign」中發送的HMAC不匹配。 –

+0

@BalázsMagyarOTOH,無論你傳遞request.spost是查詢字符串的文本版本(即urllib.parse.urlencode(payload))還是UTF-8編碼版本,它都不會產生影響。但是,我認爲把它傳遞給一個字節串而不是一個Unicode字符串更爲簡單。 –