LINE 聊天機器人: Hello world!

前面講了這麼多,終於要進入重點了。現在來寫一個會回應的 LINE 聊天機器人吧!

無論你是透過 Laravel 安裝工具 的 laravel new 或是 composer create-project 的方式 都可以,反正就是新安裝一份 Laravel 專案吧!

在你安裝完 Laravel 後,首先需要做的事情就是設定一個隨機字串到應用程式金鑰。如果這金鑰沒有被設定的話,你的使用者 sessions 和其他的加密資料都會不安全,因此我們需要來設定一下應用程式金鑰。

假設你是透過 Composer 安裝 Laravel,這個金鑰有可能已經透過 key:generate 指令幫你設定完成,如果沒有的話,試著輸入 php artisan key:generate 產生應用程式金鑰吧

首先,我們來設定 `route` 的部分,讓 LINE 可以打入我們設定好的 webhook ,打開 routes/web.php

插入一行

Route::post('/callback', '[email protected]');

此時我們只要去 LINE Developer 後台的 webhooks 網址添加 /callback (如下圖),每當使用者跟機器人講話的時候,就會觸發 LineController 裡面的 webhook 這個方法

img

剛剛我們有提到 LineController 裡面的 webhook 方法,所以我們來建立一個,輸入 php artisan make:controller LineController ,此時 app/Http/Controllers/ 裡面會多了一新的 controller,我們在裡面增加一點東西,讓他可以接受 LINE 的訊息,然後回應

接著我們需要安裝 LINE 提供的 SDK ,所以下個指令 composer require linecorp/line-bot-sdk ,來安裝 line-bot-sdk ,安裝完成後就可以開始寫 code 囉!

我們先建立一個 app\Http\Controller\LineController

<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use LINE\LINEBot;
use LINE\LINEBot\Event\MessageEvent;
use LINE\LINEBot\HTTPClient\CurlHTTPClient;

class LineController extends Controller
{
    private $client;
    private $bot;
    private $channel_access_token;
    private $channel_secret;

    public function __construct()
    {
        $this->channel_access_token = env('CHANNEL_ACCESS_TOKEN');
        $this->channel_secret = env('CHANNEL_SECRET');

        $httpClient = new CurlHTTPClient($this->channel_access_token);
        $this->bot = new LINEBot($httpClient, ['channelSecret' => $this->channel_secret]);
        $this->client = $httpClient;
    }

    public function webhook(Request $request)
    {
        $bot = $this->bot;
        $signature = $request->header(\LINE\LINEBot\Constant\HTTPHeader::LINE_SIGNATURE);
        $body = $request->getContent();

        try
        {
            $events = $bot->parseEventRequest($body, $signature);
        }
        catch(\Exception $e)
        {
            Log::error($e->getMessage());
        }

        foreach ($events as $event)
        {
            $replyToken = $event->getReplyToken();
            if ($event instanceof MessageEvent)
            {
                $message_type = $event->getMessageType();
                $text = $event->getText();
                switch ($message_type)
                {
                    case 'text':
                        $bot->replyText($replyToken, 'Hello world!');
                    break;
                }
            }
        }
    }
}

 

先來講講 __construct 。這個其實很簡單,就是拿著你的 .env 裡面的 Channel secret 和 Channel access token 去建立一個 LINEBot 物件。

緊接著是 函式 webhook 中

$bot = $this->bot;
$signature = $request->header(\LINE\LINEBot\Constant\HTTPHeader::LINE_SIGNATURE);
$body = $request->getContent();

try {
    $events = $bot->parseEventRequest($body, $signature);
} catch (\Exception $e) {
    Log::error($e->getMessage());
}

 

我們先取除剛剛建構的 LINEBot 物件,然後去接收 $request ,接著 透過 try... catch 去看看這個 $request 能不能夠正確被處理,如果可以的話,就可以開始做事情啦!

接著是最後一段,也是最核心的部分

foreach ($events as $event) {
    $replyToken = $event->getReplyToken();
    if ($event instanceof MessageEvent) {
        $message_type = $event->getMessageType();
        $text = $event->getText();
        switch ($message_type) {
            case 'text':
            $bot->replyText($replyToken, 'Hello world!');
            break;
        }
    }
}

 

如果能夠正常處理請求,過來的東西會是一個陣列,裡頭有許許多多的 event ,而這個 event 裡頭有許多資訊供我們使用,首先我透過 $event->getReplyToken() 去取得 ReplyToken ,等等回覆給使用者的時候要用這個 token ,這組 token 存活時間非常短暫,所以我們接收到使用者的訊息,必須馬上把它用掉

接著我用 if ($event instanceof MessageEvent) 去確認事件類型是 MessageEvent 。至於這是什麼東西呢?先別急,之後我會介紹更多的事件類型,緊接著 if 裡面的第一行,我們先透過 getMessageType 取得訊息類型,還有 getText() 取得文字內容,再透過 switch 的方式判斷 訊息類型 是不是 text

最後,我們透過剛剛建立的 $bot 這個 LINEBot 物件中的 replyMessage 來回覆訊息給使用者吧!這樣核心的程式就完成的差不多了

然後剛剛有提到 env ,所以我們來去 .env 添加兩個環境變數吧!其中一個是 CHANNEL_ACCESS_TOKEN 另一個是 CHANNEL_SECRET ,還記得我在 先有一個 Line Messaging API account 這個章節一直提到的 Channel secret 和 Channel access token 嗎?這時候終於派得上用場囉!把他填上去就對了

CHANNEL_ACCESS_TOKEN={{ YOUR_CHANNEL_ACCESS_TOKEN }}
CHANNEL_SECRET={{ YOUR_CHANNEL_SECRET }}

感覺好像都可以了,試著去和 chatbot 聊天的時候,會發現他還是都不理人!!!

沒錯!因為 Laravel 這邊有個小小的坑,就是 Laravel 很貼心地做了 Csrf Token 驗證,所以 LINE 打過來的資料被視為非法的,所以被拒絕了!因此我們需要讓 LINE 打過來的這個 webhook 是暢通的。

先打開 app/Middleware/VerifyCsrfToken.php ,修改內容

<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
    /**
     * Indicates whether the XSRF-TOKEN cookie should be set on the response.
     *
     * @var bool
     */
    protected $addHttpCookie = true;
    /**
     * The URIs that should be excluded from CSRF verification.
     *
     * @var array
     */
    protected $except = ['/callback'
    // 添加這行
    ];
}

 

這樣就會告訴 Laravel 說 /callback 這個路徑就不需要做驗證囉!這樣再去找聊天機器人聊天,應該就會 Hello world 了喔!

Add a Comment

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *