2017-08-17 57 views
0

我想爲Last.fm API製作Python客戶端。我想建立一個圖書館。Last.fm API無效的方法簽名,但獲得會話密鑰時有效

我設法通過獲取會話密鑰來設置會話。之後,我嘗試調用一個需要API_key,api_signature和會話密鑰的POST方法。所以我使用我有的APi密鑰,和我用來獲取會話密鑰和會話密鑰本身的api_signature一樣。

但我得到一個「無效的方法簽名」,即使我使用相同的api_signature進行POST調用。

import json 
import webbrowser 
from hashlib import md5 
import urllib3 

class PyLast(): 

def __init__(self, API_KEY, SECRET, SESSION_KEY=None): 
    self.__API_KEY__ = API_KEY 
    self.__SECRET__ = SECRET 
    self.__SESSION_KEY__ = SESSION_KEY 
    self.__api_signature__ = None 
    if SESSION_KEY is None: 
     self.__is_authorized__ = False 
    else: 
     self.__is_authorized__ = True 

    self.__http__ = urllib3.PoolManager() 

def request_token(self): 
    print("Getting the token...") 
    url = 'http://ws.audioscrobbler.com/2.0/?method=auth.gettoken&api_key={}&format=json'.format(self.__API_KEY__) 
    req_response = self.__http__.request('GET', url, headers={'User-Agent' : 'Mozilla/5.0'}) 
    if req_response.status == 200: 
     json_data = json.loads(req_response.data.decode('utf-8')) 
     TOKEN = json_data['token'] 
     self.__TOKEN__ = TOKEN 
     return TOKEN 
    else: 
     print("Error with code " + req_response.status) 

def authorize(self): 
    if not self.__is_authorized__: 
     url = 'http://www.last.fm/api/auth/?api_key={}&token={}'.format(self.__API_KEY__, self.__TOKEN__) 
     # open browser to authorize app 
     webbrowser.open(url, new=0, autoraise=True) 
     # Make sure authorized 
     self.__is_authorized__ = True 


def start_session(self): 
    if self.__is_authorized__: 
     data = "api_key{}methodauth.getSessiontoken{}{}" \ 
            .format(self.__API_KEY__, self.__TOKEN__, self.__SECRET__).encode(
      encoding='utf-8') 
     self.__api_signature__ = md5(data).hexdigest() 
     url = 'http://ws.audioscrobbler.com/2.0/?method=auth.getSession&api_key={}&token={}&api_sig={}&format=json'.format(
      self.__API_KEY__, self.__TOKEN__, self.__api_signature__) 
     req_response = self.__http__.request('GET', url) 

     if req_response.status == 200: 
      json_data = json.loads(req_response.data.decode('utf-8')) 
      session_key = json_data['session']['key'] 
      self.__SESSION_KEY__ = session_key 

      url = 'http://ws.audioscrobbler.com/2.0/?method=track.love&api_key={}&api_sig={}&sk={}&artist=cher&track=believe&format=json'.format(
       self.__API_KEY__, self.__api_signature__, self.__SESSION_KEY__) 
      req_response = self.__http__.request('POST', url) 

      return self.__SESSION_KEY__ 
     else: 
      print("Error with code " + str(req_response.status)) 




    else: 
     print("Not authorized!") 

回答

0

我找到了解決方案。問題是我使用了相同的參數來生成會話密鑰來進行POST調用。爲Last.fm API簽名方法的正確方法是從我們想要使用的POST方法構建api_sig。例如,爲track.love生成api_sig我們使用這些參數:

data = {"api_key": API_KEY, 
        "method": "track.love", 
        "track" : "yellow", 
        "artist" :"coldplay", 
        "sk" : SESSION_KEY 
        } 
keys = sorted(data.keys()) 
param = [k+data[k] for k in keys] 
param = "".join(param) + SECRET 
api_sig = md5(param.encode()).hexdigest() # this api_sig used to sign track.love call. 
相關問題