Laravel + LINE API / Messaging APIを使ってみる(WIN+Docker+Ubuntu)

Laravel(WIN+Docker+Ubuntu)でLINE APIを使ってみたいので、ひとまず届いたメッセージをそのまま返してみる

作成日:2022-11-30, 更新日:2024-03-08

流れ

基本、下記2つの流れより追加作業していく感じ

なので、環境的には「Laravel(WIN+Docker+Ubuntu)」が出来上がっている状態

追加の流れ

  1. LaravelにLineAPIのSDKをインスト
  2. Laravelの設定
  3. LINEで確認

LaravelにLineAPIのSDKをインスト

▼UbuntuよりLaravelの「composer.json」のあるとこにカレントを移して実行

$ composer require linecorp/line-bot-sdk

エラー

いくつかのサイトを見て試してたんだけど、ココでは誰もエラーにならないようなんだけど、エラーが出てきた

▼とりあえず関係のあるとこ

Problem 1
- laravel/pint is locked to version v1.2.0 and an update of this package was not requested.
- laravel/pint v1.2.0 requires ext-xml * -> it is missing from your system. Install or enable PHP's xml extension.
Problem 2
- phpunit/phpunit is locked to version 9.5.26 and an update of this package was not requested.
- phpunit/phpunit 9.5.26 requires ext-dom * -> it is missing from your system. Install or enable PHP's dom extension.
Problem 3
- tijsverkoyen/css-to-inline-styles 2.2.5 requires ext-dom * -> it is missing from your system. Install or enable PHP's dom extension.
- laravel/framework v9.41.0 requires tijsverkoyen/css-to-inline-styles ^2.2.5 -> satisfiable by tijsverkoyen/css-to-inline-styles[2.2.5].
- laravel/framework is locked to version v9.41.0 and an update of this package was not requested.

正直、何を言っているかわかんない。
ひとまずお茶してから順番に読んでいくことにする

「Problem 1」を見ると「laravel/pint」ってのが問題あるっぽい
続けてみると「Install or enable PHP's xml extension.」とあるのでPHPの「xml extension」ってのを何かすればいいんでしょ?ってことで調べてみる
同じようなコトを言ってる人が何かしたヤツを真似してみる

▼Ubuntuより実行

$ sudo apt-get install php-xml

▼再度、Laravelの「composer.json」のあるとこにカレントを移して実行

$ composer require linecorp/line-bot-sdk

なんかいけたっぽい
→「vendor\linecorp\line-bot-sdk」が増えていたので多分、成功

Laravelの設定

やらなくちゃいけないこと

  • ルーティングの記載
  • コントローラーの記載

※ルーティングファイルの中でまとめてやる方法もあるらしいけど、将来的なコトを考えるとお試し用とはいえコントローラーに投げるようにしたい

今回、関係のあるURL、ファイルPATHとか

  • Webhookに設定するURLを「https://example.com/api/linebot/message」にしたい
  • コントローラーのほうは「app/Http/Controllers/Api/linebot/message.php」の「do()」にしたい

ルーティングの記載

▼routes/api.php

~ 省略 ~
use App\Http\Controllers\Api;
~ 省略 ~
Route::get('/linebot/message', [Api\linebot\message::class, 'do']);

コントローラーの記載

▼app/Http/Controllers/Api/linebot/message.php

<?php

namespace App\Http\Controllers\Api\linebot;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

// LINE関係
use LINE\LINEBot;
use LINE\LINEBot\Constant\HTTPHeader;
use LINE\LINEBot\Event\MessageEvent\TextMessage;
use LINE\LINEBot\HTTPClient\CurlHTTPClient;

class message extends Controller
{
    public function do( Request $request ) {
        $line_access_token = アクセストークン;
        $line_channel_secret = チャネルシークレット;
        
        $httpClient = new CurlHTTPClient($line_access_token);
        $bot = new LINEBot($httpClient, ['channelSecret' => $line_channel_secret]);

        $signature = $request->header(HTTPHeader::LINE_SIGNATURE);
        if (empty($signature)) {
            return abort(400, 'Bad Request');
        }
    
        $events = $bot->parseEventRequest($request->getContent(), $signature);
        if ( !is_array($events) || count($events) == 0 ) { // これが無いとdevelopers.line.bizのWebhookの検証がエラーになる
            return;
        }

        collect($events)->each(function ($event) use ($bot) {
            if ($event instanceof TextMessage) {
                return $bot->replyText($event->getReplyToken(), $event->getText());
            }
        });

        return;
    }
}

httpsが使えるサーバにアップしてLINEのWebhookの設定がまだなら設定する

LINEで確認

Webhookを設定済みならLINEから適当にメッセージを送って同じメッセージが返ってきたらOK

メモ

トークンの記載ミスのときに何かしたい

トークンの記載ミスは例外に飛ばしてくれるんだけどコントローラー側では制御できないっぽい
そもそもトークンの記載ミスのエラー処理は気にしなくてもいいんだけど、状況によっては必要になったりするので、そのメモ

▼トークンの記載ミスのときに問題となる箇所

$events = $bot->parseEventRequest($request->getContent(), $signature);

「parseEventRequest()」の中から例外処理として「InvalidSignatureException」に飛ばしてくれる
「app/Exceptions/Handler.php」を修正すれば良い感じになるという人もいたけどコントローラー側ではどうしようもできない回答している人がいた

「parseEventRequest()」の中を見て飛ばされている箇所を調べたら「SignatureValidator::validateSignature()」ってヤツだった
ということで、コントローラー側に「SignatureValidator::validateSignature()」をつっこめばいいんじゃない?ってことで試してみた
→さらに調べたら「LINE\LINEBot」の中に「validateSignature()」があった

▼追加分: try-catch()で全体を囲っておく

~ 省略 ~

// ▼追加
use Exception; // try-catch()の例外
// ▲追加

~ 省略 ~
    public function do( Request $request ) {
        // ▼追加
        try {
        // ▲追加

            ~ 省略 ~

            // ▼追加
            if ( !$bot->validateSignature($request->getContent(), $signature) ) {
                throw new Exception('Invalid signature has given');
            }
            // ▲追加

            $events = $bot->parseEventRequest($request->getContent(), $signature);

            ~ 省略 ~
        // ▼追加
        }
        catch (Exception $e) {
            ~ 好きな処理 ~
        }
        // ▲追加

    ~ 以下、省略 ~

リクエストを取得したい

「$event->getText();」でメッセージを取得ってのは分かるんだけど他の何かを取得したい
でも、リファレンスを見ても…どこに求めている情報があるのかが見つけられないって人への参考

▼下記のトコから「get〇〇〇()」を探す

  • LINEBot/Event/BaseEvent.php
  • LINEBot/Event/Parser/MessageEvent/xxx.php