Tenho brincado com a API do Google Analytics (V3) e encontrei alguns erros. Em primeiro lugar, tudo está configurado corretamente e funcionou com minha conta de teste. Mas quando eu quero obter dados de outro ID de perfil (mesma conta do Google / GA), recebo um erro 403. O estranho é que os dados de algumas contas do GA retornarão dados enquanto outras geram esse erro.
Revoguei o token e autentiquei mais uma vez e agora parece que posso obter dados de todas as minhas contas. Problema resolvido? Não. Como a chave de acesso vai expirar, vou ter o mesmo problema novamente.
Se eu entendi as coisas direito, pode-se usar o resfreshToken para obter um novo authenticationTooken.
O problema é, quando eu executo:
$client->refreshToken(refresh_token_key)
o seguinte erro é retornado:
Error refreshing the OAuth2 token, message: '{ "error" : "invalid_grant" }'
Verifiquei o código por trás do método refreshToken e rastreei a solicitação de volta ao arquivo “apiOAuth2.php”. Todos os parâmetros são enviados corretamente. O grant_type é codificado para 'refresh_token' dentro do método, então é difícil para mim entender o que está errado. A matriz de parâmetros se parece com isto:
Array ( [client_id] => *******-uqgau8uo1l96bd09eurdub26c9ftr2io.apps.googleusercontent.com [client_secret] => ******** [refresh_token] => 1\/lov250YQTMCC9LRQbE6yMv-FiX_Offo79UXimV8kvwY [grant_type] => refresh_token )
O procedimento é o seguinte.
$client = new apiClient();
$client->setClientId($config['oauth2_client_id']);
$client->setClientSecret($config['oauth2_client_secret']);
$client->setRedirectUri($config['oauth2_redirect_uri']);
$client->setScopes('https://www.googleapis.com/auth/analytics.readonly');
$client->setState('offline');
$client->setAccessToken($config['token']); // The access JSON object.
$client->refreshToken($config['refreshToken']); // Will return error here
Isso é um bug ou eu entendi algo completamente errado?
fonte
Respostas:
Então, finalmente descobri como fazer isso. A ideia básica é que você tenha o token que receberá na primeira vez que solicitar autenticação. Este primeiro token possui um token de atualização. O primeiro token original expira após uma hora. Depois de uma hora, você deve usar o token de atualização do primeiro token para obter um novo token utilizável. Você usa
$client->refreshToken($refreshToken)
para recuperar um novo token. Vou chamar isso de "token temporário". Você também precisa armazenar este token temporário porque depois de uma hora ele também expira e observe que não há um token de atualização associado a ele. Para obter um novo token temporário, você precisa usar o método usado antes e usar o refreshtoken do primeiro token. Anexei o código abaixo, que é feio, mas sou novo nisso ...fonte
$client->isAccessTokenExpired()
ainda só verificará os tempos mantidos localmente para ver se acha que o token expirou. O token ainda pode ter expirado e o aplicativo local só saberá realmente quando tentar usá-lo. Nesse caso, o cliente API retornará uma exceção e não atualizará automaticamente o token.O problema está no token de atualização:
Quando uma string com um
'/'
é obtidojson encoded
, ele é escapado com um'\'
, portanto, você precisa removê-lo.O token de atualização no seu caso deve ser:
O que estou supondo que você fez é que imprimiu a string json que o Google enviou de volta e copiou e colou o token em seu código porque, se você fizer
json_decode
isso, ele removerá corretamente o'\'
para você!fonte
aqui está o snippet para definir o token, antes disso, certifique-se de que o tipo de acesso deve ser definido como offline
Para atualizar o token
isso irá atualizar seu token, você deve atualizá-lo na sessão para que você possa fazer
fonte
O tipo de acesso deve ser definido como
offline
.state
é uma variável que você define para seu próprio uso, não para uso da API.Certifique-se de ter a versão mais recente da biblioteca cliente e adicione:
Consulte Formando a URL para obter uma explicação dos parâmetros.
fonte
$client
($client = new apiClient();
) para usar o token de atualização?$client->setApprovalPrompt('force')
, bem como$client->setAccessType('offline')
obter um novo token de atualização durante a autorização. Sem forçar o usuário a aprovar o escopo de acesso, o Google presume que você continuará usando o token de atualização antigo.A resposta postada por @uri-weg funcionou para mim, mas como não achei as explicações dele muito claras, deixe-me reformulá-las um pouco.
Durante a primeira sequência de permissão de acesso, no retorno de chamada, quando você chegar ao ponto em que recebe um código de autenticação, deve salvar o token de acesso e o token de atualização também.
O motivo é que a API do Google envia a você um token de acesso com um token de atualização apenas ao solicitar permissão de acesso. Os próximos tokens de acesso serão enviados sem nenhum token de atualização (a menos que você use a
approval_prompt=force
opção).O token de atualização que você recebeu na primeira vez permanece válido até que o usuário revogue a permissão de acesso.
Em php simplista, um exemplo de sequência de retorno de chamada seria:
E mais tarde, em php simplista, a sequência de conexão seria:
fonte
// setAccessToken() expects json
fosse o suficiente. Ou é para outra parte do código?Aqui está o código que estou usando em meu projeto e está funcionando bem:
fonte
Tive o mesmo problema; meu script que funcionou ontem, por alguma razão estranha não funcionou hoje. Sem alterações.
Aparentemente, isso ocorreu porque o relógio do meu sistema estava atrasado em 2,5 (!!) segundos, a sincronização com o NTP corrigiu isso.
Veja também: https://code.google.com/p/google-api-php-client/wiki/OAuth2#Solving_invalid_grant_errors
fonte
sudo apt-get install ntp
na minha máquina Debian para instalar o NTP. Ele sincronizou o relógio e o problema foi resolvido.Para sua informação: a 3.0 Google Analytics API atualizará automaticamente o token de acesso se você tiver um token de atualização quando ele expirar, para que seu script nunca precise
refreshToken
.(Veja o
Sign
função emauth/apiOAuth2.php
)fonte
Às vezes, atualizar o token não foi gerado usando
$client->setAccessType ("offline");
.Experimente isto:
fonte
Usei o exemplo por smartcodes com a versão atual da API do Google, mas aquele não funcionou. Acho que a API dele está muito desatualizada.
Então, acabei de escrever minha própria versão, com base em um dos exemplos de API ... Ele produz token de acesso, token de solicitação, tipo de token, token de ID, tempo de expiração e tempo de criação como strings
Se suas credenciais de cliente e chave de desenvolvedor estiverem corretas, este código deve funcionar imediatamente.
fonte
$redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
. Por que você redireciona para a mesma página? isso é necessário?Eu tenho o mesmo problema com google / google-api-php-client v2.0.0-RC7 e depois de pesquisar por 1 hora, resolvi esse problema usando json_encode assim:
fonte
Isso aqui funciona muito bem, talvez possa ajudar alguém:
index.php
oauth2callback.php
client.php
action.php
fonte
O Google fez algumas alterações desde que esta pergunta foi postada originalmente.
Aqui está meu exemplo de trabalho atualmente.
fonte
Eu uso google-api-php-client v2.2.2 Recebo um novo token com a
fetchAccessTokenWithRefreshToken();
chamada de função if sem parâmetros, ele retorna um token de acesso atualizado e o token atualizado não é perdido.fonte
Você precisa salvar o token de acesso ao arquivo ou banco de dados como uma string json durante a solicitação de autorização inicial e definir o tipo de acesso como offline
$client->setAccessType("offline")
Em seguida, durante as solicitações de API subsequentes, pegue o token de acesso de seu arquivo ou banco de dados e passe-o ao cliente:
Agora você precisa verificar se o token expirou:
A
fetchAccessTokenWithRefreshToken()
função fará o trabalho para você e fornecerá um novo token de acesso, salvando-o de volta em seu arquivo ou banco de dados.fonte
De acordo com a autenticação no google: OAuth2 continua retornando 'invalid_grant'
"Você deve reutilizar o token de acesso obtido após a primeira autenticação bem-sucedida. Você receberá um erro invalid_grant se o token anterior ainda não tiver expirado. Armazene-o em algum lugar para que possa reutilizá-lo."
espero que ajude
fonte
use o seguinte snippet de código para obter seu token de atualização
fonte