Google API 客户端“刷新令牌必须传入或设置为 setAccessToken 的一部分" [英] Google API Client "refresh token must be passed in or set as part of setAccessToken"

查看:29
本文介绍了Google API 客户端“刷新令牌必须传入或设置为 setAccessToken 的一部分"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正面临一个非常奇怪的问题,实际上我一直在遵循同样的指南(https://developers.google.com/google-apps/calendar/quickstart/php)来自 Google API 文档.我尝试了两次,第一次它像魅力一样工作,但是在访问令牌过期后,Google API Doc 直接提供的脚本无法刷新它.

I am currently facing a very strange problem, indeed I've been following this very same guide (https://developers.google.com/google-apps/calendar/quickstart/php) from Google API documentation. I tried it twice, at the first time it work like a charm but after the access token had expire the script provided straight by Google API Doc was unable to refresh it.

TL;博士

错误信息如下:

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

这是我修改过的 google php 脚本的一部分:

Here is the part of the php script from google I've modified:

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');

我还修改了 expandHomeDirectory 以便我可以禁用"它而无需修改太多代码:

I also modified the expandHomeDirectory so I could "disable" it without modifying too much code:

function expandHomeDirectory($path) {
  $homeDirectory = getenv('HOME');
  if (empty($homeDirectory)) {
    $homeDirectory = getenv('HOMEDRIVE') . getenv('HOMEPATH');
  }
  return $path;
  // return str_replace('~', realpath($homeDirectory), $path);
}

所以为了检查是我错了还是谷歌错了,我做了一个实验:昨天晚上我从 ssh 启动了快速启动脚本来检查它是否有效,确实如此,所以我决定今天早上检查它是否有效仍然像睡前一样工作,但事实并非如此,所以我认为 Google 的 quickstart.php 有问题.

So to check if I was wrong or if Google was, I did an experiment: yesterday night I launch the quickstart script from ssh to check if it was working, and indeed it was, so I decided to check this morning if it still working just as it was before I slept and it wasn't so I think there's something wrong with Google's quickstart.php.

我希望有人能帮助我,我已经查看了有关该主题的所有其他帖子,但它们都已过时.

I hope someone could help me, I already checked all the other posts about the subject but they are all outdated.

推荐答案

我最近遇到了同样的问题,我用这个解决了.

I got the same problem recently and i solved it with this.

<?php
 $client->setRedirectUri($this->_redirectURI);
 $client->setAccessType('offline');
 $client->setApprovalPrompt('force');

我解释.....由于我们没有强制批准提示,因此不会返回刷新令牌.离线模式还不够.我们必须强制批准Prompt.此外,必须在这两个选项之前设置 redirectURI.它对我有用.

I explain ..... Refresh token is not returned because we didnt force the approvalPrompt. The offline mode is not enought. We must force the approvalPrompt. Also the redirectURI must be set before these two options. It worked for me.

这是我的全部功能

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

这篇关于Google API 客户端“刷新令牌必须传入或设置为 setAccessToken 的一部分"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆