В настоящее время я столкнулся с очень странной проблемой, действительно, я слежу за этим же руководством ( https://developers.google.com/google-apps/calendar/quickstart/php ) из документации Google API. Я попробовал это дважды, в первый раз, когда он работает как прелесть, но после того, как токен доступа истекает, скрипт, предоставленный Google API, не смог его обновить.
TL; DR
Вот сообщение об ошибке:
sam@ssh:~$ php www/path/to/app/public/quickstart.php Fatal error: Uncaught exception 'LogicException' with message 'refresh token must be passed in or set as part of setAccessToken' in /home/pueblo/www/path/to/app/vendor/google/apiclient/src/Google/Client.php:258 Stack trace: #0 /home/pueblo/www/path/to/app/public/quickstart.php(55): Google_Client->fetchAccessTokenWithRefreshToken(NULL) #1 /home/pueblo/www/path/to/app/public/quickstart.php(76): getClient() #2 {main} thrown in /home/pueblo/www/path/to/app/vendor/google/apiclient/src/Google/Client.php on line 258
Вот часть php-скрипта из google, которую я изменил:
require_once __DIR__ . '/../vendor/autoload.php'; // I don't want the creds to be in my home folder, I prefer them in the app's root define('APPLICATION_NAME', 'LRS API Calendar'); define('CREDENTIALS_PATH', __DIR__ . '/../.credentials/calendar-php-quickstart.json'); define('CLIENT_SECRET_PATH', __DIR__ . '/../client_secret.json');
Я также изменил expandHomeDirectory
чтобы я мог «отключить» его, не изменяя слишком много кода:
function expandHomeDirectory($path) { $homeDirectory = getenv('HOME'); if (empty($homeDirectory)) { $homeDirectory = getenv('HOMEDRIVE') . getenv('HOMEPATH'); } return $path; // return str_replace('~', realpath($homeDirectory), $path); }
Поэтому, чтобы проверить, был ли я неправ или был Google, я сделал эксперимент: вчера вечером я запускаю скрипт quickstart из ssh, чтобы проверить, работает ли он, и это действительно так, поэтому я решил проверить это утро, если он все еще работает просто как это было до того, как я спал, и это было не так, я думаю, что что-то не так с quickstart.php
.
Надеюсь, кто-то может мне помочь, я уже проверил все остальные записи по теме, но они все устарели.
Я недавно получил ту же проблему, и я решил ее с этим.
<?php $client->setRedirectUri($this->_redirectURI); $client->setAccessType('offline'); $client->setApprovalPrompt('force');
Я объясняю ….. Refresh token не возвращается, потому что мы не принудительно утвердилиPrompt. В автономном режиме недостаточно. Мы должны принудительно утвердитьPrompt. Кроме того, после этих двух параметров необходимо установить redirectURI. Это сработало для меня.
Это моя полная функция
<?php private function getClient() { $client = new Google_Client(); $client->setApplicationName($this->projectName); $client->setScopes(SCOPES); $client->setAuthConfig($this->jsonKeyFilePath); $client->setRedirectUri($this->redirectUri); $client->setAccessType('offline'); $client->setApprovalPrompt('force'); // Load previously authorized credentials from a file. if (file_exists($this->tokenFile)) { $accessToken = json_decode(file_get_contents($this->tokenFile), true); } else { // Request authorization from the user. $authUrl = $client->createAuthUrl(); header('Location: ' . filter_var($authUrl, FILTER_SANITIZE_URL)); if (isset($_GET['code'])) { $authCode = $_GET['code']; // Exchange authorization code for an access token. $accessToken = $client->fetchAccessTokenWithAuthCode($authCode); header('Location: ' . filter_var($this->redirectUri, FILTER_SANITIZE_URL)); if(!file_exists(dirname($this->tokenFile))) { mkdir(dirname($this->tokenFile), 0700, true); } file_put_contents($this->tokenFile, json_encode($accessToken)); }else{ exit('No code found'); } } $client->setAccessToken($accessToken); // Refresh the token if it's expired. if ($client->isAccessTokenExpired()) { // save refresh token to some variable $refreshTokenSaved = $client->getRefreshToken(); // update access token $client->fetchAccessTokenWithRefreshToken($refreshTokenSaved); // pass access token to some variable $accessTokenUpdated = $client->getAccessToken(); // append refresh token $accessTokenUpdated['refresh_token'] = $refreshTokenSaved; //Set the new acces token $accessToken = $refreshTokenSaved; $client->setAccessToken($accessToken); // save to file file_put_contents($this->tokenFile, json_encode($accessTokenUpdated)); } return $client; }
Я столкнулся с такой же проблемой с новой библиотекой google api. Поиск решения привел следующую ссылку: RefreshToken Не получать отправки после того, как я получу новый токен google sheet API
Основываясь на этой информации, я изменил часть кода быстрого запуска, чтобы соответствовать моим потребностям. После первого разрешения с Google я получил drive-php-quickstart.json, который содержит refresh_token, срок действия которого истекает через 3600 секунд или один час. Ток обновления выдается только один раз, поэтому, если он потерян, требуется повторная авторизация. Итак, чтобы это всегда было в драйвере-php-quickstart.json, я сделал следующее:
// Refresh the token if it's expired. if ($client->isAccessTokenExpired()) { // save refresh token to some variable $refreshTokenSaved = $client->getRefreshToken(); // update access token $client->fetchAccessTokenWithRefreshToken($refreshTokenSaved); // pass access token to some variable $accessTokenUpdated = $client->getAccessToken(); // append refresh token $accessTokenUpdated['refresh_token'] = $refreshTokenSaved; // save to file file_put_contents($credentialsPath, json_encode($accessTokenUpdated)); }
просто обновление для тех, у кого возникли проблемы с этим сообщением, в основном это потому, что только первая команда fetchAccessTokenWithAuthCode () генерирует credencials, который содержит токен обновления (технически вечно действительный – нет 2-часовой проверки, если вы не отмените его). Когда вы получаете новый, он заменяет исходный, но он не содержит токен обновления, который ему нужен, поэтому в следующий раз, когда вам нужно обновить токен, он выйдет из строя. Это можно легко устранить, заменив функцию обновления на, например, следующим образом:
// Refresh the token if it's expired. if ($client->isAccessTokenExpired()) { $oldAccessToken=$client->getAccessToken(); $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken()); $accessToken=$client->getAccessToken(); $accessToken['refresh_token']=$oldAccessToken['refresh_token']; file_put_contents($credentialsPath, json_encode($accessToken)); }
Теперь каждый раз, когда вы обновляете токен доступа, токен обновления также передается.
У меня были те же проблемы и, наконец, я пошел на это:
Предыстория:
Я получил ту же ошибку. Вот что я нашел:
Эта ошибка:
PHP Неустранимая ошибка: Uncaught LogicException: токен обновления должен быть передан или установлен как часть setAccessToken в /Library/WebServer/Documents/Sites/test/scripts/vendor/google/apiclient/src/Google/Client.php:267
Является ссылкой на токен доступа к обновлению (aka Refresh):
$client->fetchAccessTokenWithRefreshToken($refreshTokenSaved);
Почему это провалилось? Короче говоря, я понял, когда я распечатал массив $ accessToken, который исходит от декодирования этого json-файла (по быстрому стартовому коду, который вы отправили / который появился из Google)
Учетные данные / календарь-PHP-quickstart.json
Я обнаружил ошибку из-за того, как массив accessToken печатает, когда у меня print_r:
Array ( [access_token] => Array ([access_token] => xyz123 [token_type] => Носитель [expires_in] => 3600 [refresh_token] => xsss112222 [created] => 1511379484)
)
Решение:
$ refreshToken = $ accessToken ["access_token"] ["refresh_token"];
прямо перед этой строкой:
$client->fetchAccessTokenWithRefreshToken($refreshToken);
Я могу, наконец, обновить токен по мере необходимости, когда он истечет через час. Я думаю, что разработчики этой статьи предположили, что массив печатает как:
Массив ([access_token] => xyz123 [token_type] => Носитель [expires_in] => 3600 [refresh_token] => xsss112222 [created] => 1511379484)
поэтому они думали, что вы могли бы просто сделать $ accessToken ["refresh_token"]; Это неверно.
Теперь у нас есть допустимое значение для $ refreshToken, поэтому ошибка должна исчезнуть, если вы это сделаете. Я также обновил автора через ссылку обратной связи, чтобы сообщить об этом, если другие разработчики php столкнутся с этой проблемой. Надеюсь, это помогает кому-то. Мои извинения, если я отформатировал этот пост плохо, я новичок в SE, я просто хотел поделиться, поскольку я наконец получил это, чтобы работать.
Google обновил свой PHP Quickstart с помощью улучшенного метода для этого:
Ниже приведен фрагмент:
// Exchange authorization code for an access token. $accessToken = $client->fetchAccessTokenWithAuthCode($authCode); $client->setAccessToken($accessToken); // Refresh the token if it's expired. if ($client->isAccessTokenExpired()) { $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken()); file_put_contents($credentialsPath, json_encode($client->getAccessToken())); }
В моем случае я забыл установить тип доступа как «автономный», без которого токен обновления не генерировался.
$client->setAccessType('offline');
Как только это будет сделано, образец кода, указанный в документации Google, будет работать.
// Exchange authorization code for an access token. // "refresh_token" is returned along with the access token $accessToken = $client->fetchAccessTokenWithAuthCode($authCode); $client->setAccessToken($accessToken); // Refresh the token if it's expired. if ($client->isAccessTokenExpired()) { $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken()); file_put_contents($credentialsPath, json_encode($client->getAccessToken())); }