Googleカレンダーとララヴィルサイトの統合


Google APIを利用してGoogleカレンダーをクライアントサイトに統合することで仕事の終わりになっています.私は、私がうまくいけば、これをする必要がある次の人を助けるために我々の解決を書くと思いました.

イントロ


クライアントは、彼らの活動のためにスペースを必要とした若者組織で、無料であるか低コストスペースを提供する会場をつなぎたかったです.
会場は、彼らが可用性を持っているときに表示するカレンダーとサイト上のプロファイルがあります.要件は、このカレンダーに予約を追加することができますし、自動的にリンクされたGoogleカレンダーとその逆に追加することができる会場だった.

概要



イメージソース:https://developers.google.com/identity/protocols/OAuth2
ためには、会場のリンクされたGoogleカレンダーから任意のデータをプルする会場は、それにアクセスするためにサイトに同意を与える必要があります.
会場の上の図に記載されているように、同意を与えている同意はサイトがサイトコードをGoogle APIでアクセストークンのために交換することができる認可コードで提供します.このアクセストークンは、会場がアクセスを承諾したサービスと対話するためにのみ使用できます.この場合、Googleカレンダーです.

プロジェクトの作成


非常に最初のステップは、クライアントがGoogleアカウントを使用してプロジェクトを設定する取得することでした.Googleからのクイックスタートガイドは良いチュートリアルです.https://developers.google.com/google-apps/calendar/quickstart/php
また、デモを取得し、実行に行くが、私はそれをスキップするつもりです.
プロジェクトが設定されると、クライアントはこのプロジェクトを通じてGoogleカレンダーAPIにアクセスするための資格情報を設定する必要がありました.

資格情報の追加


資格情報を作成するウィザードがあります.その驚くほど明確ではないので、ここで我々の設定のスクリーンショットです.注:クライアントデータの代わりにダミーコンテンツを使用しました.
最初のステップはどのAPIを使用するか、どのようにアクセスされるかを尋ねます

番目のステップホワイトリストのURLとセットアップauauthコールバックパス.

番目のステップは、会場が提示される同意フォームの設定を設定します.

番目のステップはクライアントIDと資格情報を与えます.

最後の画面で'ダウンロード'をクリックすると、クライアントプロジェクトを経由してAPIへのサイトキーです.これは、プライベートな場所にサーバーに格納する必要があります.
{  
   "web":{  
      "client_id":"[hash-string].apps.googleusercontent.com",
      "project_id":"calendar-integration-[project-id]",
      "auth_uri":"https://accounts.google.com/o/oauth2/auth",
      "token_uri":"https://accounts.google.com/o/oauth2/token",
      "auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs",
      "client_secret":"[hash-string]",
      "redirect_uris":[  
         "https://www.example.com/oauth2callback"
      ],
      "javascript_origins":[  
         "https://www.example.com"
      ]
   }
}

Google APIクライアントを必要とする


これがララヴィルサイトであるので、私たちはすでに作曲家のセットアップを持っています.composer require google/apiclient:^2.0これは、Google APIと、各APIとOAuth 2のヘルパー関数の負荷を通信するPHPライブラリを提供します.
詳細はこちらhttps://github.com/google/google-api-php-client

認可


承諾を求める


サイトのための最初のステップは、サイトのGoogleカレンダーにアクセスするための同意を与える会場の手段を提供することです.
そのために、我々は同意画面を示すGoogleに会場を送るリンクを作成する必要があります.
このために、我々は提供されるGoogleクライアントを初期化しますgoogle/apiclient とアプリケーション固有の設定を設定します.
<?php

namespace App\Helpers;

// Initialise the client.
$client = new Google_Client();
// Set the application name, this is included in the User-Agent HTTP header.
$client->setApplicationName('Calendar integration');
// Set the authentication credentials we downloaded from Google.
$client->setAuthConfig('[private-path]/client_id.json');
// Setting offline here means we can pull data from the venue's calendar when they are not actively using the site.
$client->setAccessType("offline");
// This will include any other scopes (Google APIs) previously granted by the venue
$client->setIncludeGrantedScopes(true);
// Set this to force to consent form to display.
$client->setApprovalPrompt('force');
// Add the Google Calendar scope to the request.
$client->addScope(Google_Service_Calendar::CALENDAR);
// Set the redirect URL back to the site to handle the OAuth2 response. This handles both the success and failure journeys.
$client->setRedirectUri(URL::to('/') . '/oauth2callback');

注意:上記のコードブロックは、Google APIとのすべての対話に使用されます.我々はヘルパークラスにこれを置くので、我々はどこにも重複する必要はありません.
一度GoogleクライアントのセットアップをすることができますcreateAuthUrl() Googleカレンダーに同意を与えるために、Googleへのリンクを返す方法.
<?php
// Set state allows us to match the consent to a specific venues
$client->setState($venue->id);
// The Google Client gives us a method for creating the 
$client->createAuthUrl();
会場がリンクをクリックすると、Googleにリダイレクトされ、Googleカレンダーにアクセスするためのサイトの同意を得るように求められます.

レスポンスの処理


Googleは、ここで指定されたURLでサイトに会場をリダイレクトします$client->setRedirectUri(URL::to('/') . '/oauth2callback'); . このルートは、会場がGoogleカレンダーにアクセスするために同意した場合、それらが拒否された場合に使用されます.
<?php
/**
 * Google OAuth2 route
 */
Route::get('oauth2callback', [
    'as' => 'oauth',
    'uses' => 'OAuthController@index'
]);
このルートはGETリクエストが行われたときに/oauth2callback その後、index メソッドOAuthController コントローラ.
ラーレスのルーティングについての詳細は、次のとおりです.https://laravel.com/docs/5.5/routing
これは以下のようになります.
<?php

public function index(Request $request)
    {
        // Get all the request parameters
        $input = $request->all();

        // Attempt to load the venue from the state we set in $client->setState($venue->id);
        $venue = Venue::findOrFail($input['state']);

        // If the user cancels the process then they should be send back to
        // the venue with a message.
        if (isset($input['error']) &&  $input['error'] == 'access_denied') {
            \Session::flash('global-error', 'Authentication was cancelled. Your calendar has not been integrated.');
            return redirect()->route('venues.show', ['slug' => $venue->slug]);

        } elseif (isset($input['code'])) {
            // Else we have an auth code we can use to generate an access token

            // This is the helper we added to setup the Google Client with our             
            // application settings
            $gcHelper = new GoogleCalendarHelper($venue);

            // This helper method calls fetchAccessTokenWithAuthCode() provided by 
            // the Google Client and returns the access and refresh tokens or 
            // throws an exception
            $accessToken = $gcHelper->getAccessTokenFromAuthCode($input['code']);

            // We store the access and refresh tokens against the venue and set the 
            // integration to active.
            $venue->update([
                'gcalendar_credentials' => json_encode($accessToken),
                'gcalendar_integration_active' => true,
            ]);

            \Session::flash('global-success', 'Google Calendar integration enabled.');
            return redirect()->route('venues.show', ['slug' => $venue->slug]);
        }
    }

これにより、我々はアクセストークンを使用して会場のGoogleカレンダーにアクセスすることができますfetchAccessTokenWithAuthCode() . このメソッドは、他のいくつかのビットを返します.
{  
   "access_token":"[hash-string]",
   "token_type":"Bearer",
   "expires_in":3600,
   "created":1510917377,
   "refresh_token":"[hash-string]"
}
この返り値はデータベース内のストレージ用にJSONエンコードされました.
このトークンは、expires_in 上記.アクセストークンが期限切れになるとrefresh_token 新しいアクセストークンを要求する.

アクセストークンのリフレッシュ


Googleクライアントは、現在のアクセストークンが期限切れになっているかどうかをチェックするメソッドを提供します.私たちは価値がある$venue->gcalendar_credentials これは上のjsonですsetAccessToken() そして、期限切れになるとトークンをリフレッシュします.
<?php
// Refresh the token if it's expired.
$client->setAccessToken($venue->gcalendar_credentials);
if ($client->isAccessTokenExpired()) {
    $accessToken = $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
    $venue->update([
        'gcalendar_credentials' => json_encode($accessToken),
    ]);
}
我々は、再び会場に対してデータベースでそれを保存します.これは、Googleクライアントを初期化するヘルパークラスの設定に追加されました.

Googleカレンダーからの予約を引く


現在、我々はイベントのために会場のGoogleカレンダーをポーリングし始めることができる有効なアクセストークンを持っています.
<?php

// Load up the helper to initialise the Google Client
$gcHelper = new GoogleCalendarHelper($venue);

// Use the Google Client calendar service. This gives us methods for interacting 
// with the Google Calendar API
$service = $gcHelper->getCalendarService();

// Set over what timeframe we want to grab calendar events
// Dates must be an RFC3339 timestamp with mandatory time zone offset, e.g.,
// 2011-06-03T10:00:00-07:00
$optParams = array(
    'orderBy' => 'startTime',
    'singleEvents' => true,
    'timeMin' => '2011-06-03T10:00:00-07:00',
    'timeMax' => '2011-06-03T10:00:00-23:00',
);

// Poll this venue's Google Calendar
$googleBookings = $service->events->listEvents($calendarId, $optParams);

// Check if we have any events returned
if (count($googleBookings->getItems()) > 0) {
一度Googleカレンダーからイベントのリストを我々は、サイト上の予約として表示するデータベースにそれらを保存します.

Googleカレンダーに予約を押す


会場がサイトに予約を追加すると、自動的にGoogleカレンダーで作成されます.
<?php

// Set the start time and date for pushing to Google.
$tz = new DateTimeZone('Europe/London');
$startTime = Carbon::create(
    2017,
    11,
    25,
    10,
    0,
    0,
    $tz
);

// Use the Google date handling provided by the Google Client
$googleStartTime = new Google_Service_Calendar_EventDateTime();
$googleStartTime->setTimeZone($tz);
$googleStartTime->setDateTime($endTime->format('c'));

// Create the calendar event and give a default title.
$event = new Google_Service_Calendar_Event();
$event->setStart($googleStartTime);
// Same process to create end time as we use for the start time above. Code 
// omitted for brevity.
$event->setEnd($googleEndTime);
$event->setSummary('Booking automatically created from Calendar Example');

// Use the Google Client calendar service to push 
$service = $gcHelper->getCalendarService();
$createdEvent = $service->events->insert($calendarId, $event);

// Save the newly created event id against the booking.
if (!empty($createdEvent->id)) {
If the $createdEvent IDを持って、我々は新しいイベントとしてGoogleカレンダーにこの予約を押すことに成功しました.
このIDは、Googleカレンダーからイベントを削除するために使用できます$service->events->delete($calendarId,$eventId); .

ゴチャス


トークンを更新する


経験から$client->setApprovalPrompt('force'); はAuthトークンと一緒にリフレッシュトークンを返す必要があります.このように見えるの記事の負荷を見て、それはまた、ユーザーがauthトークンが期限切れになるたびに、Googleカレンダーに同意を与えることを強制する必要がありますが、これは私たちのためのケースではありませんでした.

タイムゾーン


会場のGoogleカレンダーでイベントを作成したときにタイムゾーンを設定してくださいEurope/London . デフォルトではAPIはアメリカンタイムゾーンのいずれかを使用します.これはイギリスでは私たちにはふさわしくなかった.

イベント作成


イベントがAPIを通してつくられるとき、会場はまだ彼らを彼らのカレンダーに引き込む必要がありました.これは誰かがイベントに招待したときと同じように動作し、あなたのカレンダーに入る前に、あなたが受け入れる必要があります.

概要


要約では、Google APIを使用してかなりまっすぐ前方にgoogle/apiclient . OAuthのものはトリッキーな部分でした.そして、それはほとんどAuth/Access/Refreshトークンがどのように働くかについてのSOと他のサイトの多くの矛盾する情報にほとんどダウンしました.
Googleドキュメント自体は最良のケースのシナリオに適していますが、物事がうまくいかないときの情報は存在しません.
すべてのコメント歓迎