【Laravel×ZOOM API】JSON Web Tokensを自分で作成して実装してみた（APIリクエスト編）

#JWT認証を用いてZOOM APIでミーティング生成

本記事は下記内容の続編となります。
[【Laravel×ZOOM API】JSON Web Tokensを自分で作成して実装してみた（JWTトークン編）](https://qiita.com/joe-main/items/864c79b8f35c202b099b)

前回までの記事でZOOM APIを利用する際に必要となる認証方法をJWTとし、JWT認証に必要となるヘッダー、ペイロード、シグネチャーを一から作成しました。今回の記事では実際にZOOM APIを用いてミーティング作成&URL取得までの流れを順を追って説明していきたいと思います。

今回は④〜⑩までの内容になります。

#実装内容
今回の記事ではZOOMアカウントの登録とAPIKEY生成はスコープ外であるため割愛させていただきます。。公式ドキュメントや他Qiita様にも掲載があるのでそちらをご参照いただければ幸いです。

※公式ドキュメントはこちら：[Zoom Developer Platform](https://marketplace.zoom.us/docs/guides)


```php:ZoomMakeController.php
<?php

namespace App\Http\Controllers;
use App\Http\Controllers\Controller;

class ZoomController extends Controller
{
    //⓪文字列をURL-Safe Base64でエンコード（前回の記事）
    public static function urlsafe_base64_encode($str)
    {
       return str_replace(array('+', '/', '='), array('-', '_', ''), base64_encode($str));
    }

    //①ZOOM APIを使ったMeeting作成
     public function makeZoomMeeting()
     {
        //②リクエストURL、API KEY関連を設定（前回の記事）
        $zoom_url = 'https://api.zoom.us/v2/users/メールアドレス　 or Zoom userID/meetings';
        $zoom_api_key = API Key;
        $zoom_api_secret = API Secret;

        //③JWTトークン作成（前回の記事）
        $expiration = time() + 20;
        $header = self::urlsafe_base64_encode('{"alg":"HS256","typ":"JWT"}');
        $payload = self::urlsafe_base64_encode('{"iss":"' . $zoom_api_key . '","exp":"' . $expiration . '"}');
        $signature = self::urlsafe_base64_encode(hash_hmac('sha256', "$header.$payload", $zoom_api_secret, TRUE));
        $token = "$header.$payload.$signature";

        //④ポストする作成用の会議データを連想配列で生成
        $data_to_zoom_api = array(
         'type' => "1",
         'topic' => "会議室タイトル",
        );

        //⑤コンテキストのオプションを生成
        $options = array(
            'http' => array(
            'method'=> 'POST',
            'header'=> array(
                'Content-type: application/json',
                'Authorization: Bearer' . $token,
            ),
            'content' => json_encode($data_to_zoom_api)
            )
        );

        //⑥ストリームを使用してコンテキストを作成
        $context = stream_context_create($options);

        //⑦ZOOM APIにアクセスしてして結果を取得
        $json_result = file_get_contents($zoom_url, false, $context);

        //⑧JSON形式で返ってきた結果を配列で取得
        $json_result = json_decode($json_result, true);

        //⑨参加用URLを指定して取得
        $join_url = $json_result['join_url'];

        //⑩結果を表示
        echo $join_url;
    }
}
```

##④ポストする作成用の会議データを連想配列で生成
APIでリクストをする際に必要となるデータを連想配列で$data_to_zoom_apiに渡します。上記の例ではリクエストがあった段階でミーティングを即時生成する非常にシンプルな内容を実装しております。オプションで日時指定等さまざまな設定が可能ですので適宜ご参照ください。
[Zoom API リファレンス](https://marketplace.zoom.us/docs/api-reference/zoom-api/meetings/meetingcreate)

```php
  $data_to_zoom_api = array(
   'type' => "1",
   'topic' => "会議室タイトル",
   );
```

##⑤コンテキストのオプションを生成
ここではHTTPコンテキストオプションを記述しています。具体的には以下を指定しております。

|オプション|内容|その他|
|:---|:---|:---|
| method |POST|HTTPリクエスト種別を明示
|Content-type|JSON|ファイル形式を明示
|Authorization|Bearer認証|Accesstokenとして前回作成した$tokenを渡します|
|content|適宜|生成したい会議の内容である$data_to_zoom_apiをJSONに変換して渡します|

```php
  $options = array(
    'http' => array(
      'method'=> 'POST',
      'header'=> array(
        'Content-type: application/json',
        'Authorization: Bearer' . $token,
      ),
      'content' => json_encode($data_to_zoom_api)
      )
  );
```
[PHP公式マニュアル:HTTP コンテキストオプション](https://www.php.net/manual/ja/context.http.php)

##⑥ストリームを使用してコンテキストを作成

すみません。。。

ここの部分は調べてみたのですが私レベルでは正直理解できませんでした。

```php
$context = stream_context_create($options);
```

内容としては⑤で設定したオプション内容をstream_context_create() でストリームコンテキストに変換するようです。

後述のfile_get_contents()の引数に'content'の内容を渡すためには、一旦ストリームコンテキストに変換する必要がありそうです。

> コンテキスト は、ストリームの挙動を変えたり、 拡張したりすることのできる パラメータ と ラッパー固有の オプション の集合です。 コンテキスト は、 stream_context_create() を使って生成しますが、 これは、ほとんどのファイルシステム関連のストリーム生成関数に 渡すことができます (例えば fopen(), file(), file_get_contents() など)。

[PHP公式マニュアル:ストリームコンテキスト](https://www.php.net/manual/ja/stream.contexts.php)

##⑦ZOOM APIにアクセスして結果を取得
file_get_contents()を使ってZOOM APIを叩きmeetingを作成して結果を取得していきます。

```php
$json_result = file_get_contents($zoom_url, false, $context);
```

第一引数にはZOOM APIにアクセスするためのエンドポイントである以下のURIを記載します。
ここでは以下になります。

```php
$zoom_url = 'https://api.zoom.us/v2/users/メールアドレス　 or Zoom userID/meetings';
```

[PHP公式マニュアル:file_get_contents](https://www.php.net/manual/ja/function.file-get-contents.php)
[Zoom API リファレンス](https://marketplace.zoom.us/docs/api-reference/zoom-api/meetings/meetingcreate)

##⑧JSON形式で返ってきた結果を配列で取得
ZOOM APIにアクセスして成功するとJSON形式で結果が返ってきます。
ここでは第二引数にtrueを指定することでJSON形式から連想配列に変換しています。

```php
$json_result = json_decode($json_result, true);
```
[PHP公式マニュアル:json_encode](https://www.php.net/manual/ja/function.json-encode.php)

##⑨参加用URLを指定して取得
⑧で連想配列で取得した結果が返ってきているのでキーを指定して取得してきます。
今回の例では参加用のurlを指定して$join_urlに代入しています。

```php
$join_url = $json_result['join_url'];
```

##⑩参加用URLを指定して取得
最後にこちらで表示していきます。

```php
echo $join_url;
```

#まとめ
今回はZOOM APIを使用したJWT認証方法とAPIリクエストと結果の取得までを細かく順を追ってきました。
私自身、学習中の身であるため理解が難しい部分が多々ありましたが少しずつ、一つずつ紐解いていくことで処理の内容を把握できたと思っております。

**今回は実装内容をシンプルにしてどのような仕組みで動くのかを理解するためにAPIへのアクセス方法をfile_get_contents()を用いました。**

一方でAPIリクエスト送信をGuzzle、JWTトークン生成をlcobucci/jwt:3.3を用いる例もございますので適宜ご参照ください。
[[PHP] Zoom APIを利用してミーティングを作成する](https://qiita.com/gentuki/items/d64f15447cb556eafd3b)

知識が浅い中で公式ドキュメント（zoomに関しては英文）を読み込みながら実装を進めるのは非常に困難が伴います。
今回もシンプルな実装内容でしたが数多くのエラーに苦しみました。

似たような境遇の方に少しでも参考になれば幸いです。

#参考させて頂いた内容
[Zoom Developer Platform](https://marketplace.zoom.us/docs/guides)
[Zoom API リファレンス](https://marketplace.zoom.us/docs/api-reference/zoom-api/meetings/meetingcreate)
[PHP公式マニュアル:HTTP コンテキストオプション](https://www.php.net/manual/ja/context.http.php)
[PHP公式マニュアル:ストリームコンテキスト](https://www.php.net/manual/ja/stream.contexts.php)
[PHP公式マニュアル:file_get_contents](https://www.php.net/manual/ja/function.file-get-contents.php)
[PHP公式マニュアル:json_encode](https://www.php.net/manual/ja/function.json-encode.php)