Error (401) Login Required - Google Calendar API v

2019-09-17 03:24发布

I want to add an event to a particular Google Apps calendar each time that an appointment is booked in my codeigniter app.

So far I've gone through the following steps (from Using OAuth 2.0 for Server to Server Applications):

  1. Add Google API Client Library to application/third_party
  2. Create Service Account in Developer Console with Google Apps Domain-wide Delegation enabled
  3. Store provided .p12 file
  4. Authorize Service Account Client ID in Google Apps Admin Console with scope of https://www.googleapis.com/auth/calendar
  5. Share calendar with Service Account email address

I'm getting the error "Error calling POST <calendar API insert endpoint> (401) Login Required"

I believe that I must be doing something incorrect in how I'm authenticating. Any advice would be welcomed.

application/libraries/Google.php:

<?php
if (!defined('BASEPATH')) exit('No direct script access allowed');
set_include_path(APPPATH . 'third_party/' . PATH_SEPARATOR . get_include_path());
require_once APPPATH . 'third_party/Google/autoload.php';
require_once APPPATH . 'third_party/Google/Client.php';

class Google extends Google_Client {
    function __construct($params = array()) {
        parent::__construct();

        $client_email = '<SERVICE ACCOUNT EMAIL>';
        $private_key = file_get_contents('<.P12 FILE PATH>');
        $scopes = array('https://www.googleapis.com/auth/calendar');

        $credentials = new Google_Auth_AssertionCredentials(
            $client_email,
            $scopes,
            $private_key
        );

        $client = new Google_Client();
        $client->setAssertionCredentials($credentials);
        if ($client->getAuth()->isAccessTokenExpired()) {
          $client->getAuth()->refreshTokenWithAssertion();
        }
    }
}

application/controllers/Booking.php:

(Google.php library loaded in constructor)

function addCalendarEvent($user_id, $date, $time, $address, $booking_data) {

    $cal = new Google_Service_Calendar($this->google);

    $calendar_id = '<CALENDAR ID>';

    $start_datetime = date('c', strtotime($date.' '.$time));

    $end_datetime = date('c', strtotime($date.' '.$time.' +2 hours'));

    $event = new Google_Service_Calendar_Event(array(
      'summary' => 'Appointment at '.$address['street_address'],
      'location' => $location,
      'description' => $booking_data['description'],
      'start' => array(
        'dateTime' => $start_datetime,
        'timeZone' => 'America/Los_Angeles',
      ),
      'end' => array(
        'dateTime' => $end_datetime,
        'timeZone' => 'America/Los_Angeles',
      ),
      'attendees' => array(
        array('email' => '<ADMIN EMAIL>')
      )
    ));

    $cal->events->insert($calendar_id, $event);
}

1条回答
叼着烟拽天下
2楼-- · 2019-09-17 04:03

I was able to fix my own problem by instantiating Google_Service_Calendar before authenticating, like so:

class Google extends Google_Client {
    function __construct($params = array()) {
        parent::__construct();

        $client_email = '<SERVICE ACCOUNT EMAIL>';
        $private_key = file_get_contents('<.P12 FILE PATH>');
        $scopes = array('https://www.googleapis.com/auth/calendar');

        $client = new Google_Client();

        $this->cal = new Google_Service_Calendar($client);

        $credentials = new Google_Auth_AssertionCredentials(
            $client_email,
            $scopes,
            $private_key
        );

        $client->setAssertionCredentials($credentials);
        if ($client->getAuth()->isAccessTokenExpired()) {
          $client->getAuth()->refreshTokenWithAssertion();
        }
    }
}

And then using the service in application/controllers/Booking.php like so:

$this->google->cal->events->insert($calendar_id, $event);
查看更多
登录 后发表回答