Google Photos APIを使用して、Google Photoにアクセスするアプリを作成しています。
その過程でのAPIを利用するまでを記載します。
基本的にオフィシャルのリファレンスを参照していますが、そこから読み取りにくい部分などを具体的に紹介できたらと思っております。
Laravelを使用したコードを記載していますが、Laravelに特化した部分は少ないと思いますので、
Laravel以外のフレームワークを使っている場合もご参考になればと思います。
準備
Laravelプロジェクト作成
$ composer create-project laravel/laravel googlephoto_sample --prefer-dist
Google Photos APIを有効にする
- Google APIsのダッシュボードからプロジェクト作成 → APIとサービスを有効化 → Google Photos APIを選択
- Google APIsのプロジェクトが作成済みなら Google Photos API このページから直接もできます
クライアントID作成
- Google APIsのダッシュボードから「認証情報」を選択 → 認証情報を作成 → OAuthクライアントID
- アプリケーションの種類は、ウェブアプリケーション
- 承認済みのリダイレクトURIは、今回は取り合えず http://localhost/photo/redirect
- 作成したクライアントIDの画面からJSONをダウンロード → credential.jsonにリネームしておく
- ダウンロードしたcredential.jsonをLaravelプロジェクトのフォルダに入れておきます。
Google APIs Client, Google Photos API ライブラリのインストール
"require": {
"google/apiclient": "^2.0",
"google/photos-library": "^1.5"
},
$ composer update
composer.jsonを編集せずに、直接コマンドラインかrcomposer require google/apiclient:"^2.0"みたいにやるとなぜか失敗します。
Google Photos APIを使ってみる
PhotoControllerという名前のコントローラーと、コントローラーから呼び出されるGooglePhotoServiceという名前のクラスを作成していきます。
認証URLの生成、表示
<?php
namespace App\Services;
use Google\Auth\Credentials\UserRefreshCredentials;
use Google\Photos\Library\V1\PhotosLibraryClient;
class GooglePhotoService
{
private function createGoogleClient()
{
$client = new \Google_Client();
$client->setApplicationName('GooglePhotoSample');
$client->setScopes(\Google_Service_PhotosLibrary::PHOTOSLIBRARY_READONLY);
$client->setAuthConfig(base_path("credentials.json"));
$client->setAccessType('offline');
return $client;
}
public function createAuthUrl($redirectUri)
{
$client = $this->createGoogleClient();
$client->setRedirectUri($redirectUri);
return $client->createAuthUrl();
}
}
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Services\GooglePhotoService;
class PhotoController extends Controller
{
public function start()
{
$service = new GooglePhotoService();
$url = $service->createAuthUrl("http://localhost/photo/redirect");
return view(start, [
'url' => $url
]);
}
}
<html>
<body>
<div class="flex-center position-ref full-height">
<div class="content">
Step.1<br/>
<a href="{{$url}}">{{$url}}</a>
</div>
</div>
</body>
</html>
Route::get('/photo/start, 'PhotoController@start);
OAuthのリダイレクト先を作成
リダイレクト時に受け取ったauthCodeをもとにアクセストークンを取得する。
取得したアクセストークンを保存する処理は$saveTokenFunctionという名前のコールバック関数として定義する。
public $saveTokenFunction = null;
public function getAccessToken($authCode)
{
$client = $this->createGoogleClient();
$accessToken = $client->fetchAccessTokenWithAuthCode($authCode);
if ($this->saveTokenFunction != null) {
call_user_func($this->saveTokenFunction, $accessToken);
}
return $accessToken;
}
public function saveToken($accessToken)
{
// 保存の処理は省略。データベースなどに保存
}
public function redirect(Request $request)
{
$authCode = $request->input('code');
$service = new GooglePhotoService();
$service->saveTokenFunction = [$this, 'saveToken'];
$service->getAccessToken($authCode);
return view('redirect', [
]);
}
// 省略
Route::get('/photo/redirect, 'PhotoController@redirect);
PhotosLibraryClientを生成
取得したアクセストークンで、PhotosLibraryClientを生成
アクセストークンの期限が切れたときのリフレッシュの処理も一緒に実装
public function getPhotosLibraryClient($accessToken)
{
$client = $this->createGoogleClient();
$client->setAccessToken(json_decode($accessToken, true));
if ($client->isAccessTokenExpired())
{
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
if ($this->saveTokenFunction != null) {
call_user_func($this->saveTokenFunction, $client->getAccessToken());
}
}
$authCredentials = new UserRefreshCredentials(\Google_Service_PhotosLibrary::PHOTOSLIBRARY_READONLY, [
"client_id" => $client->getClientId(),
"client_secret" => $client->getClientSecret(),
"refresh_token" => $client->getRefreshToken()
]);
return new PhotosLibraryClient(['credentials' => $authCredentials]);
}
PhotosLibraryClientを使用してGoogle Photoからアルバム情報を取得してみる
public function listAlbums()
{
$accessToken = [] // 保存してあるアクセストークンを取得する処理
// 例) $accessToken = UserToken::where('user_id', auth()->user()->id)->value('token');
$service = new GooglePhotoService();
$service->saveTokenFunction = [$this, 'saveToken'];
$client = $service->getPhotosLibraryClient($accessToken);
$pagedResponse = $client->listAlbums();
$data = [];
foreach ($pagedResponse->iterateAllElements() as $album) {
$data[] = $album->getTitle();
}
return response()->json([
"title" => $data
]);
}
Route::get('/photo/albums', 'PhotoController@listAlbums');
以上です
authCodeからAccessTokenを取得する処理を、なんとかAPIだけで完結させたかったのですが
できませんでした。今回は、このような形でウェブページを一度経由してその後APIで利用するという形になりました。