因工作需要,接觸到有趣的Line Bot,以文章記錄一下基礎開發流程
註冊Line API
首先,進入Line開發者介面(https://developers.line.biz/en/),以Line的帳號登入
登入後,即可看到Porvider list,或是透過網址進入(https://developers.line.biz/console/),接著新增一組Porvider
Porvider建立沒什麼難度,只要設定好名稱即可
完成後,進入Porvider,並選擇建立一個Message API的Channel
新增Channel也沒有什麼難度,名稱所屬產業填一填即可
主要需要注意的是,如果選擇Developer方案的話,好友上限最多50人,且未來是無法轉成其他方案的,如果有需要用於正式環境的話,建議直接選擇Free方案,方案限制可以參考這裡 https://at.line.me/tw/plan
Line更新了API方案,原本的Developer trial 方案沒了,2019/4/18後申請的bot 直接升級成”輕用量”方案,每個月上限500則推播,變更內容懶人包一下:
- 過去只能 bot 或 LINE@ 二選一,現在合併了所以 bot 也能到後台一對一聊天或群發,可以在後台切換
- LINE 計價方式由原本的好友&訊息計價,改為訊息計價(好友無上限)
- Multicast 、Push 都會被算到訊息額度(Reply不會),如果過去的 bot 訊息量比較大有機會超標
詳細資訊可以參考這裡 http://at-blog.line.me/tw/archives/LINEOA2.0FAQ.html
完成後,清單上即可看到剛剛新增的Channel
接著點選Channel,進入詳細的設定畫面,有幾個地方要特別設定:
1. Channel access token (long-lived)
這裡開啟token,並設定token的使用時限,設定0為永久。取得token等於取得權限,token是絕對不可以公布給其他人的!
2. 開啟 Use Webhooks
3. 設定 Webhook URL並驗證
這裡輸入一個URL,指的是當Bot收到訊息後,Bot會通知哪隻網頁程式,網域必須是https開頭
一切就緒後即可轉戰PHP的部分
撰寫PHP
我們可以使用官方SDK來開發,或者自己實作訊息處理;因為僅實作簡單的訊息回覆,本文使用自己處理訊息的方式實作
首先我們建立Webhooks觸發的程式,取名為CallBack.php,程式碼如下
<?php //設定Token $ChannelSecret = 'ChannelSecret'; $ChannelAccessToken = 'ChannelAccessToken'; //讀取資訊 $HttpRequestBody = file_get_contents('php://input'); $HeaderSignature = $_SERVER['HTTP_X_LINE_SIGNATURE']; //驗證來源是否是LINE官方伺服器 $Hash = hash_hmac('sha256', $HttpRequestBody, $ChannelSecret, true); $HashSignature = base64_encode($Hash); if($HashSignature != $HeaderSignature) { die('hash error!'); } //輸出 file_put_contents('log.txt', $HttpRequestBody); ?>
其中ChannelSecret、ChannelAccessToken請修改為自己的ChannelSecret與AccessToken,兩項資訊都在剛剛的Channel Setting頁面中
首先我們使用file_get_contents()的方式取得訊息內容,接著使用sha256與base64編碼並驗證是否與header中HTTP_X_LINE_SIGNATURE的內容相符(驗證資料是否來自Line官方伺服器),最後我們將收到的訊息輸出至log.txt
完成後我們掃描QR code加機器人好友
沒意外的話log.txt會存放Line伺服器發送過來的follow事件
{ "events" : [ { "type" : "follow", "replyToken" : "9cfa97373e624b4d85ee89faecee1dfd", "source" : { "userId" : "U97f699d56851a7bf725c1283772106bd", "type" : "user" }, "timestamp" : 1551514544448 } ], "destination" : "U9206f4b863b5497478a9752dac21ce99" }
接著我們傳送訊息給Bot
我們也能在log.txt看到Message事件,且得到使用者的訊息內容
{ "events":[ { "type":"message", "replyToken":"121a260a7d224d14949d9aa9c4f6aa95", "source":{ "userId":"U97f699d56851a7bf725c1283772106bd", "type":"user" }, "timestamp":1551515007430, "message":{ "type":"text", "id":"9443953102066", "text":"你好" } } ], "destination":"U9206f4b863b5497478a9752dac21ce99" }
由官方文件所示,事件訊息都會以JSON格式發送,我們只需要解析其內容即可實作相對應的反應
值得要注意的是發送過來的訊息當中,事件(events)是以陣列的方式傳送,不一定只有一個事件,所以我們必須使用迴圈逐一反應
每個事件都會取得一個replyToken,我們可以利用replyToken回覆訊息給該使用者
現在已經能正確接收訊息了,接下來實作回覆訊息,我們稍微修改一下程式碼
//解析 $DataBody=json_decode($HttpRequestBody, true); //逐一執行事件 foreach($DataBody['events'] as $Event) { //當bot收到任何訊息 if($Event['type'] == 'message') { $Payload = [ 'replyToken' => $Event['replyToken'], 'messages' => [ [ 'type' => 'text', 'text' => '我收到你的訊息了' ] ] ]; // 傳送訊息 $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'https://api.line.me/v2/bot/message/reply'); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($Payload)); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Content-Type: application/json', 'Authorization: Bearer ' . $ChannelAccessToken ]); $Result = curl_exec($ch); curl_close($ch); } }
發送訊息就會收到我們設定的「我收到你的訊息了」內容,由於我們沒有關閉預設罐頭訊息,所以使用者會看到罐頭,可以去Channel Setting頁面中關閉
完整程式碼如下:
<?php //設定Token $ChannelSecret = 'ChannelSecret'; $ChannelAccessToken = 'ChannelAccessToken'; //讀取資訊 $HttpRequestBody = file_get_contents('php://input'); $HeaderSignature = $_SERVER['HTTP_X_LINE_SIGNATURE']; //驗證來源是否是LINE官方伺服器 $Hash = hash_hmac('sha256', $HttpRequestBody, $ChannelSecret, true); $HashSignature = base64_encode($Hash); if($HashSignature != $HeaderSignature) { die('hash error!'); } //解析 $DataBody=json_decode($HttpRequestBody, true); //逐一執行事件 foreach($DataBody['events'] as $Event) { //當bot收到任何訊息 if($Event['type'] == 'message') { $Payload = [ 'replyToken' => $Event['replyToken'], 'messages' => [ [ 'type' => 'text', 'text' => '我收到你的訊息了' ] ] ]; // 傳送訊息 $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'https://api.line.me/v2/bot/message/reply'); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($Payload)); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Content-Type: application/json', 'Authorization: Bearer ' . $ChannelAccessToken ]); $Result = curl_exec($ch); curl_close($ch); } } ?>
本文僅實作簡單的回覆,未來還可以依照訊息內容或關鍵字作不同的反應
Denny
2019/05/29謝謝您的資訊,但我用您的這段 code
使用 postman 工具來模擬 post request 可以取到 log
但在 Line 上發出訊息時,一直沒有寫入 log
有什麼我該注意的地方嗎,謝謝
$ChannelSecret = ‘XXXXX’;
$ChannelAccessToken = ‘XXXXXX’;
$HttpRequestBody = file_get_contents(‘php://input’);
file_put_contents(‘log.txt’, $HttpRequestBody);
wwwang
2019/06/15您好,若希望取得Line bot收到的訊息內容,必須綁定Line API的Webhook,且必須是可以被Line連接的公開對象(固定IP或是網址),您可以先嘗試用postman連接看看Webhook的URL是否可以被外連