Search code examples
google-apigoogle-calendar-apigoogle-oauthgoogle-api-php-client

OAuth 2.0 create single event with Google Calendar PHP API - Login Required error with cURL


I need a PHP script which has to create an event on google calendar.

I've already read google API documentation and I've understood that I have to use an offline access to API because I'd like that my script would create the calendar event itself, without asking for user auth every time.

I've also read here in stackoverflow that some ppl had problems resfreshing the token and have fixed the problem using cURL; I've tried to do that but I got an error: Uncaught exception 'Google_ServiceException' with message 'Error calling POST and 401 Login Required; now in $json_response var, there is the access_token; I've not understood how to use it to renew my connection. Thanks in advance for your help!

<?php

require_once 'src/Google_Client.php';
require_once 'src/contrib/Google_CalendarService.php';
session_start();

// I need that my script refresh the token itself, starting from a token that I've generated one time with user interaction
$oauth2token_url = "https://accounts.google.com/o/oauth2/token";
$clienttoken_post = array(
"client_id" => '...',
"client_secret" => '...');

$clienttoken_post["refresh_token"] = "1/vIQ......";
$clienttoken_post["grant_type"] = "refresh_token";

$curl = curl_init($oauth2token_url);

curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $clienttoken_post);
curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);

$json_response = curl_exec($curl);
curl_close($curl);

$authObj = json_decode($json_response);

print_r($authObj);


$client = new Google_Client();
$client->setApplicationName("Google Calendar PHP Starter Application");

$client->setClientId('....');                               
$client->setClientSecret('....');                                                        $client->setRedirectUri('...'); 
$client->setDeveloperKey('....');                           
$client->setAccessType('offline');
//$client-> setApprovalPrompt("auto");
$cal = new Google_CalendarService($client);                                                     

if (isset($_GET['logout'])) {
   unset($_SESSION['token']);
}

if (isset($_GET['code'])) {
    $client->authenticate();
    $_SESSION['token'] = $client->getAccessToken();
    header('Location: http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']);
}

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

$event = new Google_Event();
$event->setSummary($event_name);
$event->setLocation('');
$start = new Google_EventDateTime();
$start->setDate($scadenza);
$event->setStart($start);
$end = new Google_EventDateTime();
$end->setDate($scadenza);
$event->setEnd($end);
$createdEvent = $cal->events->insert('cal_id_xyz', $event);
?>

Thanks in advance!


Solution

  • I've finally solved my problem this way:

    First of all I've obtained an access token and a refresh token with a human interaction using the PHP sample script found at this URL: https://code.google.com/p/google-api-php-client/

    So I've put the access token in actok.txt and then I've run the following script.

    Hope that could help beginners (and I am one of them :-) ), to better understand how OAuth works with offline access.

    <?php
    
        // I've put the last valid access token in a txt file
        $my_file = 'actok.txt';
        $handle = fopen($my_file, 'r');
        $data = fread($handle,filesize($my_file));
        fclose($handle);
    
        $first_answer = "{\"access_token\":\"" . $data . "\",\"expires_in\":3920,\"token_type\":\"Bearer\",\"refresh_token\":\"1/xxxxx\"}";   // the refresh_token is always the same and it's the one obtained at the beginning.
    
        require_once 'src/Google_Client.php';
        require_once 'src/contrib/Google_CalendarService.php';
        session_start();
    
        $oauth2token_url = "https://accounts.google.com/o/oauth2/token";
         $clienttoken_post = array(
         "client_id" => '....',
         "client_secret" => '....');
    
        $clienttoken_post["refresh_token"] = "...."; // the same as before
        $clienttoken_post["grant_type"] = "refresh_token";
    
        $curl = curl_init($oauth2token_url);
    
        curl_setopt($curl, CURLOPT_POST, true);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $clienttoken_post);
        curl_setopt ($curl, CURLOPT_HTTPHEADER, Array("application/x-www-form-urlencoded"));
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    
        $client = new Google_Client();
        $client->setApplicationName("Google Calendar PHP Starter Application");
    
        $client->setClientId('xyz');       // ClientID
        $client->setClientSecret('xyz');   // ClientSecret
        $client->setRedirectUri('http://www.xyz/zzz.php');    // RedirectUri
        $client->setDeveloperKey('ffffff');         // DeveloperKey
        $client->setAccessType('offline');
        $cal = new Google_CalendarService($client);                                                     
    
        $client->setAccessToken($first_answer); // here I set the last valid access_token, taken from the txt file      
    
        if (isset($_GET['logout'])) {
          unset($_SESSION['token']);
        }
    
        if(isset($_GET['code'])) {
            $client->authenticate();
            $_SESSION['token'] = $client->getAccessToken();
            header('Location: http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']);
        }
    
        if(isset($_SESSION['token'])) {
            $client->setAccessToken($_SESSION['token']);
        }
    
        if($client->isAccessTokenExpired()) {  // if the token is expired, I have to refresh it
    
            echo 'Access Token Expired'; // debug
    
            $json_response = curl_exec($curl); // JSON value returned
            curl_close($curl);
    
            $authObj = json_decode($json_response);
    
            $sec_answer = "{\"access_token\":\"" . $authObj->access_token . "\",\"expires_in\":3920,\"token_type\":\"Bearer\",\"refresh_token\":\"1/xxxxxx\"}"; // same refresh_token as always
    
            $client->setAccessToken($sec_answer);
    
            $handle2 = fopen($my_file, 'w') or die('Cannot open file:  '.$my_file);
            $new_accesstk = $authObj->access_token;
            fwrite($handle2, $new_accesstk);
            fclose($handle2);
        }
    
        // Event Creation
        $event = new Google_Event();
        $event->setSummary('xyz');          // Event name
        $event->setLocation('');            // Event location
        $start = new Google_EventDateTime();
        $start->setDate('2013-xx-xx');
        $event->setStart($start);
        $end = new Google_EventDateTime();
        $end->setDate('2013-xx-xx');
        $event->setEnd($end);
        $createdEvent = $cal->events->insert('xyz', $event); // insert(calendar_id, event)
    
    ?>