PHP Google 服务帐户身份验证日历 API

Posted

技术标签:

【中文标题】PHP Google 服务帐户身份验证日历 API【英文标题】:PHP Google Service account auth Calendar API 【发布时间】:2022-01-06 08:20:08 【问题描述】:

我想从我的网站分享事件并将其添加到我自己的谷歌日历。 所以,我不想要 oauth 提示。因为访问我网站的用户也可以将活动添加到我的日历中。

我认为我做对了,但我有这个错误:Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested

所以,我不确定是否需要付费的工作区帐户来执行此操作。 如果没有,我无法理解我失败的地方?

这是我的代码:

$client = new Google\Client();

$client->setAuthConfig('./secret.json');
$client->setApplicationName('app name');
$client->addScope(Google\Service\Calendar::CALENDAR_EVENTS);
$client->setSubject('mail@gmail.com');
$client->setAccessType('offline');

$service = new Google\Service\Calendar($client);

$event = new Google\Service\Calendar\Event(array(
    'summary' => 'summary',
    'location' => 'street bla bla',
    'description' => 'first event',
    'start' => array(
        'dateTime' => '2021-11-30T10:00:00.000-05:00',
        'timeZone' => 'Europe/Brussels',
    ),
    'end' => array(
        'dateTime' => '2021-11-30T10:00:00.000-05:00',
        'timeZone' => 'Europe/Brussels',
    )
));

$service->events->insert('calendar_id', $event);

谢谢

【问题讨论】:

正如@DalmTo 在他的回答中提到的那样,服务帐户仅适用于Google Workspace Domain Accounts,如果他提供的答案对您有用,您还可以查看指南中的各种示例日历 API,如如何添加Event。 【参考方案1】:

问题是您尝试将主题或委托设置为正常的 Gmail 电子邮件地址 $client->setSubject('mail@gmail.com');

服务帐户仅适用于 Google 工作区域帐户,并且只有在您正确设置了对域中用户的委派之后。

很遗憾地告诉您,您将无法通过您的 gmail 电子邮件地址使用服务帐户。

您可以做的是运行示例项目中的代码,该项目使用已安装的应用程序并存储刷新令牌。此代码将是单个用户。您将不得不对其进行一点监控,因为刷新令牌可能会过期,尽管在您的项目设置为 prodctuion 后它并不常见。

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

【讨论】:

您好,感谢您的帮助。但是您知道我们是否可以免费进行测试吗?我的客户需要此访问权限,但我想我可以免费访问开发?还是我也要付钱? 只有在您的客户有工作区帐户时才能工作,要对此进行测试,您需要一个工作区帐户。您需要为工作区帐户付费。让他们在他们的工作区域上为您设置服务帐户,您可以使用它进行测试。

以上是关于PHP Google 服务帐户身份验证日历 API的主要内容,如果未能解决你的问题,请参考以下文章

使用 php 和服务帐户创建谷歌日历事件 - 身份验证问题

Google OAuth 2.0 服务帐户 - 日历 API(PHP 客户端)

Google Calendar API v3 - 使用硬编码凭据进行身份验证

Google Calendar API - 请求的身份验证范围不足

未在服务帐户谷歌日历 api php 中创建环聊链接

使用服务帐户密钥对 Google Photos API 进行身份验证?