【问题标题】:How to refresh token with Google API client?如何使用 Google API 客户端刷新令牌?
【发布时间】:2012-03-03 17:09:54
【问题描述】:

我一直在使用 Google Analytics API (V3) 并遇到了一些错误。首先,一切都设置正确并与我的测试帐户一起使用。但是,当我想从另一个配置文件 ID(相同的 Google 帐户/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

这是一个错误,还是我完全误解了什么?

【问题讨论】:

  • 不知道是错误还是什么,但我目前正在使用原始 CURL http 请求刷新访问令牌,并且工作正常。
  • 搜索...你找到这个了吗?同样的问题。
  • @gremo 你能分享你在这里使用的原始 CURL http 请求吗?真的很有帮助。谢谢!

标签: php google-api oauth-2.0 access-token google-analytics-api


【解决方案1】:

所以我终于想出了如何做到这一点。基本思想是您拥有第一次请求身份验证时获得的令牌。第一个令牌有一个刷新令牌。第一个原始令牌在一小时后过期。一小时后,您必须使用第一个令牌中的刷新令牌来获取新的可用令牌。您使用$client->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);

【讨论】:

  • 你应该使用 $client->isAccessTokenExpired() 而不是检查 3600 秒
  • 小更新。在最新版本中,当您请求刷新令牌时,现在返回的新访问令牌带有新的刷新令牌。所以本质上,你可以使用更新后的 json token 来替换之前的 json token,不再需要保留初始访问 token。 .
  • 请注意,$client-&gt;isAccessTokenExpired() 仍然只会检查本地持有的时间,以查看它是否认为令牌已过期。令牌可能仍然过期,本地应用程序只有在尝试使用它时才会真正知道。在这种情况下,API 客户端将返回异常,并且不会自动刷新令牌。
  • @Jason 我认为现在不正确。我在“isAccessTokenExpired”方法中看到以下返回语句:return ($created + ($this->token['expires_in'] - 30))
【解决方案2】:

问题出在刷新令牌中:

[refresh_token] => 1\/lov250YQTMCC9LRQbE6yMv-FiX_Offo79UXimV8kvwY

当带有'/' 的字符串得到json encoded 时,它会被'\' 转义,因此您需要将其删除。

在您的情况下,刷新令牌应该是:

1/lov250YQTMCC9LRQbE6yMv-FiX_Offo79UXimV8kvwY

我假设你所做的是你已经打印了谷歌发回的 json 字符串并将令牌复制并粘贴到你的代码中,因为如果你 json_decode 它那么它将正确删除 '\'给你!

【讨论】:

  • 太棒了,让我开心!节省时间!
  • 你拯救了我的一天!
  • 我希望我能投票 100 次。在尝试了一切使令牌工作之后,我盯着“错误授权”消息几个小时后,正准备用键盘在墙上打一个洞。他妈的谷歌人,为什么要使用斜线,为什么?
【解决方案3】:

这里是设置令牌的sn-p,在此之前确保访问类型应该设置为离线

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()

【讨论】:

  • 你用这个让我很开心 :) 非常感谢,比我想象的要简单得多,因为我花了很多时间无处可去 :D
【解决方案4】:

访问类型应设置为offlinestate 是您设置的变量供自己使用,而不是 API 使用。

确保您拥有latest version of the client library 并添加:

$client->setAccessType('offline');

有关参数说明,请参阅Forming the URL

【讨论】:

  • 谢谢jk。我已经下载了最新版本并撤销了我帐户对该应用程序的访问权限。然后我再次授予访问权限并存储了 accessToken 和 refreshToken。问题是,我总是得到一个 refreshToken,即使 setAccessType 已被省略。无论如何,当我运行 $client->refreshToken(refresh-token-key) 时,我仍然收到“invalid_grant”错误。我检查了 auth-url,它默认为“强制”。如果我将其更改为“自动”并运行身份验证方法,我不会被重定向,因为我已经授予访问权限。但是响应是一个没有刷新的 accessToken 。有什么想法吗?
  • @seorch.me 听起来很疯狂,但您是否可能必须设置一个新的$client ($client = new apiClient();) 才能使用刷新令牌?
  • @seorch.me 您必须设置$client-&gt;setApprovalPrompt('force')$client-&gt;setAccessType('offline') 才能在授权期间获取新的刷新令牌。在不强制用户批准访问范围的情况下,Google 假定您将继续使用旧的刷新令牌。
【解决方案5】:

@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());
}

【讨论】:

  • 完美,辛苦了。我要说的唯一一件事是您应该解释您需要传递 json 对象而不仅仅是将令牌作为字符串传递。
  • @OliverBayes-Shelton 嗨。谢谢。我认为// setAccessToken() expects json 就足够了。还是代码的另一部分?
  • 这对我很有用,但是你知道这段代码是否可以处理由于超过 50 次令牌刷新的限制而导致令牌过期的情况吗?可以在此处找到有关“令牌过期”的详细信息:developers.google.com/identity/protocols/OAuth2#expiration
  • 似乎最新的2.0版本现在正在返回访问令牌数组中的刷新令牌。这意味着保存访问令牌也会保存刷新令牌,因为包含刷新令牌。为了响应刷新令牌过期,我猜这将不得不进行测试和明确处理 - 记住 50 个限制是“每个用户每个客户端”,即每个客户端 50 个,所以你不太可能点击它,特别是如果您使用包含的范围来组合标记。
【解决方案6】:

这是我在项目中使用的代码,它运行良好:

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;
}

【讨论】:

    【解决方案7】:

    有同样的问题;我昨天工作的脚本,由于某种奇怪的原因,今天没有。没有变化。

    显然这是因为我的系统时钟关闭了 2.5 (!!) 秒,与 NTP 同步修复了它。

    另请参阅:https://code.google.com/p/google-api-php-client/wiki/OAuth2#Solving_invalid_grant_errors

    【讨论】:

    • 这个答案对我帮助很大,伙计。你可能为我节省了很多时间。很多!谢谢!我刚刚在我的 Debian 机器上执行了sudo apt-get install ntp 来安装 NTP。它同步了时钟,问题就解决了。
    【解决方案8】:

    有时刷新令牌不是使用$client-&gt;setAccessType ("offline"); 生成的。

    试试这个:

    $client->setAccessType ("offline");
    $client->setApprovalPrompt ("force"); 
    

    【讨论】:

    • 更具体地说,刷新令牌似乎包含在您的 first 授权中。如果你保存然后使用它,我相信(根据其他人,未验证)刷新令牌会继续返回。该文档现在还表示,如果他们有刷新令牌,他们将自动刷新访问令牌,这意味着只需安全地管理刷新令牌即可。 setApprovalPrompt('force') 确实会强制随后发出刷新令牌;没有它,您将无法获得另一个。
    【解决方案9】:

    仅供参考:如果您有一个过期令牌,3.0 Google Analytics API 将自动刷新访问令牌,因此您的脚本永远不需要refreshToken

    (参见auth/apiOAuth2.php 中的Sign 函数)

    【讨论】:

    • “自动刷新”意味着我只需要请求 getAccessToken() 并且我会得到一个刷新的回来吗?但是我必须先从数据库中设置刷新令牌,对吧?否则刷新将在没有刷新令牌的情况下工作,我认为这不会工作
    【解决方案10】:

    初始授权请求时需要将访问令牌保存为json字符串,并将访问类型设置为离线$client-&gt;setAccessType("offline")

    然后,在后续的 api 请求期间,从您的文件或数据库中获取访问令牌并将其传递给客户端:

    $accessToken = json_decode($row['token'], true);
    $client->setAccessToken($accessToken);
    

    现在您需要检查令牌是否已过期:

    if ($client->isAccessTokenExpired()) {
        // access token has expired, use the refresh token to obtain a new one
        $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
        // save the new token to file or db
        // ...json_encode($client->getAccessToken())
    

    fetchAccessTokenWithRefreshToken() 函数将为您完成工作并提供新的访问令牌,将其保存回您的文件或数据库。

    【讨论】:

      【解决方案11】:

      我在当前版本的 Google API 中使用了 smartcodes 的示例,但该示例不起作用。我认为他的 API 已经过时了。

      所以,我只是根据其中一个 API 示例编写了自己的版本...它将访问令牌、请求令牌、令牌类型、ID 令牌、过期时间和创建时间作为字符串输出

      如果您的客户端凭据和开发人员密钥正确,则此代码应该可以立即使用。

      <?php
      // Call set_include_path() as needed to point to your client library.
      require_once 'google-api-php-client/src/Google_Client.php';
      require_once 'google-api-php-client/src/contrib/Google_Oauth2Service.php';
      session_start();
      
      $client = new Google_Client();
      $client->setApplicationName("Get Token");
      // Visit https://code.google.com/apis/console?api=plus to generate your
      // oauth2_client_id, oauth2_client_secret, and to register your oauth2_redirect_uri.
      $oauth2 = new Google_Oauth2Service($client);
      
      if (isset($_GET['code'])) {
          $client->authenticate($_GET['code']);
          $_SESSION['token'] = $client->getAccessToken();
          $redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
          header('Location: ' . filter_var($redirect, FILTER_SANITIZE_URL));
          return;
      }
      
      if (isset($_SESSION['token'])) {
          $client->setAccessToken($_SESSION['token']);
      }
      
      if (isset($_REQUEST['logout'])) {
          unset($_SESSION['token']);
          $client->revokeToken();
      }
      ?>
      <!doctype html>
      <html>
          <head><meta charset="utf-8"></head>
          <body>
              <header><h1>Get Token</h1></header>
              <?php
              if ($client->getAccessToken()) {
                  $_SESSION['token'] = $client->getAccessToken();
                  $token = json_decode($_SESSION['token']);
                  echo "Access Token = " . $token->access_token . '<br/>';
                  echo "Refresh Token = " . $token->refresh_token . '<br/>';
                  echo "Token type = " . $token->token_type . '<br/>';
                  echo "Expires in = " . $token->expires_in . '<br/>';
                  echo "ID Token = " . $token->id_token . '<br/>';
                  echo "Created = " . $token->created . '<br/>';
                  echo "<a class='logout' href='?logout'>Logout</a>";
              } else {
                  $authUrl = $client->createAuthUrl();
                  print "<a class='login' href='$authUrl'>Connect Me!</a>";
              }
              ?>
          </body>
      </html>
      

      【讨论】:

      • 拜托,你能解释一下为什么这行:$redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];。为什么你重定向到同一页面?这有必要吗?
      • @Tropicalista :不需要重新加载页面本身,但这是通常实现身份验证流程的方式。
      • 但是如果访问令牌过期,您没有使用刷新令牌来获取新的访问令牌。
      【解决方案12】:

      自此问题最初发布以来,Google 已进行了一些更改。

      这是我当前工作的示例。

          public function update_token($token){
      
          try {
      
              $client = new Google_Client();
              $client->setAccessType("offline"); 
              $client->setAuthConfig(APPPATH . 'vendor' . DIRECTORY_SEPARATOR . 'google' . DIRECTORY_SEPARATOR . 'client_secrets.json');  
              $client->setIncludeGrantedScopes(true); 
              $client->addScope(Google_Service_Calendar::CALENDAR); 
              $client->setAccessToken($token);
      
              if ($client->isAccessTokenExpired()) {
                  $refresh_token = $client->getRefreshToken();
                  if(!empty($refresh_token)){
                      $client->fetchAccessTokenWithRefreshToken($refresh_token);      
                      $token = $client->getAccessToken();
                      $token['refresh_token'] = json_decode($refresh_token);
                      $token = json_encode($token);
                  }
              }
      
              return $token;
      
          } catch (Exception $e) { 
              $error = json_decode($e->getMessage());
              if(isset($error->error->message)){
                  log_message('error', $error->error->message);
              }
          }
      
      
      }
      

      【讨论】:

        【解决方案13】:

        我对 google/google-api-php-client v2.0.0-RC7 有同样的问题 搜索 1 小时后,我使用 json_encode 解决了这个问题 像这样:

            if ($client->isAccessTokenExpired()) {
                $newToken = json_decode(json_encode($client->getAccessToken()));
                $client->refreshToken($newToken->refresh_token);
                file_put_contents(storage_path('app/client_id.txt'), json_encode($client->getAccessToken()));
            }
        

        【讨论】:

          【解决方案14】:

          这里的效果很好,也许它可以帮助任何人:

          index.php

          session_start();
          
          require_once __DIR__.'/client.php';
          
          if(!isset($obj->error) && isset($_SESSION['access_token']) && $_SESSION['access_token'] && isset($obj->expires_in)) {
          ?>
          <!DOCTYPE html>
          <html>
          <head>
          <title>Google API Token Test</title>
          <meta charset='utf-8' />
          <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
          <script>
          search('Music Mix 2010');
          function search(q) {
              $.ajax({
                  type: 'GET',
                  url: 'action.php?q='+q,
                  success: function(data) {
                      if(data == 'refresh') location.reload();
                      else $('#response').html(JSON.stringify(JSON.parse(data)));
                  }
              });
          }
          </script>
          </head>
          <body>
          <div id="response"></div>
          </body>
          </html>
          <?php
          }
          else header('Location: '.filter_var('https://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']).'/oauth2callback.php', FILTER_SANITIZE_URL));
          ?>
          

          oauth2callback.php

          require_once __DIR__.'/vendor/autoload.php';
          
          session_start();
          
          $client = new Google_Client();
          $client->setAuthConfigFile('auth.json');
          $client->setAccessType('offline');
          $client->setApprovalPrompt('force');
          $client->setRedirectUri('https://'.filter_var($_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'], FILTER_SANITIZE_URL));
          $client->addScope(Google_Service_YouTube::YOUTUBE_FORCE_SSL);
          
          if(isset($_GET['code']) && $_GET['code']) {
              $client->authenticate(filter_var($_GET['code'], FILTER_SANITIZE_STRING));
              $_SESSION['access_token'] = $client->getAccessToken();
              $_SESSION['refresh_token'] = $_SESSION['access_token']['refresh_token'];
              setcookie('refresh_token', $_SESSION['refresh_token'], time()+60*60*24*180, '/', filter_var($_SERVER['HTTP_HOST'], FILTER_SANITIZE_URL), true, true);
              header('Location: '.filter_var('https://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']), FILTER_SANITIZE_URL));
              exit();
          }
          else header('Location: '.filter_var($client->createAuthUrl(), FILTER_SANITIZE_URL));
          exit();
          
          ?>
          

          client.php

          // https://developers.google.com/api-client-library/php/start/installation
          require_once __DIR__.'/vendor/autoload.php';
          
          $client = new Google_Client();
          $client->setAuthConfig('auth.json');
          $client->setAccessType('offline');
          $client->setApprovalPrompt('force');
          $client->addScope(Google_Service_YouTube::YOUTUBE_FORCE_SSL);
          
          // Delete Cookie Token
          #setcookie('refresh_token', @$_SESSION['refresh_token'], time()-1, '/', filter_var($_SERVER['HTTP_HOST'], FILTER_SANITIZE_URL), true, true);
          
          // Delete Session Token
          #unset($_SESSION['refresh_token']);
          
          if(isset($_SESSION['refresh_token']) && $_SESSION['refresh_token']) {
              $client->refreshToken($_SESSION['refresh_token']);
              $_SESSION['access_token'] = $client->getAccessToken();
          }
          elseif(isset($_COOKIE['refresh_token']) && $_COOKIE['refresh_token']) {
              $client->refreshToken($_COOKIE['refresh_token']);
              $_SESSION['access_token'] = $client->getAccessToken();
          }
          
          $url = 'https://www.googleapis.com/oauth2/v1/tokeninfo?access_token='.urlencode(@$_SESSION['access_token']['access_token']);
          $curl_handle = curl_init();
          curl_setopt($curl_handle, CURLOPT_URL, $url);
          curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT, 2);
          curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);
          curl_setopt($curl_handle, CURLOPT_USERAGENT, 'Google API Token Test');
          $json = curl_exec($curl_handle);
          curl_close($curl_handle);
          
          $obj = json_decode($json);
          
          ?>
          

          action.php

          session_start();
          
          require_once __DIR__.'/client.php';
          
          if(isset($obj->error)) {
              echo 'refresh';
              exit();
          }
          elseif(isset($_SESSION['access_token']) && $_SESSION['access_token'] && isset($obj->expires_in) && isset($_GET['q']) && !empty($_GET['q'])) {
              $client->setAccessToken($_SESSION['access_token']);
              $service = new Google_Service_YouTube($client);
              $response = $service->search->listSearch('snippet', array('q' => filter_input(INPUT_GET, 'q', FILTER_SANITIZE_SPECIAL_CHARS), 'maxResults' => '1', 'type' => 'video'));
              echo json_encode($response['modelData']);
              exit();
          }
          ?>
          

          【讨论】:

            【解决方案15】:

            我使用 google-api-php-client v2.2.2 我得到一个带有 fetchAccessTokenWithRefreshToken(); 的新令牌,如果没有参数的函数调用,它返回一个更新的访问令牌并且刷新的令牌不会丢失。

            if ($client->getAccessToken() && $client->isAccessTokenExpired()) {
                $new_token=$client->fetchAccessTokenWithRefreshToken();
                $token_data = $client->verifyIdToken();
            }    
            

            【讨论】:

              【解决方案16】:

              使用以下代码 sn-p 获取您的刷新令牌

                  <?php
              
                  require_once 'src/apiClient.php';
                  require_once 'src/contrib/apiTasksService.php';
              
                  $client = new apiClient();
                  $client->setAccessType('offline');
                  $tasksService = new apiTasksService($client);
              
                  $auth = $client->authenticate();
                  $token = $client->getAccessToken();
                  // the refresh token
                  $refresh_token = $token['refresh_token'];
                  ?>
              

              【讨论】:

                【解决方案17】:

                根据Authentication on google: OAuth2 keeps returning 'invalid_grant'

                “您应该重复使用在第一次成功验证后获得的访问令牌。如果您之前的令牌尚未过期,您将收到一个 invalid_grant 错误。将其缓存在某个地方以便您可以重复使用它。”

                希望对你有帮助

                【讨论】:

                  【解决方案18】:

                  我遇到了这个问题,我发现这是获得正确令牌的最简单和最干净的方法。

                  public function authenticate()
                  {
                      $access_token = 'OLD_TOKEN';
                      $refresh_token = 'OLD_TOKEN';
                  
                      if ($access_token) {
                          $this->client->setAccessToken($access_token);
                      }
                  
                      if ($this->client->isAccessTokenExpired()) {
                           $this->client->refreshToken($refresh_token);
                      }
                  }
                  
                  

                  我将client 作为类的属性,这就是我使用$this-&gt;client 的原因。

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2014-07-18
                    • 2013-02-03
                    • 2012-06-25
                    • 2014-08-18
                    • 1970-01-01
                    • 1970-01-01
                    • 2018-04-22
                    • 2019-06-09
                    相关资源
                    最近更新 更多