如何从 Google Calendar API 获取刷新的令牌

Posted

技术标签:

【中文标题】如何从 Google Calendar API 获取刷新的令牌【英文标题】:How to get refreshed token from Google Calendar API 【发布时间】:2021-10-03 07:45:00 【问题描述】:

我的目标是在 cron 函数中从谷歌日历中检索事件,我需要在访问令牌过期后每 1 小时授权一次请求的情况下执行此操作。 从许多相关的堆栈溢出问题中,我了解到一开始我通过授权请求获得访问令牌,然后将令牌写入 token.json 文件。第一次访问后,每次我需要访问日历时,fGetClient 函数控制令牌是否过期,如果我以前设置过

$client->setAccessType('offline');

该函数应该刷新令牌并且我应该访问日历的事件而不授权任何进一步的请求。 我的问题是我无法获取刷新的令牌,它会在一个小时后过期,然后我需要手动复制链接,授权请求,然后复制并粘贴验证码。

我把代码留在下面。

public function fGoogleCalendar($operazione=null)
        //require_once $this->config["googlecalendardir"].'vendor/autoload.php';

        // Get the API client and construct the service object.
        $client = $this->fGCGetClient();
        $service = new Google_Service_Calendar($client);

        // Print the next 10 events on the user's calendar.
        $calendarId = 'primary';
        $optParams = array(
          'maxResults' => 10,
          'orderBy' => 'startTime',
          'singleEvents' => true,
          'timeMin' => date('c'),
        );
        $results = $service->events->listEvents($calendarId, $optParams);
        $events = $results->getItems();

        if (empty($events)) 
            $aEventi="0 events found";
         else 
            // "Upcoming events:\n";
            foreach ($events as $event) 
                $start = $event->start->dateTime;
                if (empty($start)) 
                    $start = $event->start->date;
                
                $end = $event->end->dateTime;
                if (empty($end)) 
                    $end = $event->end->date;
                
                
                $aEventi[]=array(
                            "nome" => $event->getSummary(),
                            "startdate" => $start,
                            "enddate" => $end 
                        );                          
                $start);
            
        
        return $aEventi;

    

    public function fGCGetClient()
        require_once $this->config["googlecalendardir"].'vendor/autoload.php';

        $client = new Google_Client(); 
        //die("ok");
        $client->setApplicationName('Google Calendar API PHP Quickstart');
        $client->setScopes(Google_Service_Calendar::CALENDAR_READONLY);
        $client->setAuthConfig($this->config["googlecalendardir"].'credentials.json');
        $client->setAccessType('offline');
         //$client->setApprovalPrompt('auto');
        $client->setPrompt('consent');

        // Load previously authorized token from a file, if it exists.
        // The file token.json stores the user's access and refresh tokens, and is
        // created automatically when the authorization flow completes for the first
        // time.
        $tokenPath = $this->config["googlecalendardir"].'token.json';
        if (file_exists($tokenPath)) 
            $accessToken = json_decode(file_get_contents($tokenPath), true);
            $client->setAccessToken($accessToken);
        

        // If there is no previous token or it's expired.
        //if (true) 
        if ($client->isAccessTokenExpired()) 
            // Refresh the token if possible, else fetch a new one.
            if ($client->getRefreshToken()) 
                //$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
                $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
                $client->setAccessToken($client->getAccessToken());
             else 
                // Request authorization from the user.
                $authUrl = $client->createAuthUrl(); 
                printf("Open the following link in your browser:\n%s\n", $authUrl);
                print 'Enter verification code: ';
                $authCode = trim(fgets(STDIN));

                // Exchange authorization code for an access token.
                $accessToken = $client->fetchAccessTokenWithAuthCode($authCode);
                $client->setAccessToken($accessToken);

                // Check to see if there was an error.
                if (array_key_exists('error', $accessToken)) 
                    throw new Exception(join(', ', $accessToken));
                
            

             
            // Save the token to a file.
            if (!file_exists(dirname($tokenPath))) 
                mkdir(dirname($tokenPath), 0700, true);
            
            file_put_contents($tokenPath, json_encode($client->getAccessToken()));
        
        return $client;
    

【问题讨论】:

【参考方案1】:

如果您关注php quick start,您会注意到它请求离线访问,这意味着用户第一次授权此应用程序时,刷新令牌将被返回,然后存储在 $tokenPath 中

<?php
require __DIR__ . '/vendor/autoload.php';

if (php_sapi_name() != 'cli') 
    throw new Exception('This application must be run on the command line.');


/**
 * Returns an authorized API client.
 * @return Google_Client the authorized client object
 */
function getClient()

    $client = new Google_Client();
    $client->setApplicationName('Google Calendar API PHP Quickstart');
    $client->setScopes(Google_Service_Calendar::CALENDAR_READONLY);
    $client->setAuthConfig('credentials.json');
    $client->setAccessType('offline');
    $client->setPrompt('select_account consent');

    // Load previously authorized token from a file, if it exists.
    // The file token.json stores the user's access and refresh tokens, and is
    // created automatically when the authorization flow completes for the first
    // time.
    $tokenPath = 'token.json';
    if (file_exists($tokenPath)) 
        $accessToken = json_decode(file_get_contents($tokenPath), true);
        $client->setAccessToken($accessToken);
    

    // If there is no previous token or it's expired.
    if ($client->isAccessTokenExpired()) 
        // Refresh the token if possible, else fetch a new one.
        if ($client->getRefreshToken()) 
            $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
         else 
            // Request authorization from the user.
            $authUrl = $client->createAuthUrl();
            printf("Open the following link in your browser:\n%s\n", $authUrl);
            print 'Enter verification code: ';
            $authCode = trim(fgets(STDIN));

            // Exchange authorization code for an access token.
            $accessToken = $client->fetchAccessTokenWithAuthCode($authCode);
            $client->setAccessToken($accessToken);

            // Check to see if there was an error.
            if (array_key_exists('error', $accessToken)) 
                throw new Exception(join(', ', $accessToken));
            
        
        // Save the token to a file.
        if (!file_exists(dirname($tokenPath))) 
            mkdir(dirname($tokenPath), 0700, true);
        
        file_put_contents($tokenPath, json_encode($client->getAccessToken()));
    
    return $client;



// Get the API client and construct the service object.
$client = getClient();
$service = new Google_Service_Calendar($client);

// Print the next 10 events on the user's calendar.
$calendarId = 'primary';
$optParams = array(
  'maxResults' => 10,
  'orderBy' => 'startTime',
  'singleEvents' => true,
  'timeMin' => date('c'),
);
$results = $service->events->listEvents($calendarId, $optParams);
$events = $results->getItems();

if (empty($events)) 
    print "No upcoming events found.\n";
 else 
    print "Upcoming events:\n";
    foreach ($events as $event) 
        $start = $event->start->dateTime;
        if (empty($start)) 
            $start = $event->start->date;
        
        printf("%s (%s)\n", $event->getSummary(), $start);
    

【讨论】:

是的,我看到令牌存储在 tokenpath (这是 token.json 文件)中,但这并不会阻止函数在每次令牌过期时请求手动身份验证(每 1 小时一次) .我只想手动同意一次,然后让函数自行刷新令牌。 如果该文件中有有效的刷新令牌,它将使用刷新令牌来请求新的访问令牌。除非您的刷新令牌有问题,否则它不会再次请求授权。确保您有一个有效的刷新令牌,您可以撤消用户访问权限以确保您得到一个。 PHP 仅第一次返回刷新令牌。 好的,所以我必须检查刷新令牌是否有效......我该怎么做?在日历 API 文档中找不到与此相关的任何内容。【参考方案2】:

在你的当前目录下删除这个文件token.json

如果您删除文件,您的程序将无法找到该令牌因此创建一个新令牌。

【讨论】:

您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。

以上是关于如何从 Google Calendar API 获取刷新的令牌的主要内容,如果未能解决你的问题,请参考以下文章

如何让服务器访问Google Calendar API?

从google-calendar-API获取详细信息,无需帐户关联

如何通过 Javascript 中的 Google Calendar API 获取 Google Calendar 中事件的位置?

Google Calendar API,如何添加带有附加新生成的google meet的事件?

通过多封电子邮件从 google calendar api 查询事件

如何在没有 oAuth 身份验证的情况下连接到 Google Calendar API?