💬
LaravelでLINE Botのフォローイベントをフックする #laravel #messagingapi #php
はじめに
の続きです。
前回作成した LINE Bot を改修して、フォローイベント
(友達登録時/ブロック解除時に発生するイベント)に応答できるように変更します。
少しハマったので、後半で説明します。
完成イメージ
環境
- MacBook Air (M1, 2020)
$ sw_vers
ProductName: macOS
ProductVersion: 12.2.1
BuildVersion: 21D62
参考URL
- フォローイベント | Messaging APIリファレンス | LINE Developers
- line-bot-sdk-php/examples/EchoBot at master · line/line-bot-sdk-php
事前準備
下記記事の手順を実施し、オウム返しが動く状態にしておきます。
コーディング
routes/app.php
を下記の通り変更します。
<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use LINE\LINEBot;
use LINE\LINEBot\Constant\HTTPHeader;
+ use LINE\LINEBot\Event\FollowEvent;
+ use LINE\LINEBot\Event\MessageEvent\TextMessage;
+ use LINE\LINEBot\HTTPClient\CurlHTTPClient;
(略)
$httpClient = new CurlHTTPClient($_ENV['LINE_CHANNEL_ACCESS_TOKEN']);
$bot = new LINEBot($httpClient, ['channelSecret' => $_ENV['LINE_CHANNEL_SECRET']]);
Route::post('/webhook', function (Request $request) use ($bot) {
- $request->collect('events')->each(function ($event) use ($bot) {
- $bot->replyText($event['replyToken'], $event['message']['text']);
- });
+ $signature = $request->header(HTTPHeader::LINE_SIGNATURE);
+ if (empty($signature)) {
+ return abort(400, 'Bad Request');
+ }
+
+ $events = $bot->parseEventRequest($request->getContent(), $signature);
+
+ collect($events)->each(function ($event) use ($bot) {
+ if ($event instanceof TextMessage) {
+ return $bot->replyText($event->getReplyToken(), $event->getText());
+ }
+ if ($event instanceof FollowEvent) {
+ return $bot->replyText($event->getReplyToken(), '[bot]友達登録されたよ!');
+ }
+ });
return 'ok!';
});
変更概要
+ $events = $bot->parseEventRequest($request->getContent(), $signature);
-
LINE\LINEBot
クラスのparseEventRequest
メソッドを使うよう変更。署名検証もこのメソッドでできる。便利。 - 公式サンプルの使用例: line-bot-sdk-php/Route.php at master · line/line-bot-sdk-php
+ if ($event instanceof FollowEvent) {
+ return $bot->replyText($event->getReplyToken(), '[bot]友達登録されたよ!');
+ }
- フォローイベントのときの条件分岐を追加。
- 友達登録されたら〇〇したい、みたいな処理はこの中に書けば OK。
署名検証で少しハマったメモ
line-bot-sdk-php/Route.php at master · line/line-bot-sdk-php
を参考に実装してたら少しハマったのでメモ(ハマった原因は僕です)
最初、サンプルを参考にこんなコードを書いていました。
$signature = $request->header(HTTPHeader::LINE_SIGNATURE);
if (empty($signature)) {
return abort(400, 'Bad Request');
}
$events = $bot->parseEventRequest($request->getContent(), $signature[0]);
すると、Invalid signature has given
と怒られます。
[2022-06-04 02:33:11] local.ERROR: Invalid signature has given {"exception":"[object] (LINE\\LINEBot\\Exception\\InvalidSignatureException(code: 0): Invalid signature has given at /Users/mitsu/ghq/github.com/mitsuoka0423/laravel-line-members-card/backend/vendor/linecorp/line-bot-sdk/src/LINEBot/Event/Parser/EventRequestParser.php:71)
原因は、$signature[0]
の[0]
で、Laravel では不要でした。
公式のサンプルが利用しているSlim Framework - Slim Frameworkでは必要なようです。
$signature = $request->header(HTTPHeader::LINE_SIGNATURE);
if (empty($signature)) {
return abort(400, 'Bad Request');
}
$events = $bot->parseEventRequest($request->getContent(), $signature);
で無事動きました。
Discussion