PHP の Google Cloud SDK でサポートされていない API をお手軽にリクエストする

# はじめに
[GameWith AdventCalendar 2020](https://qiita.com/advent-calendar/2020/gamewith) の18日目の記事になります。

# 概要

今回の内容は非常にニッチですが、 PHP の Google Cloud SDK でサポートされていない API は直接リクエストをする必要があります。
直接リクエストをする場合は、 `OAUTH2_TOKEN` が必要になりますが発行方法について、あまり記事が見当たらなかったので、ご紹介いたします。

# どうやるのか
PHP で Google Auth のライブラリが公開されているので、こちらを利用します。
https://github.com/googleapis/google-auth-library-php

また、今回は GCP のサービスアカウントの認証情報を元にソースコードの記述をしています。

### セットアップ

まずは、 composer でインストールをします。

```console
$ ./composer.phar require google/auth
```

`google/auth` の依存関係で含まれているのでインストールしなくても動作しますが、
いつ依存関係が外れるか分からないので guzzle も明示的にインストールします。

```console
$ ./composer.phar require guzzlehttp/guzzle
```

### ソースコード

ライブラリの準備は整ったので、早速コードを書いていきましょう。
今回は SDK サポートはされていますが、Google Cloud Storage の Bucket 一覧を取得するコードを記述いたします。

```command.php
<?php
declare(strict_types=1);

use Google\Auth\ApplicationDefaultCredentials;
use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;

require __DIR__ . '/vendor/autoload.php';

// どのリソースにアクセス出来るかスコープを設定します。
// スコープの内容は Google Cloud の API ドキュメントに記載されています。
// https://cloud.google.com/storage/docs/authentication
$scopes = ['https://www.googleapis.com/auth/devstorage.read_only'];

// 下記の middleware を guzzle に適用すると、リクエストする際に `Authorization: Bearer xxxx` を HEADER に挿入してくれます。
$middleware = ApplicationDefaultCredentials::getMiddleware($scopes);
$stack = HandlerStack::create();
$stack->push($middleware);

// 以下の API ドキュメントを参考にし、 base_uri を設定する。
// https://cloud.google.com/storage/docs/json_api/v1
$client = new Client([
    'handler' => $stack,
    'base_uri' => 'https://storage.googleapis.com',
    'auth' => 'google_auth'
]);

// バケット一覧を取得する
// https://cloud.google.com/storage/docs/json_api/v1/buckets/list
$response = $client->get('/storage/v1/b', [
    'query' => [
        'project' => '[Bucket 一覧を取得したい project id]'
    ]
]);

print_r((string) $response->getBody());
```

### 実行

credentials ファイルパスを環境変数にセットしておく必要がありますので、以下のコマンドを実行します。

```console
$ export GOOGLE_APPLICATION_CREDENTIALS=[credentials の filepath]
```

準備が整ったので早速実行してみましょう。

```console
$ php command.php
```

無事取得できました。

```js
{
  "kind": "storage#buckets",
  "items": [
    {
      "kind": "storage#bucket",
      "selfLink": "https://www.googleapis.com/storage/v1/b/xxxx",
      "id": "xxx",
      "name": "xxx",
      "projectNumber": "xxx",
      "metageneration": "1",
      "location": "US",
      "storageClass": "STANDARD",
      "etag": "CAE=",
      "timeCreated": "1970-01-01T00:00:00.000Z",
      "updated": "1970-01-01T00:00:00.000Z",
      // ...
    }
  ]
}
```

# トークンだけ取得したい場合

以下の様に CredentialsLoader を呼び出すことで取得が可能です。

### ソースコード

```token.php
<?php
declare(strict_types=1);

use Google\Auth\CredentialsLoader;

require __DIR__ . '/vendor/autoload.php';

// 環境変数 の GOOGLE_APPLICATION_CREDENTIALS を参照して認証情報を取得します。
$jsonKey = CredentialsLoader::fromEnv();

// どのリソースにアクセス出来るかスコープを設定します。
// スコープの内容は Google Cloud の API ドキュメントに記載されています。
// https://cloud.google.com/storage/docs/authentication
$scopes = ['https://www.googleapis.com/auth/devstorage.read_only'];

// トークンを取得します
$token = CredentialsLoader::makeCredentials($scopes, $jsonKey)->fetchAuthToken();

var_export($token);
```

### 実行
credentials ファイルパスを環境変数にセットしておく必要がありますので、以下のコマンドを実行します。

```console
$ export GOOGLE_APPLICATION_CREDENTIALS=[credentials の filepath]
```

先ほど作成した、 token.php を実行します。

```console
$ php token.php
```

無事取得できました。
以下の情報をもとに リクエストヘッダーに `Authorization: [token_type] [access_token]` を追加して API にアクセスすることも可能です。

```console
array (
    'access_token' => 'xxx',
    'expires_in' => 3600,
    'token_type' => 'Bearer',
)
```

# 終わりに

ネタ探しにひたすら迷い続け・・・ネタを思いついて途中まで書いては、
「あ、このネタ没だ」と、スプラトゥーン2で現実逃避をし行き着いた果てがこれです :sweat_smile:
来年も機会あれば書きたいと思いますので、よろしくお願いいたします。