💬

LaravelでLINE Botのフォローイベントをフックする #laravel #messagingapi #php

2022/06/04に公開

はじめに

https://zenn.dev/tmitsuoka0423/articles/laravel-line-helloworld

の続きです。
前回作成した LINE Bot を改修して、フォローイベント(友達登録時/ブロック解除時に発生するイベント)に応答できるように変更します。

少しハマったので、後半で説明します。

完成イメージ

https://twitter.com/mitsuoka0423/status/1532916722059341824?conversation=none

環境

  • MacBook Air (M1, 2020)
$ sw_vers

ProductName:    macOS
ProductVersion: 12.2.1
BuildVersion:   21D62

参考URL

事前準備

下記記事の手順を実施し、オウム返しが動く状態にしておきます。

https://zenn.dev/tmitsuoka0423/articles/laravel-line-helloworld

コーディング

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);
+        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);

で無事動きました。

GitHubで編集を提案

Discussion