0

I wanna call Google Calendar API's freebusy.query endpoint by service account in server-side with php and google-api-php-client.

First, I opened Google Cloud Platform project page. Then I created service account, downloaded credential JSON file, enabled Calendar API, and allowed delegated authority.

Second, I opened Google Admin. Then I allowed scope:https://www.googleapis.com/auth/calendar for delegated authority.

Third, I wrote the following code. There're some laravel helper functions. I referenced https://github.com/googleapis/google-api-php-client/blob/master/examples/service-account.php to use library for service account.

<?php

use DateTime;
use Google_Client;
use Google_Service_Calendar;
use Google_Service_Calendar_FreeBusyRequest as FreeBusyRequest;
use Google_Service_Calendar_FreeBusyRequestItem as FreeBusyRequestItem;

$calendar = new Calendar();
$busyPeriods = $calendar->getBusyTimes(
    [env('GSUITE_MEMBER')],
    '2021-03-01 00:00:00',
    '2021-04-01 00:00:00'
);
dd($busyPeriods);

class Client {
    protected $client;

    public function __construct() {
        $this->client = new Google_Client();

        $credentialsPath = env('GOOGLE_SA_CREDENTIALS');
        if (file_exists($credentialsPath)) {
            $this->client->setAuthConfig($credentialsPath);
        } else {
            error_log('Google service account credentials don\'t exist.');
            return;
        }
    }

    public function setScopes($scopes) {
        $this->client->setScopes($scopes);
    }

    public function getClient() {
        return $this->client;
    }
}

class Calendar {
    protected $service;

    public function __construct() {
        $client = new Client();
        $client->setScopes([Google_Service_Calendar::CALENDAR]);
        $this->service = new Google_Service_Calendar($client->getClient());
    }

    /**
     * @param array $calendarIdList List of calendar identifier.
     * @param string $start Start of time period for getting busy times.
     * @param string $end End of time period for getting busy times.
     * @return Google_Service_Calendar_FreeBusyCalendar[]
     */
    public function getBusyTimes($calendarIdList, $start, $end) {
        $fbRequestItems = collect($calendarIdList)->map(function ($calendarId) {
            $i = new FreeBusyRequestItem();
            $i->setId($calendarId);
            return $i;
        })->toArray();
        $fbRequest = new FreeBusyRequest();
        $fbRequest->setItems($fbRequestItems);
        $fbRequest->setTimeZone(config('app.timezone'));
        $fbRequest->setTimeMin(
            (new DateTime($start))->format(DateTime::ISO8601)
        );
        $fbRequest->setTimeMax(
            (new DateTime($end))->format(DateTime::ISO8601)
        );
        return $this->service->freebusy->query($fbRequest)->getCalendars();
    }
}

However, Google_Service_Calendar_Error was returned.

Google_Service_Calendar_Error {#347 ▼
  +domain: "global"
  +reason: "notFound"
  #internal_gapi_mappings: []
  #modelData: []
  #processed: []
}
yutaaa
  • 97
  • 8

1 Answers1

0

We should impersonate G Suite member's account.

$this->client->setSubject(
    config('google.gsuite_admin_email')
);

Reference

Raserhin
  • 2,516
  • 1
  • 10
  • 14
yutaaa
  • 97
  • 8