3
1

More than 1 year has passed since last update.

LINE WORKS Bot メッセージ送受信機能(Laravel, Line works API 2.0)

Posted at

始めに

LINE WORKS Botチャット機能とwebアプリケーションを連携し、
webアプリケーション側からの送信機能、コールバック値を取得する機能

機能としては、大きく2つ
1、メッセージ通知(送信)
   チャットボットを利用しLINE WORKS上のトークルームにメッセージ送信(ボタン付き)
2、コールバック取得
   トークルームのチャット画面にて、送信されたボタン押下後に、
   値がwebアプリケーション側にコールバックされる

環境

開発環境 バージョン
LINE WORKS API 2.0
Laravel 8.60.0
PHP 7.3.10

初期設定

1、LINE WORKS Developer consoleでアプリを作成する
2、アプリの OAuth Scopes を bot に設定する
3、Bot を作成する
4、Bot の API Interface を API 2.0に設定する
5、Bot の Callback URL を追加しておく(Botに送信可能なタイプ:テキスト)
6、チャット画面でトークルームを作成する
7、トークルームに 2、で作成した Bot を招待する

メッセージ通知に必要な情報を取得しておく

パラメータに必要な情報(5つ)
( ↓ Developer consoleのアプリ内 ↓ )
 ・Client ID
 ・Client Secret
 ・Service Account
 ・Private Key
( ↓ Developer consoleのBot内 ↓ )
 ・bot ID
( ↓ チャット画面の指定したいトークルームから取得可 ↓ )
 ・channel ID

取得方法の参考URL
 https://qiita.com/kunihiros/items/54853e910ed1dff9ebdc

メッセージ通知(送信)

LineWorksController.php

    // LINE WORKSにメッセージ送信
    public function sendLineWorks(Request $request)
    {
        Log::debug(__FUNCTION__)

        try {

            // 初期設定
            $client_id          = 'Client ID';
            $client_secret      = 'Client Secret';
            $service_account_id = 'Service Account';
            $private_key        = 'Private Key'
                    // ------------------------------------------------------------------------
                                    <<< EOM
                                    -----BEGIN PRIVATE KEY-----
                                    // ... 略
                                    -----END PRIVATE KEY-----
                                    EOM;
                                    // ↑ Laravelの場合は、"<<< EOM", "EOM" をつける必要があった
                                    //   生PHの場合は、"<<< EOM", "EOM" または、ダブルクオーテーション
                                    //   keyファイルを直接読み込むことも可能
                    // ------------------------------------------------------------------------
            $bot_id              = "bot ID";
            $channel_id          = "channel ID";

            // トークンを取得する
            $token = $this->service->lw_get_accesstoken($client_id, $client_secret, $service_account_id, $private_key);

            // トークンが存在しない時
            if(!$token) {
                throw new Exception('トークンを取得できませんでした。');
            }

            // webhookURLを作成する(LINE WORKS トークルーム向け)
            $user_message_api = 'https://www.worksapis.com/v1.0/bots/'.$bot_id.'/channels/'.urlencode($channel_id).'/messages'; // チャンネル用

            // ヘッダー情報を配列に格納する
            $headers = ['Content-Type'  => 'application/json; charset=UTF-8',
                        'Authorization' => 'Bearer '.$token->access_token
                        ];

            // ペイロード情報を配列に格納する
            $payload = [
                "content"=> [
                    "type"=> "button_template",
                    "contentText"=> "あなたは、どちらに旅行したい?",
                    "actions"=> [[
                        // ボタン(上部)
                        "type"=> "message"
                        "label"=> "北海道"
                        ], [
                        // ボタン(下部)
                        "type"=> "message",
                        "label"=> "沖縄"
                    ]]
                ]
            ];

            // HTTPリクエストを送信する
            $response = \Http::withHeaders($headers)->post($user_message_api, $payload);

            // レスポンスが成功した時
            if($response->successful()) {
                // 送信成功
                Log::error(get_class($this).':'.__FUNCTION__);

            // レスポンスが失敗した時
            } else {
                // エラー処理
                Log::error(get_class($this).':'.__FUNCTION__);
            }

        } catch (Exception $e) {

            // エラー処理
            Log::error(get_class($this).':'.__FUNCTION__);
            Log::error($e->getMessage());
        }
    }
LineWorksService.php
    use Firebase\JWT\JWT;

    // アクセストークン取得
    public function lw_get_accesstoken($client_id, $client_secret, $service_account_id, $private_key)
    {
        // 初期設定
        $lw_auth_url = "https://auth.worksmobile.com/oauth2/v2.0/token";

        // トークンを取得する
        $token = $this->jwt_encode($client_id, $service_account_id, $private_key);

        // ヘッダー情報を配列に格納する
        $headers = ['Content-Type' => 'application/x-www-form-urlencoded'];

        $params = array(
            'assertion'     => $token,
            'grant_type'    => 'urn:ietf:params:oauth:grant-type:jwt-bearer',
            'client_id'     => $client_id,
            'client_secret' => $client_secret,
            'scope'         => 'bot',
        );

        try {

            $client = new \GuzzleHttp\Client;

            // HTTPリクエストを送信する
            // レスポンスを取得する
            $response = $client->post($lw_auth_url, [$headers, 'form_params' => $params]);

            // ステータスコードを取得する
            $status_code = $response->getStatusCode();

            // 通信が成功した時
            if($status_code == 200) {

                return json_decode($response->getBody());

            // 通信が失敗した時
            } else {
                // エラー処理
                return false;
            }
        }
        catch (\Exception $e) {
            // エラー処理
            Log::error(get_class($this).':'.__FUNCTION__);
            Log::error($e->getMessage());
        }
    }

    // エンコード処理
    private function jwt_encode($client_id, $service_account_id, $private_key)
    {
        try{
            $payload = array(
                'iss' => $client_id,
                'sub' => $service_account_id,
                'iat' => time(),
                'exp' => time() + 3600
            );

            // エンコード
            $encodedInfo = JWT::encode($payload, $private_key,'RS256');

            // エンコードされた値を返す
            return $encodedInfo;

        } catch (\Exception $e) {
            // ログ出力
            Log::error(get_class($this).':'.__FUNCTION__);
            Log::error($e->getMessage());
        }
    }

firebase/php-jwtがないよ、みたいなエラーが出てきたので、下記のコマンドで解決。
(JWT のライブラリとして firebase/php-jwt がLaravelに入っていない場合)

composer require firebase/php-jwt

コールバック取得

LineWorksCallbackController.php

    // LINE WORKS からのコールバック値を取得
    public function update(Request $request)
    {
        Log::debug(__FUNCTION__);

        $callbackInfo = $request->all();
        
        Log::debug($callbackInfo);
    }

コールバックが取得できなくてはまりました。
CSRFトークンのチェックが原因でした。💦
VerifyCsrfToken.phpにCSRF保護から除外したいURIを記載するだけ!

参考URL LaravelでCSRF保護からURIを除外する
https://curecode.jp/tech/laravel-csrf-check-except-with-specified-referer-uri/

終わりに

参考URLの作成者様方に助けられて、本当に感謝です。ありがとうございます。
ご指摘、ご意見等ありましたら、メッセージいただけますとありがたいです。
よろしくお願いします。

LINE WORKS 参考資料まとめ

・公式ドキュメント
 https://developers.worksmobile.com/jp/document?lang=ja

・API認証情報の取得方法まとめ
 https://qiita.com/kunihiros/items/54853e910ed1dff9ebdc

・【Line works API 2.0】LaravelでBotからユーザーにメッセージを送信する
 https://qiita.com/flatwhite/items/261b395adea70defe952

 

 

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1