Messaging API (LINE Bot) と CakePHP3 を連携する

必要なもの
LINE Developers のアカウント
・SDK(PHP で開発する場合は line-bot-sdk-php
ngrok(任意)

手順
まずは、SDK をインストールします。

$ composer require linecorp/line-bot-sdk

Getting started を読めば、とりあえず使い始めることはできると思います。
ただ、どのようなメソッドが用意されているのかを知るには、地道にコードを読んでいくしかなさそうです(Octotree が便利です)。

今回は Component を用意しました。/src/Controller/Component 下に次のコードを置いてください。ただし、ファイル名の最後に「Component」を付ける必要があること、クラス名とファイル名を揃える必要があることに注意してください。

<?php

namespace App\Controller\Component;

use Cake\Controller\Component;
use LINE\LINEBot;
use LINE\LINEBot\Constant\HTTPHeader;
use LINE\LINEBot\HTTPClient\CurlHTTPClient;

class LineComponent extends Component
{
   protected $_defaultConfig = [];

   protected $channelAccessToken;
   protected $channelSecret;
   protected $bot;
   protected $controller;

   public function initialize(array $config)
   {
       parent::initialize($config);

       $this->channelAccessToken = env("CHANNEL_ACCESS_TOKEN");
       $this->channelSecret = env("CHANNEL_SECRET");

       $this->bot = new LINEBot(new CurlHTTPClient($this->channelAccessToken), [
           'channelSecret' => $this->channelSecret,
       ]);

       $this->controller = $this->_registry->getController();
   }

   public function fetchEvents(): array
   {
       $signature = $this->controller->request->getHeaderLine(HTTPHeader::LINE_SIGNATURE);

       $events = [];

       try {
           $events = $this->bot->parseEventRequest($this->controller->request->getBody(), $signature);
       } catch(\LINE\LINEBot\Exception\InvalidSignatureException $e) {
           $this->log('parseEventRequest failed. InvalidSignatureException => ' . print_r($e, true));
       } catch(\LINE\LINEBot\Exception\UnknownEventTypeException $e) {
           $this->log('parseEventRequest failed. UnknownEventTypeException => ' . print_r($e, true));
       } catch(\LINE\LINEBot\Exception\UnknownMessageTypeException $e) {
           $this->log('parseEventRequest failed. UnknownMessageTypeException => ' . print_r($e, true));
       } catch(\LINE\LINEBot\Exception\InvalidEventRequestException $e) {
           $this->log('parseEventRequest failed. InvalidEventRequestException => ' . print_r($e, true));
       }

       return $events;
   }

   public function getUserProfile($event): array
   {
       $response = $this->bot->getProfile($event->getUserId());

       $userProfile = [];
       if ($response->isSucceeded()) {
           $userProfile = $response->getJSONDecodedBody();
       }

       return $userProfile;
   }

   public function fetchMediaContent(String $messageId): String
   {
       $ch = curl_init("https://api.line.me/v2/bot/message/{$messageId}/content");

       curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
       curl_setopt($ch, CURLOPT_HTTPHEADER, [
           "Content-Type: application/json; charser=UTF-8",
           "Authorization: Bearer {$this->channelAccessToken}"
       ]);
       $result = curl_exec($ch);

       curl_close($ch);
       return $result;
   }
}

initialze メソッドでは、.env からアクセストークンとシークレットを読み込んでいます。

$this->channelAccessToken = env("CHANNEL_ACCESS_TOKEN");
$this->channelSecret = env("CHANNEL_SECRET");

アクセストークンとシークレットを入手するには、こちらの手順に従い、Messaging API のチャネルを作成しておく必要があります。アクセストークンは、[チャネル基本設定] > [アクセストークン(ロングターム)] から、シークレットは、[チャネル基本設定] > [Channel Secret] から確認できます。

先述の Component を Controller から呼び出します。

<?php
 
namespace App\Controller;

use App\Controller\AppController;
use Cake\Event\Event;

class LineMessagesController extends AppController
{
   public function initialize()
   {
       parent::initialize();
       $this->loadComponent('Line');
   }

   public function doPost()
   {
       $this->autoRender = false;
       $this->request->allowMethod('post');
     
       $events = $this->Line->fetchEvents();
     
       foreach ($events as $event) {
           $userProfile = $this->Line->getUserProfile($event);
           $replyToken = $event->getReplyToken();
           
           if ($event->getType() === 'message' && $event->getMessageType() === 'text') {
               $this->Line->bot->replyText(
                   $replyToken,
                   "{$userProfile['displayName']}さんが「{$event->getText()}」と言いました。"
               );
           }
       }
   }
}

ローカルで LINE Bot の動作を確認するために、ngrok を使用します。たとえば、CakePHP を http://192.168.33.10:8000 で動かしている場合は、

$ ngrok http 192.168.33.10:8000

と入力します。すると、次のような表示とともに ngrok が起動します。

ngrok by @inconshreveable

Session Status                online
Account                       hoge (Plan: Free)
Region                        United States (us)
Web Interface                 http://127.0.0.1:4040
Forwarding                    http://XXXXXXXX.ngrok.io -> http://192.168.33.10:8000
Forwarding                    https://XXXXXXXX.ngrok.io -> http://192.168.33.10:8000

Connections                   ttl     opn     rt1     rt5     p50     p90
                              0       0       0.00    0.00    0.00    0.00

Forwarding の項目に表示されている XXXXXXXX.ngrok.io の部分をコピーします。次に Messaging API のチャネルの [チャネル基本設定] > [Webhook URL] > [編集] で、

(https://) XXXXXXXX.ngrok.io/LineMessages/doPost

を LINE Bot からの POST を受け取る URL として入力します。このとき、[チャネル基本設定] > [Webhook送信] が「利用する」になっていること、グループで LINE Bot を動かすのであれば、[チャネル基本設定] > [Botのグループトーク参加] が「利用する」になっていることを確認してください。

最後に、[チャネル基本設定] ページの下部にある QR コードを読み取って、LINE Bot を友だちに登録します。そして LINE Bot とのトークが次のようになれば、完了です。

画像1


この記事が気に入ったらサポートをしてみませんか?