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) 
返回以下错误:
Error refreshing the OAuth2 token, message: '{ "error" : "invalid_grant" }'
我检查了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 )
程序如下.
$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
这是一个错误,还是我完全误解了什么?
小智 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);
小智 41
问题出在刷新令牌中:
[refresh_token] => 1\/lov250YQTMCC9LRQbE6yMv-FiX_Offo79UXimV8kvwY
当带有a的字符串'/'获取时json encoded,它会被a转义'\',因此您需要将其删除.
您的案例中的刷新令牌应为:
1/lov250YQTMCC9LRQbE6yMv-FiX_Offo79UXimV8kvwY
我假设你已经完成的是你已经打印了谷歌发回的json字符串并将其复制并粘贴到你的代码中,因为如果你json_decode这样,那么它将正确地'\'为你删除!
Str*_*k3r 18
这是设置令牌的代码段,在此之前确保应将访问类型设置为脱机
if (isset($_GET['code'])) {
  $client->authenticate();
  $_SESSION['access_token'] = $client->getAccessToken();
}
刷新令牌
$google_token= json_decode($_SESSION['access_token']);
$client->refreshToken($google_token->refresh_token);
这将刷新你的令牌,你必须在会话中更新它,你可以做
 $_SESSION['access_token']= $client->getAccessToken()
jk.*_*jk. 17
访问类型应设置为offline.state是您为自己使用而设置的变量,而不是API的用途.
确保您拥有最新版本的客户端库并添加:
$client->setAccessType('offline');
有关参数的说明,请参阅形成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']);
稍后,在简单的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());
}
这是我在我的项目中使用的代码,它工作正常:
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;
}
有同样的问题; 我的剧本昨天有效,因为一些奇怪的原因今天没有.没有变化.
显然这是因为我的系统时钟关闭了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"); 
| 归档时间: | 
 | 
| 查看次数: | 120058 次 | 
| 最近记录: |