seo*_*.me 86 php google-api google-analytics-api access-token oauth-2.0
我一直在使用Google AnalyticsAPI(V3)并遇到了som错误.首先,一切都设置正确,并与我的测试帐户一起使用.但是,当我想从其他个人资料ID(相同的Google Accont/GA帐户)中获取数据时,我收到403错误.奇怪的是,来自某些GA帐户的数据将返回数据,而其他帐户会生成此错误.
我已经撤销了令牌并再次进行了身份验证,现在看来我可以从我的所有帐户中获取数据.问题解决了?不.由于访问密钥将过期,我将再次遇到同样的问题.
如果我理解正确,可以使用resfreshToken来获取新的authenticationTooken.
问题是,当我跑:
$client->refreshToken(refresh_token_key)
Run Code Online (Sandbox Code Playgroud)
返回以下错误:
Error refreshing the OAuth2 token, message: '{ "error" : "invalid_grant" }'
Run Code Online (Sandbox Code Playgroud)
我检查了refreshToken方法背后的代码,并将请求追溯回"apiOAuth2.php"文件.所有参数都正确发送.grant_type在方法中被硬编码为'refresh_token',所以我很难理解什么是错的.参数数组如下所示:
Array ( [client_id] => *******-uqgau8uo1l96bd09eurdub26c9ftr2io.apps.googleusercontent.com [client_secret] => ******** [refresh_token] => 1\/lov250YQTMCC9LRQbE6yMv-FiX_Offo79UXimV8kvwY [grant_type] => refresh_token )
Run Code Online (Sandbox Code Playgroud)
程序如下.
$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
Run Code Online (Sandbox Code Playgroud)
这是一个错误,还是我完全误解了什么?
小智 74
所以我终于想出了如何做到这一点.基本的想法是,您有第一次请求身份验证时获得的令牌.该第一个令牌具有刷新令牌.第一个原始令牌在一小时后到期.一小时后,您必须使用第一个令牌中的刷新令牌来获取新的可用令牌.您$client->refreshToken($refreshToken)
用来检索新令牌.我将这称为"临时令牌".您还需要存储此临时令牌,因为一小时后它也会过期并注意它没有与之关联的刷新令牌.为了获得新的临时令牌,您需要使用之前使用的方法并使用第一个令牌的refreshtoken.我在下面附上了代码,这是丑陋的,但我是新的...
//pull token from database
$tokenquery="SELECT * FROM token WHERE type='original'";
$tokenresult = mysqli_query($cxn,$tokenquery);
if($tokenresult!=0)
{
$tokenrow=mysqli_fetch_array($tokenresult);
extract($tokenrow);
}
$time_created = json_decode($token)->created;
$t=time();
$timediff=$t-$time_created;
echo $timediff."<br>";
$refreshToken= json_decode($token)->refresh_token;
//start google client note:
$client = new Google_Client();
$client->setApplicationName('');
$client->setScopes(array());
$client->setClientId('');
$client->setClientSecret('');
$client->setRedirectUri('');
$client->setAccessType('offline');
$client->setDeveloperKey('');
//resets token if expired
if(($timediff>3600)&&($token!=''))
{
echo $refreshToken."</br>";
$refreshquery="SELECT * FROM token WHERE type='refresh'";
$refreshresult = mysqli_query($cxn,$refreshquery);
//if a refresh token is in there...
if($refreshresult!=0)
{
$refreshrow=mysqli_fetch_array($refreshresult);
extract($refreshrow);
$refresh_created = json_decode($token)->created;
$refreshtimediff=$t-$refresh_created;
echo "Refresh Time Diff: ".$refreshtimediff."</br>";
//if refresh token is expired
if($refreshtimediff>3600)
{
$client->refreshToken($refreshToken);
$newtoken=$client->getAccessToken();
echo $newtoken."</br>";
$tokenupdate="UPDATE token SET token='$newtoken' WHERE type='refresh'";
mysqli_query($cxn,$tokenupdate);
$token=$newtoken;
echo "refreshed again";
}
//if the refresh token hasn't expired, set token as the refresh token
else
{
$client->setAccessToken($token);
echo "use refreshed token but not time yet";
}
}
//if a refresh token isn't in there...
else
{
$client->refreshToken($refreshToken);
$newtoken=$client->getAccessToken();
echo $newtoken."</br>";
$tokenupdate="INSERT INTO token (type,token) VALUES ('refresh','$newtoken')";
mysqli_query($cxn,$tokenupdate);
$token=$newtoken;
echo "refreshed for first time";
}
}
//if token is still good.
if(($timediff<3600)&&($token!=''))
{
$client->setAccessToken($token);
}
$service = new Google_DfareportingService($client);
Run Code Online (Sandbox Code Playgroud)
小智 41
问题出在刷新令牌中:
[refresh_token] => 1\/lov250YQTMCC9LRQbE6yMv-FiX_Offo79UXimV8kvwY
Run Code Online (Sandbox Code Playgroud)
当带有a的字符串'/'
获取时json encoded
,它会被a转义'\'
,因此您需要将其删除.
您的案例中的刷新令牌应为:
1/lov250YQTMCC9LRQbE6yMv-FiX_Offo79UXimV8kvwY
Run Code Online (Sandbox Code Playgroud)
我假设你已经完成的是你已经打印了谷歌发回的json字符串并将其复制并粘贴到你的代码中,因为如果你json_decode
这样,那么它将正确地'\'
为你删除!
Str*_*k3r 18
这是设置令牌的代码段,在此之前确保应将访问类型设置为脱机
if (isset($_GET['code'])) {
$client->authenticate();
$_SESSION['access_token'] = $client->getAccessToken();
}
Run Code Online (Sandbox Code Playgroud)
刷新令牌
$google_token= json_decode($_SESSION['access_token']);
$client->refreshToken($google_token->refresh_token);
Run Code Online (Sandbox Code Playgroud)
这将刷新你的令牌,你必须在会话中更新它,你可以做
$_SESSION['access_token']= $client->getAccessToken()
Run Code Online (Sandbox Code Playgroud)
jk.*_*jk. 17
访问类型应设置为offline
.state
是您为自己使用而设置的变量,而不是API的用途.
确保您拥有最新版本的客户端库并添加:
$client->setAccessType('offline');
Run Code Online (Sandbox Code Playgroud)
有关参数的说明,请参阅形成URL.
Dai*_*shi 14
@ uri-weg发布的答案对我有用,但由于我没有发现他的解释非常清楚,让我稍微改写一下.
在第一个访问权限序列期间,在回调中,当您到达收到身份验证代码的位置时,您还必须保存访问令牌和刷新令牌.
原因是google api仅在提示访问权限时才向您发送带有刷新令牌的访问令牌.下一个访问令牌将在没有任何刷新令牌的情况下发送(除非您使用该approval_prompt=force
选项).
您第一次收到的刷新令牌保持有效,直到用户撤消访问权限.
在简单的php中,回调序列的一个例子是:
// init client
// ...
$authCode = $_GET['code'];
$accessToken = $client->authenticate($authCode);
// $accessToken needs to be serialized as json
$this->saveAccessToken(json_encode($accessToken));
$this->saveRefreshToken($accessToken['refresh_token']);
Run Code Online (Sandbox Code Playgroud)
稍后,在简单的php中,连接序列将是:
// init client
// ...
$accessToken = $this->loadAccessToken();
// setAccessToken() expects json
$client->setAccessToken($accessToken);
if ($client->isAccessTokenExpired()) {
// reuse the same refresh token
$client->refreshToken($this->loadRefreshToken());
// save the new access token (which comes without any refresh token)
$this->saveAccessToken($client->getAccessToken());
}
Run Code Online (Sandbox Code Playgroud)
这是我在我的项目中使用的代码,它工作正常:
public function getClient(){
$client = new Google_Client();
$client->setApplicationName(APPNAME); // app name
$client->setClientId(CLIENTID); // client id
$client->setClientSecret(CLIENTSECRET); // client secret
$client->setRedirectUri(REDIRECT_URI); // redirect uri
$client->setApprovalPrompt('auto');
$client->setAccessType('offline'); // generates refresh token
$token = $_COOKIE['ACCESSTOKEN']; // fetch from cookie
// if token is present in cookie
if($token){
// use the same token
$client->setAccessToken($token);
}
// this line gets the new token if the cookie token was not present
// otherwise, the same cookie token
$token = $client->getAccessToken();
if($client->isAccessTokenExpired()){ // if token expired
$refreshToken = json_decode($token)->refresh_token;
// refresh the token
$client->refreshToken($refreshToken);
}
return $client;
}
Run Code Online (Sandbox Code Playgroud)
有同样的问题; 我的剧本昨天有效,因为一些奇怪的原因今天没有.没有变化.
显然这是因为我的系统时钟关闭了2.5(!!)秒,与NTP同步修复了它.
另请参阅:https://code.google.com/p/google-api-php-client/wiki/OAuth2#Solving_invalid_grant_errors
小智 5
有时刷新令牌我不是通过使用生成的$client->setAccessType ("offline");
。
尝试这个:
$client->setAccessType ("offline");
$client->setApprovalPrompt ("force");
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
120058 次 |
最近记录: |