2017-06-02 12 views
0

突然、Spotify Search APIの承認ヘッダが必要と判断しました。Poco Netライブラリを使用してSpotifyでトークンのコードを交換する方法

私のアプリケーションはPoco Netライブラリを使ってC++で動作し、動作させることができません。

私はトークンを交換するはずの "コード"を手に入れました。私はこのコードが有効であると仮定します。ただし、まったく無関係のドメインを使用して、そのページに送信された変数をコピーしました。

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; 
    } 
} 

私が代わりにリクエストにクライアントIDとclientSecretを置くのBasicCredentialsを試してみましたが、それは、同じ結果を得ました。

これは、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私は最初に身体の長さの要求を行う、私はいくつかのkeepAliveフラグを設定し、私は残りのデータを送信する必要があります。 BasicCredentialsも機能しました。私は、この愚かなredirect_uriが必要な場合、最初に認証コードを取得する方法を知る必要があります。 – CashCow

答えて

0

[OK]を、私は答えを見つけた今、自分の質問にお答えします。私のエラーは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; 
    } 
} 
関連する問題