5

I'm having a heck of a time trying to get a very simple event added to a calendar using the Google Calendar API, and I would love it if someone could point out my (probably obvious) issue. I'm using code that I found here. I've put the code in the "google-api-php-client/examples.calendar" directory, where a simple example can be found.

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


    $client = new Google_Client();
        $client->setApplicationName("Google Calendar PHP Starter Application");
        $client->setClientId('');
        $client->setClientSecret('');
        $client->setRedirectUri('worked.html'); //I made a file called "worked.html" in the same directory that just says "it worked!"
        $client->setDeveloperKey('SecretLongDeveloperKey');
        $cal = new Google_CalendarService($client);

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

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

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

$authUrl = $client->createAuthUrl();

 if (!$client->getAccessToken()){

    $event = new Google_Event();

        $event->setSummary('Halloween');
        $event->setLocation('The Neighbourhood');
        $start = new Google_EventDateTime();
        $start->setDateTime('2012-10-31T10:00:00.000-05:00');
        $event->setStart($start);
        $end = new Google_EventDateTime();
        $end->setDateTime('2012-10-31T10:25:00.000-05:00');
        $event->setEnd($end);
        $createdEvent = $cal->events->insert('secretLongCalendarId@group.calendar.google.com', $event);

}


echo $createdEvent->getId();

?>

When I access this script, I get a 404 error. I've tried going through the code and commenting out lines in an attempt to find the culprit - it appears to be the second-to-last line, which actually inserts the event.

Any advice? I'd really appreciate some pointers, as I cannot seem to get even the simplest of examples to work.

Community
  • 1
  • 1
Jake
  • 3,142
  • 4
  • 30
  • 48

2 Answers2

4

Your code almost works.

However, you redirect to "worked.html". That way your event does not get created after the redirect of authentication. Also the setRedirectUri should match what you entered in Google API plus console (see "Redirect URIs") AND it should be THIS file because this file is entering the event after the redirect. (You don't need the "worked.html")

So your simple.php should look like this (ALSO change the "Redirect URIs" on Google Api to http://localhost/simple.php, you need to specify the domain but can use localhost, in setRedirectUri you can specify the same)

<?php
error_reporting(E_ALL);
require_once 'google-api-php-client/src/Google_Client.php';
require_once 'google-api-php-client/src/contrib/Google_CalendarService.php';
session_start();

if ((isset($_SESSION)) && (!empty($_SESSION))) {
   echo "There are cookies<br>";
   echo "<pre>";
   print_r($_SESSION);
   echo "</pre>";
}

$client = new Google_Client();
$client->setApplicationName("Google Calendar PHP Starter Application");
$client->setClientId('###');
$client->setClientSecret('###');
$client->setRedirectUri('http://###/index.php');
$client->setDeveloperKey('###');
$cal = new Google_CalendarService($client);

if (isset($_GET['logout'])) {
  echo "<br><br><font size=+2>Logging out</font>";
  unset($_SESSION['token']);
}

if (isset($_GET['code'])) {
  echo "<br>I got a code from Google = ".$_GET['code']; // You won't see this if redirected later
  $client->authenticate($_GET['code']);
  $_SESSION['token'] = $client->getAccessToken();
  header('Location: http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']);
  echo "<br>I got the token = ".$_SESSION['token']; // <-- not needed to get here unless location uncommented
}

if (isset($_SESSION['token'])) {
  echo "<br>Getting access";
  $client->setAccessToken($_SESSION['token']);
}

if ($client->getAccessToken()){

  echo "<hr><font size=+1>I have access to your calendar</font>";
  $event = new Google_Event();
  $event->setSummary('Halloween');
  $event->setLocation('The Neighbourhood');
  $start = new Google_EventDateTime();
  $start->setDateTime('2013-9-29T10:00:00.000-05:00');
  $event->setStart($start);
  $end = new Google_EventDateTime();
  $end->setDateTime('2013-9-29T10:25:00.000-05:00');
  $event->setEnd($end);
  $createdEvent = $cal->events->insert('###', $event);
  echo "<br><font size=+1>Event created</font>";

  echo "<hr><br><font size=+1>Already connected</font> (No need to login)";

} else {

  $authUrl = $client->createAuthUrl();
  print "<hr><br><font size=+2><a href='$authUrl'>Connect Me!</a></font>";

}

$url = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
echo "<br><br><font size=+2><a href=$url?logout>Logout</a></font>";

?>

Also, like @BigMacAttack already stated, you only need the
$authURL = $client->createAuthURL(); once, only if getAccessToken failed.

Happy Halloween ;-)

Edit: I cleaned up the code a lot with working links to login and logout and log-messages.

Rik
  • 1,982
  • 1
  • 17
  • 30
  • This seems very close, but isn't quite there yet. Here is my current code revision: http://pastebin.com/QJ7WTQfq I made a subdomain for this, test.mywebsite.com. All of the code is in index.php. I replaced my code with yours, putting in the correct values for all of the ###'s, and then put test.mywebsite.com/index.php as the redirect uri. Going to the page, I get to the "else" section, which gives me a URL. I go to that URL, Google asks me for authorization, I click accept, it sends me back to index.php, then I get to the "got the code" section. It never actually gets to the insertion. – Jake Sep 14 '13 at 16:39
  • I took your code again and here it works. Perhaps there is something wrong with your cookies. You can try debugging with a `print_r($_SESSION);` after the `session_start()`. You should see the cookies `token` etc.. Also perhaps you can comment out the `header('Location:` line. You won't need the redirect to the same file. You can see if you then get to the 'got the token' and 'get the token' line. I don't know if the Google code itself needs the cookies to work. – Rik Sep 14 '13 at 23:02
  • First let me just say thank you so much for your help! You're the only resource I could find! =) I couldn't get it to work in another browser either, or on another computer. I tried putting a print_r where you said, it just prints Array(), which I believe (?) means there's nothing in the array - is that true? Is there something else I can print_r() to help diagnose the issue? – Jake Sep 15 '13 at 16:08
  • If you only get `Array()` it means that `$_SESSION` is empty so there are no cookies getting through. You are getting to "got the code" so there the cookie 'token' ($_SESSION['token']) should be set just before redirecting to itself. After that it should give you (with the print_r) something in the $_SESSION. Did you try removing the `header('Location:` line? Also you could try, right after `$_SESSION['token'] = $client->getAccessToken();`, to do a `print("i got the token = ".$_SESSION['token']); exit();` to see if the token is filled. (The `exit();` is important or else you get redirected. – Rik Sep 15 '13 at 16:21
  • Also the way you did it with outputting a line 'got the code' before doing a `header('Location:` does not work. Headers only work if you haven't outputted anything yet. So you don't get redirected. (I would try commenting out the `header('Location:`-line. It worked here.) – Rik Sep 15 '13 at 16:31
  • Another thought i just had. Besides the fact you should not output anything before the `header`-line, you should do a `session_write_close() ;` just before the `header('Location:`. Sometimes the location-redirect is too fast and the cookie does not get set. I don't think this was your problem here because you didn't get redirected but better to be safe then sorry. – Rik Sep 15 '13 at 21:32
  • Ok, lots of things - again, thank you so much for the help. I commented out the header line. I seem to have found an issue - after the "got the code" line, I have a `$client->authenticate($_GET['code']);` line - I put an echo directly underneath it to see what happens, and I don't get to that point. It seems like that authentication line is the issue. – Jake Sep 16 '13 at 16:16
  • According to your code, if you get to "got the code" you also get to the line `$client->authenticate(`. Question is, do you get **past** this line. If you've put in the line `print("i got the token = ".$_SESSION['token']);` and you don't even get the text `"i got the token = "` then there is something wrong in `$client->authenticate`. 2 things you can do. 1) Put `echo "
    got the code = ".$_GET['code'];` so you can see you got a **valid** code. 2) if the problem is in `$client->authenticate` you can put `error_reporting(E_ALL);` at the top of your php to see if you have unreported errors.
    – Rik Sep 16 '13 at 19:09
  • Also found this: `$authUrl = $client->createAuthUrl(); print "Connect Me!";` on [this page](https://code.google.com/p/google-api-php-client/). Easier then doing a copy paste of that authentication url :) – Rik Sep 16 '13 at 19:14
  • -+Hi again. I edited my answer and cleaned up the code a lot with working links to login and logout and log-messages. This way is much easier to test. I can click login and logout and it all works here. You can uncomment the header line to troubleshoot but then you get an url in the address bar (with ?code=...) which you should not refresh (because the google.php gives an error on the second go after refresh, there was the redirection for needed). Change all the ### and i hope it works directly. (now i'm going to delete a hundred haloween entries ;) – Rik Sep 16 '13 at 19:50
  • Ok, so using your new code I still run into the same issue. I replaced my old code with your new one, and replaced all of the ###'s. I click "Connect me", click accept to let Google modify my calendars, and on the resulting page I get "I got a code from Google = blahblahblah". That's the end of the page though, it never says "I got the token". It's the same story if I comment out the `header('location...` line – Jake Sep 16 '13 at 20:18
  • Ok, then there is definitively something wrong in `$client->authenticate($_GET['code']);`. 2 questions. 1) What version of PHP do you use. 2) What do you get if you only do `$client->authenticate();` without the _GET parameter. I found it on [this page](https://code.google.com/p/google-api-php-client/) where it was not needed. (just tested it and here it works without _GET parameter, so try it) – Rik Sep 16 '13 at 20:28
  • I'm using PHP 5.3.27. When I switch to just `$client->authenticate();`, I still get only the "Got a code from Google" but not the "got the token" – Jake Sep 16 '13 at 20:39
  • Only thing to do is put a line between `$client->authenticate();` and `$_SESSION['token'] = $client->getAccessToken();` to see if that gets through. Then you know in which of the 2 lines the problems is. But either way, there is a problem in the Google-code. Perhaps you can download it again [(link to latest version)](https://code.google.com/p/google-api-php-client/downloads/list) and try again. I used 0.6.6. – Rik Sep 16 '13 at 20:49
  • Nope, I put an echo between the two lines and it never got there. I also replaced my code library with the one you linked to, which I believe was what I was using before. – Jake Sep 16 '13 at 21:08
  • My 'traffic reports' section of the Google Console also says that I have made 0 requests...also, unless it's built-in to the Google API, I really don't want to have to authenticate. I'm not interested in the information of the user, I set up a calendar for which the script should be able to add an event. I don't want to have to hit a button to accept the app modifying my calendars...is that possible? If it is, it would bypass this whole authentication fiasco – Jake Sep 16 '13 at 21:20
  • Adding an event to any calendar will always require (one-time) authentication. However if you have done this once **and you save the token**, you can keep using that same token. (That's what the cookie does, now it is for one session but it can be permanent) So, onetime authentication is always needed but after that it can be click and go. – Rik Sep 16 '13 at 21:33
  • But for the rest, i'm stumped why you don't get past the authentication line **without an error**. Perhaps you can try a different server and/or browser. Although i thought you already tried another browser, perhaps a different server could get you further. BTW explanations about all the steps are [here](http://25labs.com/tutorial-implementing-google-api-using-oauth-2-0-in-php/). This sites gives comments about all the steps. – Rik Sep 16 '13 at 21:35
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/37482/discussion-between-user774359-and-rik) – Jake Sep 16 '13 at 21:49
0

The last portion of your code isn't using correct logic. The crux of the problem is with if (!$client->getAccessToken()). This statement, in the context of your sample code, roughly translates to: If you fail to get the access token, create the event. Obviously this is not what you want to happen. ;)

Instead try this:

if ($client->getAccessToken()){
    //succeeded in getting an access token, so create and insert the event
} else {
    $authUrl = $client->createAuthUrl();
    //failed to get an access token, so display $authurl as a link to open the auth window
}
BigMacAttack
  • 4,479
  • 3
  • 30
  • 39
  • Hmm, so that seemed to work, but it isn't exactly what I want, or perhaps it's just not working correctly. What I would like is to be able to run the php script, and then have an event added to a calendar I set up for this purpose. What seems to be happening is that every time I run the script, I get asked if I will authorize the application to be able to edit my calendars. When I click OK, I get sent to my redirect URI, but no event is actually added to the calendar. Running the script again just makes me repeat the authorization process. Here's my current code: http://pastebin.com/KTBuh6B6 – Jake Sep 11 '13 at 21:25