2017-06-02 15 views
0

因此他們突然決定我需要Spotify Search API的授權頭。如何使用Poco Net Library在Spotify中交換令牌代碼

我的應用程序運行在C++使用Poco網絡庫,我無法讓它工作。

我經歷了所有獲取我應該交換令牌的「代碼」的過程。我假設這段代碼是有效的,儘管我只是使用了一個完全不相關的域,然後將它發送到發送給該頁面的變量。

https://developer.spotify.com/web-api/authorization-guide/

這是我的代碼不工作:

bool getToken() 
{ 
    Poco::URI loginURI("https://accounts.spotify.com"); 
    Poco::Net::HTTPSClientSession loginSession(loginURI.getHost(), loginURI.getPort(), context); 
//  Poco::Net::HTTPBasicCredentials credentials(clientId, clientSecret); 

    std::ostringstream requestOStr; 
    requestOStr << "https://accounts.spotify.com/api/token?grant_type=authorization_code&code=" 
      << (m_refreshToken.empty() ? code : m_refreshToken) 
      << "&redirect_uri=" << redirectURI 
      << "&client_id=" << clientId << "&client_secret=" << clientSecret; 

    std::string requestStr(requestOStr.str()); 
    Poco::Net::HTTPRequest loginRequest(Poco::Net::HTTPRequest::HTTP_POST, requestStr, 
      Poco::Net::HTTPMessage::HTTP_1_1); 

//  credentials.authenticate(loginRequest); 

    loginSession.sendRequest(loginRequest); 
    Poco::Net::HTTPResponse response; 

    std::istream& rs = loginSession.receiveResponse(response); 
    std::cout << "Login request " << requestStr << std::endl; 
    std::cout << "Login response status " << static_cast<int>(response.getStatus()) << ", " 
      << response.getReason() << std::endl; 

    std::string rsStr(std::istreambuf_iterator<char>(rs), {}); 
    if(rsStr.empty()) 
    { 
     std::cout << "No results" << std::endl; 
     return false; 
    } 
    else 
    { 
     std::cout << "Logon response:\n" << rsStr << std::endl; 
    } 
    Parser parser; 
    Var result; 
    result = parser.parse(rsStr); 
    Object::Ptr obj = result.extract<Object::Ptr>(); 
    try 
    { 
     Var tokenVar = obj->get("access_token "); 
     if(tokenVar.isString()) 
     { 
      m_token = tokenVar.convert<std::string>(); 
     } 
     else 
     { 
      std::cerr << "Could not get access token" << std::endl; 
      return false; 
     } 
     Var refreshTokenVar = obj->get("refresh_token"); 
     if(refreshTokenVar.isString()) 
     { 
      m_refreshToken = refreshTokenVar.convert<std::string>(); 
     } 
     return true; 
    } 
    catch(const std::exception& err) 
    { 
     std::cerr << "Error getting login token" << err.what() << std::endl; 
     return false; 
    } 
} 

我試過BasicCredentials而不是把客戶端ID和clientSecret到請求但得到了同樣的結果。

這是HTTP請求的外觀與值修正:

https://accounts.spotify.com/api/token?grant_type=authorization_code&code=THE_CODE&redirect_uri=THE_REDIRECT_URI&client_id=THE_CLIENT_ID&client_secret=THE_CLIENT_SECRET 

我得到的迴應是:

Login response status 400, Bad Request 
    {"error":"server_error","error_description":"Unexpected status: 400"} 
+0

那麼一個驚喜,我回來一整天后,沒有人回答它。無論如何,當我問過以前的問題時,我所看到的都是無稽之談。 – CashCow

+0

我幾乎找到了答案:https://stackoverflow.com/questions/13165877/how-do-i-make-an-http-post-with-http-basic-authentication-using-poco 顯然是因爲它是一個POST我首先使用body的長度發出請求,我必須設置一對keepAlive標誌,然後發送其餘的數據。 BasicCredentials也起作用。我只需要知道如何獲得授權碼,因爲我需要這個愚蠢的redirect_uri。 – CashCow

回答

0

好吧,我現在回答我的問題已經找到了答案。我的錯誤是錯誤使用POST。

這有效,一旦我有原始authorization_code。一旦「交換」代碼將不再有效,但這是一個不同的問題。

bool getToken() 
{ 
    Poco::URI loginURI("https://accounts.spotify.com"); 
    Poco::Net::HTTPSClientSession loginSession(loginURI.getHost(), loginURI.getPort(), context); 
    Poco::Net::HTTPBasicCredentials credentials(clientId, clientSecret); 

    loginSession.setKeepAlive(true); 
    std::string requestStr("https://accounts.spotify.com/api/token"); 
    Poco::Net::HTTPRequest loginRequest(Poco::Net::HTTPRequest::HTTP_POST, 
      requestStr, 
      Poco::Net::HTTPMessage::HTTP_1_1); 
    loginRequest.setContentType("application/x-www-form-urlencoded"); 
    loginRequest.setKeepAlive(true); 

    std::string grantType; 
    std::string authCode; 

    if(m_refreshToken.empty()) 
    { 
     grantType = "authorization_code"; 
     authCode = code; 
    } 
    else 
    { 
     grantType = "refresh_token"; 
     authCode = m_refreshToken; 
    } 
    std::ostringstream contentOStr; 
    contentOStr << "grant_type=" << grantType << 
     "&code=" << authCode 
     << "&redirect_uri=" << redirectURI; 

    std::string contentStr = contentOStr.str(); 
    loginRequest.setContentLength(contentStr.size()); 
    credentials.authenticate(loginRequest); 

    std::ostream& requestOStr = loginSession.sendRequest(loginRequest); 
    requestOStr << contentStr; 
    requestOStr.flush(); 
    Poco::Net::HTTPResponse response; 

    std::istream& rs = loginSession.receiveResponse(response); 
    std::cout << "Login request "; 
    loginRequest.write(std::cout); 
    std::cout << std::endl; 
    std::cout << "Login response status " << static_cast<int>(response.getStatus()) << ", " 
      << response.getReason() << std::endl; 

    std::string rsStr(std::istreambuf_iterator<char>(rs), {}); 
    if(rsStr.empty()) 
    { 
     std::cout << "No results" << std::endl; 
     return false; 
    } 
    else 
    { 
     std::cout << "Logon response:\n" << rsStr << std::endl; 
    } 
    Parser parser; 
    Var result; 
    result = parser.parse(rsStr); 
    Object::Ptr obj = result.extract<Object::Ptr>(); 
    try 
    { 
     Var tokenVar = obj->get("access_token"); 
     if(tokenVar.isString()) 
     { 
      m_token = tokenVar.convert<std::string>(); 
     } 
     else 
     { 
      std::cerr << "Could not get access token" << std::endl; 
      return false; 
     } 
     Var refreshTokenVar = obj->get("refresh_token"); 
     if(refreshTokenVar.isString()) 
     { 
      m_refreshToken = refreshTokenVar.convert<std::string>(); 
     } 
     return true; 
    } 
    catch(const std::exception& err) 
    { 
     std::cerr << "Error getting login token" << err.what() << std::endl; 
     return false; 
    } 
} 
相關問題