php - passed - El token de actualización de Google API Client debe pasarse o establecerse como parte de setAccessToken.
invalid token format google api (6)
Actualmente estoy enfrentando un problema muy extraño, de hecho, he estado siguiendo esta misma guía ( https://developers.google.com/google-apps/calendar/quickstart/php ) de la documentación de la API de Google. Lo probé dos veces, la primera vez funciona como un amuleto, pero después de que el token de acceso expiró, el script proporcionado directamente por Google API Doc no pudo actualizarlo.
TL; DR
Aquí está el mensaje de error:
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
Aquí está la parte del script php de google que he modificado:
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'');
También modifiqué el expandHomeDirectory
para poder "deshabilitarlo" sin modificar demasiado código:
function expandHomeDirectory($path) {
$homeDirectory = getenv(''HOME'');
if (empty($homeDirectory)) {
$homeDirectory = getenv(''HOMEDRIVE'') . getenv(''HOMEPATH'');
}
return $path;
// return str_replace(''~'', realpath($homeDirectory), $path);
}
Entonces, para verificar si estaba equivocado o si Google lo estaba haciendo, hice un experimento: ayer por la noche lancé el script de inicio rápido de ssh para comprobar si funcionaba, y de hecho lo estaba, así que decidí consultar esta mañana si todavía funcionaba como era antes de dormir y no fue así, creo que hay algo mal con quickstart.php
de Google.
Espero que alguien pueda ayudarme, ya he comprobado todas las otras publicaciones sobre el tema, pero están desactualizadas.
Google ha actualizado su PHP Quickstart , con un método mejorado para manejar esto:
Fragmento a continuación:
// 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()));
}
En mi caso, había olvidado establecer el tipo de acceso como "fuera de línea" sin el cual no se generaba el token de actualización.
$client->setAccessType(''offline'');
Una vez hecho esto, el código de muestra proporcionado en la documentación de google funcionará.
// 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()));
}
solo una actualización para cualquiera que tenga problemas con este mensaje, principalmente porque solo el primer comando fetchAccessTokenWithAuthCode () genera credenciales que contienen el token de actualización (técnicamente válido para siempre; no hay 2 horas de validez si no lo revoca). Cuando obtienes el nuevo, reemplaza al original, pero no contiene el token de actualización que necesita, así que la próxima vez que necesites actualizar el token, se bloqueará. Esto se puede solucionar fácilmente reemplazando la función de actualización para, por ejemplo, esto:
// 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));
}
Ahora, cada vez que actualizas el token de acceso, también se pasa tu token de actualización.
He enfrentado el mismo problema con la nueva biblioteca de google api. La búsqueda de la solución trajo el siguiente enlace: RefreshToken No me envían de vuelta después de recibir el nuevo token de hojas de google API
En base a esa información, he modificado la parte del código de inicio rápido para que se ajuste a mis necesidades. Después de la primera autorización con Google, obtuve drive-php-quickstart.json que contiene refresh_token que expira en 3600 segundos o una hora. El token de actualización se emite solo una vez, por lo que si se pierde, se requiere una nueva autorización. Entonces, para tenerlo siempre en drive-php-quickstart.json, he hecho lo siguiente:
// 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));
}
Recientemente tuve el mismo problema y lo resolví con esto.
<?php
$client->setRedirectUri($this->_redirectURI);
$client->setAccessType(''offline'');
$client->setApprovalPrompt(''force'');
Explico ..... La ficha de actualización no se devuelve porque no hemos forzado la aprobaciónPrompt. El modo fuera de línea no es suficiente. Debemos forzar la aprobaciónPrompt. También el redirectURI debe establecerse después de estas dos opciones. Funcionó para mí
Esta es mi función completa
<?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;
}
Tuve los mismos problemas y finalmente voy a trabajar:
Trasfondo:
Recibí el mismo error. Esto es lo que encontré:
Este error:
Error fatal de PHP: Uncaught LogicException: el token de actualización debe pasarse o establecerse como parte de setAccessToken en /Library/WebServer/Documents/Sites/test/scripts/vendor/google/apiclient/src/Google/Client.php:267
Hace referencia al método token de acceso de actualización (también conocido como Refresh):
$client->fetchAccessTokenWithRefreshToken($refreshTokenSaved);
¿Por qué estaba fallando? Para resumir, me di cuenta cuando imprimí la matriz $ accessToken, que proviene de la decodificación de este archivo json (según el código de inicio rápido que publicó / que proviene de google)
credenciales / calendar-php-quickstart.json
Encontré el error debido a cómo se imprime la matriz accessToken cuando imprimo_r:
Array ( [access_token] => Array ([access_token] => xyz123 [token_type] => Portador [expires_in] => 3600 [refresh_token] => xsss112222 [created] => 1511379484)
)
Solución:
$ refreshToken = $ accessToken ["access_token"] ["refresh_token"];
justo antes de esta línea:
$client->fetchAccessTokenWithRefreshToken($refreshToken);
Finalmente puedo actualizar el token según sea necesario cuando expira en una hora. Creo que los desarrolladores de este artículo asumieron que la matriz imprime como:
Array ([access_token] => xyz123 [token_type] => Portador [expires_in] => 3600 [refresh_token] => xsss112222 [created] => 1511379484)
entonces pensaron que simplemente podías hacer $ accessToken ["refresh_token"]; Eso no es correcto.
Ahora tenemos un valor válido para $ refreshToken, por lo que el error debería desaparecer si lo hace. También actualicé al autor a través del enlace de comentarios para informarles sobre esto, en caso de que otros desarrolladores de php encuentren este problema. Espero que esto ayude a alguien. Mis disculpas si formateé este post de forma deficiente. Soy nuevo en SE, solo quería compartirlo, ya que finalmente conseguí que esto funcionara.