Google API 致命错误:未捕获的 LogicException:必须传入或设置刷新令牌作为 setAccessToken 的一部分 [英] Google API Fatal error: Uncaught LogicException: refresh token must be passed in or set as part of setAccessToken

查看:18
本文介绍了Google API 致命错误:未捕获的 LogicException:必须传入或设置刷新令牌作为 setAccessToken 的一部分的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 PHP 快速入门代码时,我发现了一个问题:当需要刷新token,代码返回如下错误:

<块引用>

致命错误:未捕获的 LogicException:必须传入刷新令牌或设置为 setAccessToken 的一部分/app/vendor/google/apiclient/src/Google/Client.php:258

堆栈跟踪:

#0/app/gmail.php(32):Google_Client->fetchAccessTokenWithRefreshToken(NULL)

#1/app/test.php(14): getClient()

#2 {main} 被抛出/app/vendor/google/apiclient/src/Google/Client.php 第 258 行

我像这样修改了 getClient() 函数:

function getClient() {$client = new Google_Client();$client->setApplicationName(APPLICATION_NAME);$client->setScopes(SCOPES);$client->setAuthConfig(CLIENT_SECRET_PATH);$client->setRedirectUri(REDIRECT_URL);$client->setAccessType('离线');$client->setApprovalPrompt('force');//从文件中加载先前授权的凭据.$credentialsPath = expandHomeDirectory(CREDENTIALS_PATH);如果(文件存在($credentialsPath)){$accessToken = json_decode(file_get_contents($credentialsPath), true);}别的 {//请求用户授权.$authUrl = $client->createAuthUrl();return printf("<a href='%s' target='_blank'>auth</a><br/>", $authUrl);}$client->setAccessToken($accessToken);//如果令牌过期,则刷新令牌.//这里有错误!!if ($client->isAccessTokenExpired()) {$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());file_put_contents($credentialsPath, json_encode($client->getAccessToken()));}返回 $client;}

在第一次认证之后(使用在 getClient() 函数中创建的链接),当用户登陆到 REDIRECT_URL 时,一个 callbackAuth()代码>函数被执行:

function callbackAuth() {$client = new Google_Client();$client->setApplicationName(APPLICATION_NAME);$client->setScopes(SCOPES);$client->setAuthConfig(CLIENT_SECRET_PATH);$client->setRedirectUri(REDIRECT_URL);$client->setAccessType('离线');$client->setApprovalPrompt('force');//从文件中加载先前授权的凭据.$credentialsPath = expandHomeDirectory(CREDENTIALS_PATH);//请求用户授权.$authCode = trim($_GET['code']);//交换访问令牌的授权码.$accessToken = $client->fetchAccessTokenWithAuthCode($authCode);//将凭据存储到磁盘.if(!file_exists(dirname($credentialsPath))) {mkdir(dirname($credentialsPath), 0700, true);}file_put_contents($credentialsPath, json_encode($accessToken));printf("凭据保存到 %s
", $credentialsPath);$client->setAccessToken($accessToken);返回 $client;}

我尝试应用其他相关stackoverflow 问题,但没有结果.为什么会出现这个错误?

解决方案

感谢 Alex Blex 我能够注意我第一次收到令牌时有 refresh_token 但在第一次请求之后,refresh_token 没有被存储.解决方案如下(来自这个答案):

//如果令牌过期,则刷新令牌.if ($client->isAccessTokenExpired()) {$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());$newAccessToken = $client->getAccessToken();$accessToken = array_merge($accessToken, $newAccessToken);file_put_contents($credentialsPath, json_encode($accessToken));}

<块引用>

refresh_token 仅在第一次请求时返回.当你第二次刷新访问令牌它返回除refresh_token 和 file_put_contents 删除了 refresh_token第二次发生这种情况时.

修改如下代码会合并到原来的访问令牌与新的.这样你就可以保留您的 refresh_token 以供将来请求使用.

Working with the PHP Quickstart code, I found a problem: when the token needs to be refreshed, the code returns the following error:

Fatal error: Uncaught LogicException: refresh token must be passed in or set as part of setAccessToken in /app/vendor/google/apiclient/src/Google/Client.php:258

Stack trace:

#0 /app/gmail.php(32): Google_Client->fetchAccessTokenWithRefreshToken(NULL)

#1 /app/test.php(14): getClient()

#2 {main} thrown in /app/vendor/google/apiclient/src/Google/Client.php on line 258

I modified the getClient() function like this:

function getClient() {
    $client = new Google_Client();
    $client->setApplicationName(APPLICATION_NAME);
    $client->setScopes(SCOPES);
    $client->setAuthConfig(CLIENT_SECRET_PATH);
    $client->setRedirectUri(REDIRECT_URL);
    $client->setAccessType('offline');
    $client->setApprovalPrompt('force');

    // Load previously authorized credentials from a file.
    $credentialsPath = expandHomeDirectory(CREDENTIALS_PATH);

    if (file_exists($credentialsPath)) {
        $accessToken = json_decode(file_get_contents($credentialsPath), true);
    } 
    else {
        // Request authorization from the user.
        $authUrl = $client->createAuthUrl();
        return printf("<a href='%s' target='_blank'>auth</a><br />", $authUrl);
    }
    $client->setAccessToken($accessToken);

    // Refresh the token if it's expired.
    // ERROR HERE !!
    if ($client->isAccessTokenExpired()) {
        $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
        file_put_contents($credentialsPath, json_encode($client->getAccessToken()));
    }
    return $client;
}

After the first authentication (using the link created in the getClient() function), when the user lands to REDIRECT_URL, a callbackAuth() function is executed:

function callbackAuth() {
    $client = new Google_Client();
    $client->setApplicationName(APPLICATION_NAME);
    $client->setScopes(SCOPES);
    $client->setAuthConfig(CLIENT_SECRET_PATH);
    $client->setRedirectUri(REDIRECT_URL);
    $client->setAccessType('offline');
    $client->setApprovalPrompt('force');

    // Load previously authorized credentials from a file.
    $credentialsPath = expandHomeDirectory(CREDENTIALS_PATH);

    // Request authorization from the user.
    $authCode = trim($_GET['code']);

    // Exchange authorization code for an access token.
    $accessToken = $client->fetchAccessTokenWithAuthCode($authCode);

    // Store the credentials to disk.
    if(!file_exists(dirname($credentialsPath))) {
      mkdir(dirname($credentialsPath), 0700, true);
    }
    file_put_contents($credentialsPath, json_encode($accessToken));
    printf("Credentials saved to %s
", $credentialsPath);

    $client->setAccessToken($accessToken);

    return $client;
}

I tried to apply the solutions of other related stackoverflow question, but without results. Why does this error ocurr?

解决方案

Thanks to Alex Blex I was able to notice that the first time I receive the token has the refresh_token but after the first request, the refresh_token is not stored. The solution is the following (from this answer):

// Refresh the token if it's expired.
if ($client->isAccessTokenExpired()) {
    $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
    $newAccessToken = $client->getAccessToken();
    $accessToken = array_merge($accessToken, $newAccessToken);
    file_put_contents($credentialsPath, json_encode($accessToken));
}

The refresh_token is only returned on the first request. When you refresh the access token a second time it returns everything except the refresh_token and the file_put_contents removes the refresh_token when this happens the second time.

Modifying the code as following will merge in the original access token with the new one. This way you will be able to preserve your refresh_token for future requests.

这篇关于Google API 致命错误:未捕获的 LogicException:必须传入或设置刷新令牌作为 setAccessToken 的一部分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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