Google API致命错误:未捕获LogicException:刷新令牌必须传入或设置为setAccessToken的一部分 [英] Google API Fatal error: Uncaught LogicException: refresh token must be passed in or set as part of setAccessToken
问题描述
使用 PHP快速入门代码,我发现了一个问题:何时令牌需要刷新,代码返回以下错误:
Working with the PHP Quickstart code, I found a problem: when the token needs to be refreshed, the code returns the following error:
致命错误:未捕获LogicException:刷新令牌必须在$ b中传递$ b或作为setAccessToken的一部分设置在
/app/vendor/google/apiclient/src/Google/Client.php:258
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
堆栈跟踪中:
#0 /app/gmail.php(32):
Google_Client-> fetchAccessTokenWithRefreshToken(NULL)
#0 /app/gmail.php(32): Google_Client->fetchAccessTokenWithRefreshToken(NULL)
#1 /app/test.php(14):getClient()
#1 /app/test.php(14): getClient()
#2 {main}抛出
/ app / vendor / google /第258行上的apiclient / src / Google / Client.php
#2 {main} thrown in /app/vendor/google/apiclient/src/Google/Client.php on line 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('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;
}
首次验证后(使用在 getClient()
函数),当用户登陆到 REDIRECT_URL
时,会出现 callbackAuth()
执行函数:
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\n", $credentialsPath);
$client->setAccessToken($accessToken);
return $client;
}
我尝试应用其他相关\">stackoverflow问题,但没有结果。为什么会发生此错误?
I tried to apply the solutions of other related stackoverflow question, but without results. Why does this error ocurr?
推荐答案
感谢 Alex Blex 我注意到我第一次收到令牌时有 refresh_token
,但是在第一个请求之后, refresh_token
未存储。解决方案如下(来自此答案):
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));
}
refresh_token仅在第一次请求时返回。当您
第二次刷新访问令牌时,它将返回除
以外的所有内容,refresh_token和file_put_contents会在第二次发生此操作时删除refresh_token
。
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.
按如下所示修改代码,会将原始访问
令牌与新令牌合并。这样,您将能够
保留您的refresh_token以供将来使用。
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屋!