문제

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!

도움이 되었습니까?

해결책 2

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)

?>

다른 팁

(Disclaimer: I'm not a PHP expert (or even novice) - but I do know Google's OAuth flows)

A few things to note:

  1. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); - if that is disabling certificate validation, then I strongly suggest not doing that - you should want to verify that you are sending the refresh token to accounts.google.com and no-one else.

  2. Make sure you set the content-type to "application/x-www-form-urlencoded" on the POST - it's not clear to me whether setting CURLOPT_POSTFIELDS does this or something else for you.

  3. I don't know why you are setting CURLOPT_HTTPAUTH - I wouldn't expect that to make any positive effect on the request.

That all said, my suggestion would be to take advantage of the Google provided client library - which it looks like you are already using.

After looking at the src for Google_Client.php, I believe that adding a:

$client->refreshToken("1/xxxxxx....");

after all of the other ->setXXXs will have it go ahead and get a new access token for you that it should then automatically add to subsequent APIs calls. I suggest trying that and removing the manual calls to curl.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top