PHPからService AccountsとしてGoogleカレンダーAPIにアクセスしてみる
今更感漂いますが気にしない:-)
ちょっとGoogleカレンダーにアクセスするバッチアプリを書いてたんですが、いろいろと苦労したのでまとめてみます。
前置き
PHPからGoogleのAPI群にアクセスする記事はいろいろありますが、ユーザーがブラウザを介してアクセスするモノ(Web Server Applicationsと呼ばれる)がほとんどです。一方で、バッチアプリなどブラウザを介さずにGoogleのAPIにアクセス(Service Accountsと呼ばれる)するモノはあまり見つかりません。
上のリンクにある図を見比べてもらえれば分かりますが、これら2つの大きな違いは"User Login & Consent"の部分、つまり、ログインとアプリのアクセス許可があるかどうか?なんですが、バッチアプリの場合はこれをGoogle側の設定であったり、PHPコードで書く必要があります。
今回の環境
- CentOS5+PHP5.3.3(rpm)
- CentOS6+PHP5.5.3(src)
Google APIs Consoleでの作業
1. Google APIs Consoleにアクセスする
まずはGoogleアカウントでログインした後、Google APIs Consoleにアクセスします。
2. プロジェクトを作成する
デカデカと表示されている"Create project..."ボタンをクリックして、プロジェクトを作成します。
3. 利用するGoogleのサービスを設定する
プロジェクト作成後、Googleのサービス一覧が表示されますので、このプロジェクトで利用するサービスを"ON"にします。今回は"Calendar API"のトグルスイッチをクリックします。
4. OAuth 2.0用のクライアントIDを作成する
Google APIs Consoleの左メニューにある"API Access"をクリックし、表示される青い大きなボタンをクリックします。
ダイアログが表示されるので、Product nameに入力して"Next"ボタンをクリック。その他の項目は適宜入力してください。
"Client ID Setting"ダイアログが表示されますので、真ん中の"Service account"を選択して"Create client ID"ボタンをクリックします。クリックするとキーペアが生成されます。
10秒ほど時間がかかりますが、以下の様なダイアログが表示されたら、"Download private key"ボタンをクリックして秘密鍵をダウンロードします。
ダウンロードされる秘密鍵のファイル名は、
[0-9a-f]{40}-privatekey.p12
のようなパターンです。このp12ファイルはバッチアプリに必要です。また、p12ファイルはSSHなどの秘密鍵と同様、他のユーザーからの読み書きできないパスに保存し、p12ファイル自身の権限も変更しておきます。
3. Client IDとメールアドレスを確認する
クライアントIDを生成したダイアログを閉じると、Google APIs Console画面に以下のような項目が追加表示されているはずです。ここに表示されている
- Client ID
- Email address
Googleカレンダーの設定
これ、ハマりどころだと思うんですが、バッチアプリからカレンダーを参照/更新する場合のアカウントは、先ほど作成したクライアントになります。ですので、カレンダーを参照/更新する権限を、クライアントに追加しておく必要があります。
Googleカレンダーにアクセスし、バッチからアクセスするカレンダーの設定画面にある"このカレンダーを共有"タブから権限を与えておきます。今回は
- 予定の変更権限
PHPコードを書く
事前準備が終わったので、ようやくPHPコードの方です。
1. Google APIs Client Library for PHPをダウンロードする
Google APIs Client Library for PHPをダウンロードします。今回ダウンロードしたのは、ver.0.6.6です。
$ wget https://google-api-php-client.googlecode.com/files/google-api-php-client-0.6.6.tar.gz $ tar zxf google-api-php-client-0.6.6.tar.gz $
2. カレンダー一覧を取得してみる
以下の様なコードで動作を確認してみます。カレンダーの一覧が取得できればOKです。
<?php require_once '/path/to/src/Google_Client.php'; require_once '/path/to/src/contrib/Google_CalendarService.php'; const CLIENT_ID = 'xxxxxxxxxxxx.apps.googleusercontent.com'; const SERVICE_ACCOUNT_NAME = 'xxxxxxxxxxxx@developer.gserviceaccount.com'; const KEY_FILE = '/path/to/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-privatekey.p12'; $client = new Google_Client(); $client->setApplicationName("Google Prediction Sample"); $client->setAssertionCredentials(new Google_AssertionCredentials( SERVICE_ACCOUNT_NAME, array('https://www.googleapis.com/auth/calendar'), file_get_contents(KEY_FILE) )); $client->setClientId(CLIENT_ID); $service = new Google_CalendarService($client); $calList = $service->calendarList->listCalendarList(); var_dump($calList);
3. すべてのカレンダーに登録されたすべての予定を取得してみる
前半は先ほどのコードと同じです。
<?php : $service = new Google_CalendarService($client); $calList = $service->calendarList->listCalendarList(); foreach ($calList['items'] as $calendar) { $events = $service->events->listEvents($calendar['id']); foreach ($events['items'] as $event) { printf('%s - %s %s%s', (isset($event['start']['dateTime']) ? $event['start']['dateTime'] : $event['start']['date']), (isset($event['end']['dateTime']) ? $event['end']['dateTime'] : $event['end']['date']), $event['summary'], PHP_EOL ); } }
実行してみると分かりますが、開始日時と終了日時はISO-8601形式です。
4. カレンダーに予定を登録してみる
前半はこれまでのコードと同じです。登録する場合、イベント自体を表すGoogle_Eventクラスを使用します。開始・終了日時はGoogle_EventDateTimeオブジェクトでラップします。
<?php : $service = new Google_CalendarService($client); // Google_CalendarService.calendarList#listCalendarList()を使って // 登録対象のカレンダーのIDを取得しておく // : // $calendarId = ... ; /** * 予定(イベント)の作成 */ $event = new Google_Event(); $start_time = new Google_EventDateTime(); $start_time->setDateTime('2013-10-25T10:00:00+09:00'); $event->setStart($start_time); $end_time = new Google_EventDateTime(); $end_time->setDateTime('2013-10-25T11:00:00+09:00'); $event->setEnd($end_time); $event->setLocation('ヨドバシAkiba'); $event->setSummary('QX100を触りに行く'); $event->setDescription('QX100が展示されてたらいろいろと弄ってみる。Wi-Fi接続とかNFCとか。'); $service->events->insert($calendarId, $event);
カレンダーサービスのリファレンスは以下を参照してください。