1
votes
  <?php

    include('lead1.php');
    require_once __DIR__ . '/vendor/autoload.php';

    global $link;

        $emailmsgsql =  "SELECT *
                        FROM psleads WHERE agreeid = '6'";
        $msgreqsres = mysqli_query($link, $emailmsgsql); // or die(mysql_error()0);
        $msgreqs = $msgreqsres->fetch_assoc();

        $start = $msgreqs['contractbegindate'] . ' ' . $msgreqs['contractbegintime'];
        $end = $msgreqs['contractenddate'] . ' ' . $msgreqs['contractendtime'];

        $startDT = new DateTime($start, new DateTimeZone('Pacific/Honolulu'));
        $endDT = new DateTime($end, new DateTimeZone('Pacific/Honolulu'));

        $startDTw3c = $startDT->format(DateTime::W3C);
        $endDTw3c = $endDT->format(DateTime::W3C);

        putenv('GOOGLE_APPLICATION_CREDENTIALS=./service-account.json');

        define('CREDENTIALS_PATH', '~/calendar-php.json');
        define('CLIENT_SECRET_PATH', './client_secret.json');
        //define('CLIENT_SECRET_PATH', __DIR__ . '/client_secret.json');

        $client = new Google_Client();
        $client->setApplicationName("Paradise_Sound_Booking_Calendar");
        $client->addScope('https://www.googleapis.com/auth/calendar');
        $client->setAuthConfig(CLIENT_SECRET_PATH);
        $client->setClientId('532085378494-s908fs5mu4rf2e2s60cecgaprg9pem1p.apps.googleusercontent.com');

        $client->setDeveloperKey("XXXXX");//flo.gd

        $client->useApplicationDefaultCredentials();

        // Load previously authorized credentials from a file.
        function expandHomeDirectory($path) {
          $homeDirectory = getenv('HOME');
          if (empty($homeDirectory)) {
            $homeDirectory = getenv('HOMEDRIVE') . getenv('HOMEPATH');
          }
          return str_replace('~', realpath($homeDirectory), $path);
        }

$credentialsPath = expandHomeDirectory(CREDENTIALS_PATH);
if (file_exists($credentialsPath)) {
    $accessToken = json_decode(file_get_contents($credentialsPath), true);
} 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));
    $authCode = 'Manually pasted return code into script here';

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

    // Store the credentials to disk.
    if(!file_exists(dirname($credentialsPath))) {
      mkdir(dirname($credentialsPath), 0700, true);
    }
    file_put_contents($credentialsPath, json_encode($accessToken));
    printf("Credentials saved to %s\n", $credentialsPath);
}

$client->setAccessToken($accessToken);

// Refresh the token if it's expired.
if ($client->isAccessTokenExpired()) {
    $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
    file_put_contents($credentialsPath, json_encode($client->getAccessToken()));
}



        $service = new Google_Service_Calendar($client);

        $event = new Google_Service_Calendar_Event(array(
          'summary' => 'Booked Event ' . $msgreqs['contractbegindate'],
          'start' => array(
            'dateTime' => $startDTw3c,
            //'dateTime' => '2015-05-28T09:00:00-07:00',
            'timeZone' => 'Pacific/Honolulu',
          ),
          'end' => array(
            'dateTime' => $endDTw3c,
            'timeZone' => 'Pacific/Honolulu',
          )
        ));

        $calendarId = '[email protected]';
        $eventres = $service->events->insert($calendarId, $event);

        echo json_encode($eventres);
?>

So here is my PHP code I am using to test event insertion into MY google calendar.

I thought I could use just an API key but google seems to have this convulted way of doing OAUTH that I just can't figure out. I can see all my 403 errors in my API Developers Console.

Does anyone have working code to do simple event inserts into my calendar.

CONTEXT:

I will recieve an IPN from paypal (done) and that will fire off this script that will insert an event into MY calendar, not the users. Can anyone help me without referring me to the google developer docs? They seem sparse and I have read them over and over and over again to no avail of solving my issue.

Here is the error I am getting:

Fatal error: Uncaught exception 'Google_Service_Exception' with message '{ "error": { "errors": [ { "domain": "global", "reason": "forbidden", "message": "Forbidden" } ], "code": 403, "message": "Forbidden" } } ' in /home/dahfrench/flo.gd/src/Google/Http/REST.php:118 Stack trace: #0 /home/dahfrench/flo.gd/src/Google/Http/REST.php(94): Google_Http_REST::decodeHttpResponse(Object(GuzzleHttp\Psr7\Response), Object(GuzzleHttp\Psr7\Request), 'Google_Service_...') #1 [internal function]: Google_Http_REST::doExecute(Object(GuzzleHttp\Client), Object(GuzzleHttp\Psr7\Request), 'Google_Service_...') #2 /home/dahfrench/flo.gd/src/Google/Task/Runner.php(181): call_user_func_array(Array, Array) #3 /home/dahfrench/flo.gd/src/Google/Http/REST.php(58): Google_Task_Runner->run() #4 /home/dahfrench/flo.gd/src/Google/Client.php(789): Google_Http_REST::execute(Object(GuzzleHttp\Client), Object(GuzzleHttp\Psr7\Request), 'Google_Service_...', Array) #5 /home/dahfrench/flo.gd/src/Google/Service/Resource.php(232): Goo in /home/dahfrench/flo.gd/src/Google/Http/REST.php on line 118

1
also, I was getting this error BEFORE I had done any of the OAuth crap, because I thought I needed the service account authentication Google suggests for server to server communication.JohnHanks
API key is used for accessing public data (And probably isn't even oauth) , Oauth2 and service accounts are used for accessing private user data.DaImTo

1 Answers

2
votes

You may want to finalize what authentication you want to implement : user needs to login to perform/request to Google Services or delegate a domain-wide authority to the service account.

If you will be using OAuth 2.0:

Your application must use OAuth 2.0 to authorize requests.

Sample Code from Google:

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


define('APPLICATION_NAME', 'Google Calendar API PHP Quickstart');
define('CREDENTIALS_PATH', '~/.credentials/calendar-php-quickstart.json');
define('CLIENT_SECRET_PATH', __DIR__ . '/client_secret.json');
// If modifying these scopes, delete your previously saved credentials
// at ~/.credentials/calendar-php-quickstart.json
define('SCOPES', implode(' ', array(
  Google_Service_Calendar::CALENDAR_READONLY)
));

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(APPLICATION_NAME);
  $client->setScopes(SCOPES);
  $client->setAuthConfig(CLIENT_SECRET_PATH);
  $client->setAccessType('offline');

  // Load previously authorized credentials from a file.
  $credentialsPath = expandHomeDirectory(CREDENTIALS_PATH);
  if (file_exists($credentialsPath)) {
    $accessToken = json_decode(file_get_contents($credentialsPath), true);
  } 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);

    // Store the credentials to disk.
    if(!file_exists(dirname($credentialsPath))) {
      mkdir(dirname($credentialsPath), 0700, true);
    }
    file_put_contents($credentialsPath, json_encode($accessToken));
    printf("Credentials saved to %s\n", $credentialsPath);
  }
  $client->setAccessToken($accessToken);

  // Refresh the token if it's expired.
  if ($client->isAccessTokenExpired()) {
    $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
    file_put_contents($credentialsPath, json_encode($client->getAccessToken()));
  }
  return $client;
}

/**
 * Expands the home directory alias '~' to the full path.
 * @param string $path the path to expand.
 * @return string the expanded path.
 */
function expandHomeDirectory($path) {
  $homeDirectory = getenv('HOME');
  if (empty($homeDirectory)) {
    $homeDirectory = getenv('HOMEDRIVE') . getenv('HOMEPATH');
  }
  return str_replace('~', realpath($homeDirectory), $path);
}

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

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

If you will be using Google Apps Domain-Wide Delegation of Authority:

Authorizing a service account to access data on behalf of users in a domain is sometimes referred to as "delegating domain-wide authority" to a service account.

Sample Code from a SO post:

function calendarize ($title, $desc, $ev_date, $cal_id) {

    session_start();

    /************************************************
    Make an API request authenticated with a service
    account.
    ************************************************/
    set_include_path( '../google-api-php-client/src/');

    require_once 'Google/Client.php';
    require_once 'Google/Service/Calendar.php';

    //obviously, insert your own credentials from the service account in the Google Developer's console
    $client_id = '843319906820-xxxxxxxxxxxxxxxxxxxdcqal54p1he6.apps.googleusercontent.com';
    $service_account_name = '843319906820-xxxxxxxxxxxxxxxxxxxdcqal54p1he6@developer.gserviceaccount.com';
    $key_file_location = '../google-api-php-client/calendar-xxxxxxxxxxxx.p12';

    if (!strlen($service_account_name) || !strlen($key_file_location))
        echo missingServiceAccountDetailsWarning();

    $client = new Google_Client();
    $client->setApplicationName("Whatever the name of your app is");

    if (isset($_SESSION['service_token'])) {
        $client->setAccessToken($_SESSION['service_token']);
    }

    $key = file_get_contents($key_file_location);
    $cred = new Google_Auth_AssertionCredentials(
        $service_account_name, 
        array('https://www.googleapis.com/auth/calendar'), 
        $key
    );
    $client->setAssertionCredentials($cred);
    if($client->getAuth()->isAccessTokenExpired()) {
        $client->getAuth()->refreshTokenWithAssertion($cred);
    }
    $_SESSION['service_token'] = $client->getAccessToken();

    $calendarService = new Google_Service_Calendar($client);
    $calendarList = $calendarService->calendarList;

    //Set the Event data
    $event = new Google_Service_Calendar_Event();
    $event->setSummary($title);
    $event->setDescription($desc);

    $start = new Google_Service_Calendar_EventDateTime();
    $start->setDateTime($ev_date);
    $event->setStart($start);

    $end = new Google_Service_Calendar_EventDateTime();
    $end->setDateTime($ev_date);
    $event->setEnd($end);

    $createdEvent = $calendarService->events->insert($cal_id, $event);

    echo $createdEvent->getId();
} 

?>

Note: If you plan on using only one calendar, I would recommend using a service account then sharing your calendar to the account in order to avoid 403 : Forbidden as said in the related SO post

Hope this helps.