如何利用POCO网库在Spotify中实现令牌换码 [英] How to exchange code for token in Spotify using Poco Net Library

查看:22
本文介绍了如何利用POCO网库在Spotify中实现令牌换码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以他们突然决定我需要Spotify搜索API的授权头。

我的应用程序使用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:
" << 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"}

推荐答案

好了,我现在回答我自己的问题,已经找到了答案。我的错误是错误地使用了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:
" << 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;
    }
}

这篇关于如何利用POCO网库在Spotify中实现令牌换码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆