Googleカレンダー連携 †OAuth認証後に Google Calendar APIを使用してカレンダー情報を取得する簡単なWebアプリケーションを作成する。 エンドポイントに対して直接リクエストを発行する場合のインターフェースは以下のURLを参照。 概要 †以下の通り、カレンダーAPIからのデータ取得を行う簡単なアプリケーションを作成する。 TODO: フォルダ構成、サンプル概要
※Google認証後のリダイレクトページも同じURIを使用する プロジェクトの作成と認証情報の設定/取得 †プロジェクトの登録 †Google API Console から プロジェクトを作成する APIの有効化 †(1) 対象のプロジェクトを選択して「APIとサービスの有効化」をクリック。 認証情報の作成 †(1)「認証情報の作成」から「OAuthクライアントID」をクリックして以下の通り入力して「作成」。 アプリケーションの種類: ウェブ アプリケーション (2) ”認証情報” の OAuth同意画面を以下の通り入力し、「保存」 ユーザーに表示するサービス名: カレンダー連携テストサービス (3) "認証情報" から作成したOAuthクライアントを選択し、「JSONをダウンロード」 Google クライアントライブラリをインストールする †ここでは composer でインストールする cd /path/to/www/ mkdir google-calendar && cd google-calendar composer require google/apiclient:^2.0 ※GitHubからダウンロードする場合はダウンロード後、上記ディレクトリ(/path/to/www/google-calendar配下)に解凍 参考 †連携処理の作成 †TODO: 登録/更新/削除
/path/to/www/test/google-calendar/index.php <?php date_default_timezone_set('Asia/Tokyo'); //error_reporting(E_ALL); require_once 'vendor/autoload.php'; // OAuthクライアント認証用のJSONファイル $oauth_credentials = "/path/to/client_secret.json"; // 上記でダウンロードしたJSONファイルのPATH // Google認証後のリダイレクト先(「http://localhost/test/google-calendar/?code=アクセストークン」 という形でリダイレクトされる) $redirect_uri = "http://localhost/test/google-calendar/"; // トークンの退避用 TODO: テスト用(本番時はDB等に退避する) $token_file = "/tmp/google-calendar-api-token-cache.txt"; session_start(); // セッションを破棄する(テスト用) // ※退避しておいたトークンを使用して認証が通る事の確認用 if (isset($_REQUEST['logout'])) { session_destroy(); session_start(); header("Location: " . $redirect_uri); exit; } // トークンを破棄する(テスト用) // ※アカウントの再選択を行いたい場合 if (isset($_REQUEST['remove-token'])) { session_destroy(); session_start(); file_put_contents($token_file, ""); header("Location: " . $redirect_uri); exit; } $msg = ""; // 取得済みのトークンがある場合はセッションにセット TODO: 本番時はDBから取得 if (empty($_SESSION['google-calendar-api-token'])) { if (file_exists($token_file)) { $tokenText = file_get_contents($token_file); if (trim($tokenText) !== "") { $msg = "トークンをファイルから取得しました。"; $_SESSION['google-calendar-api-token'] = unserialize(file_get_contents($token_file)); } } } // Google API Client $client = new Google_Client(); $client->setAuthConfig($oauth_credentials); $client->setRedirectUri($redirect_uri); $client->addScope(Google_Service_Calendar::CALENDAR); $client->setAccessType("offline"); // トークンの自動リフレッシュ $client->setApprovalPrompt("force"); // これがないと初回以外はリフレッシュトークンが得られない $authUrl = $client->createAuthUrl(); // 認証後のリダイレクトの場合 if (isset($_GET['code'])) { $token = $client->fetchAccessTokenWithAuthCode($_GET['code']); $_SESSION['google-calendar-api-token'] = $token; header("Location: ${redirect_uri}"); exit; } // トークンの有効期限が切れている場合はリフレッシュトークンを使用して最新のトークンを得る if (!empty($_SESSION['google-calendar-api-token'])) { $client->setAccessToken($_SESSION['google-calendar-api-token']); If ($client->isAccessTokenExpired()) { if (isset($_SESSION['google-calendar-api-token']["refresh_token"])) { $client->refreshToken($_SESSION['google-calendar-api-token']["refresh_token"]); } else { unset($_SESSION['google-calendar-api-token']); } } } // トークンが無効な場合は認証ページにリダイレクト $accessToken = $client->getAccessToken(); if (!$accessToken) { header("Location: ${authUrl}"); exit; } $_SESSION['google-calendar-api-token'] = $accessToken; // トークンを退避 TODO: 本番時はDBなどに退避する $tokenText = serialize($_SESSION['google-calendar-api-token']); file_put_contents($token_file, $tokenText); // カレンダーAPI用のインスタンス生成 $cal_service = new Google_Service_Calendar($client); // カレンダ一覧を取得 $calendar_list = array(); $calendarList = $cal_service->calendarList->listCalendarList(); while(true) { foreach ($calendarList->getItems() as $i => $calendarListEntry) { $rec = $calendarListEntry; $calendar_list[] = $rec; } $pageToken = $calendarList->getNextPageToken(); if ($pageToken) { $optParams = array('pageToken' => $pageToken); $calendarList = $service->calendarList->listCalendarList($optParams); } else { break; } } // イベント情報 $calender_idx = 0; $calender_id = "primary"; if (isset($_REQUEST["calender_idx"])){ if (isset($calendar_list[$_REQUEST["calender_idx"]])){ $calender_idx = $_REQUEST["calender_idx"]; $calender_id = $calendar_list[$calender_idx]["id"]; } } $event_list = array(); $optParams = array(); /* 日付指定する場合 */ $optParams["timeMin"] = "2017-01-01T00:00:00+0900"; // "2017-01-01T00:00:00Z"; $optParams["timeMax"] = "2017-12-31T23:59:59+0900"; $optParams["timeZone"] = "Asia/Tokyo"; $optParams["singleEvents"] = true; $optParams["orderBy"] = "startTime"; // orderBy指定する場合は singleEvents=true でないと怒られる $events = $cal_service->events->listEvents($calender_id, $optParams); while(true) { foreach ($events->getItems() as $event) { $rec = array(); $rec["id"] = $event->getId(); $rec["start"] = $event->getStart()->date ? $event->getStart()->date : $event->getStart()->dateTime; $rec["end"] = $event->getEnd()->date ? $event->getEnd()->date : $event->getEnd()->dateTime; $rec["summary"] = $event->getSummary(); $event_list[] = $rec; } $pageToken = $events->getNextPageToken(); if ($pageToken) { $optParams['pageToken'] = $pageToken; $events = $cal_service->events->listEvents($calender_id, $optParams); } else { break; } } // 描画 require_once("view/calendar.php"); ?> Viewの作成 †/path/to/www/test/google-calendar/view/calendar.php <!doctype html> <html lang="ja"> <head> <meta charset="utf-8" /> <style> * { font-size: 16px; } h1,h2,h3,h4,h5 { margin: 0; } .tbl { border-collapse: collapse; border-spacing: 0; } .tbl th { background: #ccc; } .tbl th, .tbl td{ padding: 1px 10px; border: 1px solid #333; } html,body { height: 100%; } #loading_layer { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.7); } #loading_inner { position: fixed; top: 50%; left: 50%; width: 200px; height: 50px; margin-left: -100px; margin-top: -25px; background: #fff; border-radius: 4px; overflow-y: hidden; } #loading_msg { padding-top: 10px; padding-bottom: 10px; text-align: center; vertical-align: middle; } </style> </head> <body> <div><?= $msg ?></div> <div style="position:relative;"> <div style="position:absolute;top:0;right:10px;"> セッション破棄 トークン破棄 </div> <div style="display:inline-block"> カレンダー : <select id="calendar_id"> <?php foreach ($calendar_list as $idx => $rec) {?> <option value="<?= $idx ?>" <?= $calender_idx == $idx ? "selected" : "" ?>><?= $rec["summary"] ?></option> <?php } ?> </select> </div> </div> <table class="tbl" style="margin-top:4px"> <thead> <tr> <th>Id</th> <th>Start</th> <th>End</th> <th>Summary</th> </tr> </thead> <tbody> <?php foreach ($event_list as $rec) { ?> <tr> <td><?= $rec["id"] ?></td> <td><?= $rec["start"] ?></td> <td><?= $rec["end"] ?></td> <td><?= $rec["summary"] ?></td> <tr> <?php } ?> </tbody> </table> <div id="loading_layer" style="display:none"> <div id="loading_inner"><div id="loading_msg">Now Loading...</div></div> </div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script> <script> jQuery(function($){ $("#calendar_id").on("change", function(){ $("#loading_layer").show(); location.href = "./?calender_idx=" + $(this).val(); }); }); </script> </body> </html> APIリファレンス †以下はAPIのエンドポイントを直叩きする場合用の記載になっているが、クライアントAPIを利用する場合でもオプション引数などはそのまま使える。 サンプルソース † |