今天要來聊聊 LINE Bot 開發
嗯...今天我們來聊一下 LINE Bot 的開發。這個主題,其實...網路上有很多教學了,真的很多。 大部分都是一步一步帶著你做,從申請帳號啊、到寫第一支「回音」機器人...就是你傳什麼、它回什麼那種。 但我發現,很多教學好像...嗯...少了一點東西。
它們教你「怎麼做」,但比較少提到「為什麼要這樣做」,還有...那些新手一定會卡關的地方。對,就是那些官方文件寫得很簡單,但你一試就錯的神秘小地方。 所以,我今天想用一個比較...嗯,像在自言自語整理思緒的方式,來走過整個流程。不只是步驟,還有我踩過的坑、跟一些...我自己覺得比較重要的觀念。
重點一句話
老實說,做一個 LINE Bot 的技術門檻...真的不高,關鍵反而在於...你怎麼去規劃它的用途,還有...耐心處理那些煩人的設定跟錯誤。真的,耐心很重要。
第一步不是寫 Code,是先想清楚
很多人,包括以前的我,都急著去 LINE Developers Console 註冊帳號。 但...等一下。在點下那個「建立」按鈕之前,我覺得...應該先停下來想幾個問題。
你的機器人,到底要幹嘛?是做客服? 還是...幫忙記錄團購的「+1」? 或是像我之前幫朋友做的,定時推播一些天氣資訊?這個「目的」,會決定你後面所有的技術選擇。是需要資料庫?需不需要很複雜的對話邏輯?要不要串接外部的 AI 服務? 這些都要先有個大概的藍圖。
想清楚目的之後,再來才是去 LINE 的開發者後台。你要先有一個 LINE 帳號,然後登入 LINE Developers Console。 接下來的流程大致是...建立一個「提供者 (Provider)」,然後在提供者底下,建立一個「Messaging API 通道 (Channel)」。 這個通道,就等於是你未來機器人的身份證。你會在這裡拿到兩組最重要的東西:`Channel secret` 和 `Channel access token`。 這兩樣東西...千萬不要外洩,它們就是你程式用來跟 LINE 溝通的鑰匙。
怎麼做:帳號、程式與部署的實作指引
好,身份證拿到了。接下來,你的機器人就需要一個「大腦」跟一個「家」。大腦就是你的程式碼,家...就是運行你程式碼的伺服器。
程式碼的部分:SDK 讓事情簡單很多
你可以直接去呼叫 LINE 的 API,但...說真的,沒必要。LINE 官方有提供各種程式語言的 SDK (Software Development Kit),像是 Python、Node.js、Java 等等。 這些 SDK 已經把很多複雜的細節都包裝好了,你只要...嗯...專心處理訊息邏輯就好。例如用 Python 的話,你大概就是 `pip install line-bot-sdk`,然後搭配一個像 Flask 這樣的輕量級網站框架,就可以開始了。
你的程式最核心的部分,就是一個接收 LINE 平台訊息的端點,這個端點通常叫做「Webhook」。 簡單說,當有使用者傳訊息給你的機器人時,LINE 的伺服器就會把這個訊息,用一個 HTTP POST 的請求,送到你指定的 Webhook URL。 你的程式收到這個請求後,就要去解析裡面的內容,看看是誰傳了什麼訊息,然後決定要回覆什麼。
# 這是一個非常簡化的 <a href="https://www.digitalocean.com/community/tutorials/how-to-make-a-web-application-using-flask-in-python-3" target="_blank" class="blogHightLight_css nobox">Python Flask</a> 範例
from flask import Flask, request, abort
from linebot import (
LineBotApi, WebhookHandler
)
from linebot.exceptions import (
InvalidSignatureError
)
from linebot.models import (
MessageEvent, TextMessage, TextSendMessage,
)
app = Flask(__name__)
# 這邊要換成你自己的 Channel Access Token 和 Channel Secret
line_bot_api = LineBotApi('YOUR_CHANNEL_ACCESS_TOKEN')
handler = WebhookHandler('YOUR_CHANNEL_SECRET')
@app.route("/callback", methods=['POST'])
def callback():
# 取得 X-Line-Signature 標頭的值
signature = request.headers['X-Line-Signature']
# 取得請求的 body 內容
body = request.get_data(as_text=True)
app.logger.info("Request body: " + body)
# 驗證 signature
try:
handler.handle(body, signature)
except InvalidSignatureError:
abort(400)
return 'OK'
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text=event.message.text)) # 把收到的訊息原樣送回
if __name__ == "__main__":
app.run()
你看,用了 SDK 之後,程式碼其實...還蠻直觀的。 最重要的部分就是 `@handler.add` 那邊,你可以在那裡定義收到不同類型的事件(像是文字訊息、貼圖、或有人加入群組)時,你的機器人該做什麼事。
伺服器的選擇:給新手的幾條路
這大概是最多新手卡關的地方...之一。你寫好了程式,在自己電腦上可以跑。但 LINE 的伺服器要怎麼找到你家的電腦?這就需要一個公開的網址。開發測試的時候,很多人會用 `ngrok` 這種工具,它可以暫時給你一個公開網址,對應到你本機的服務。 這在開發階段非常方便,但...它不是長久之計。
當你要正式上線時,就需要找個地方部署。這時候就有點像...嗯...在比較美國跟台灣的租屋市場。美國的選擇可能很多,各種價位都有,但有些規定跟我們不熟。台灣的選擇相對單純,但可能比較貴。LINE Bot 部署也是,選項很多,各有優缺點。
我這邊簡單整理一下幾個常見的選項,給...嗯...比較初學的朋友參考。
| 部署平台 | 優點 | 缺點 | 我自己是覺得... |
|---|---|---|---|
| Heroku | 超級簡單,對新手很友善,有免費方案。 | 免費方案的機器會休眠,一段時間沒人用,第一次啟動會很慢。而且現在免費方案限制越來越多。 | 如果你只是想做個小玩具、或是學習用,Heroku 還是...嗯...最快的起點。但別期待太多。 |
| Google App Script (GAS) | 完全免費,跟 Google Sheet 整合超方便,不用管伺服器。 | 功能限制比較多,執行時間有限制,適合比較...嗯...輕量的應用,像是記錄資料。 | 如果你要做的是「+1」機器人這種,需要把資料寫到試算表的,那 GAS 簡直是...絕配。 超級方便。 |
| Serverless (AWS Lambda, Google Cloud Functions) | 用多少付多少,擴展性超強,很穩定。 | 設定比 Heroku 複雜一點,需要對雲端服務有一點點概念。 | 這是我個人最推薦的長期方案。雖然一開始設定比較麻煩,但...一旦搞定,你幾乎就不用再管它了。穩定又便宜。 |
| 傳統 VPS (像 DigitalOcean, Linode) | 完全的控制權,你想裝什麼就裝什麼。 | 最麻煩。你要自己管理作業系統、安全性更新、設定網路... | 除非你有特殊需求,或是你本來就很熟伺服器維運,不然...嗯...先不要碰這個。 |
反例與誤解釐清:那些一定會遇到的坑
好,接下來講重點。就是那些...你跟著教學做,但怎麼樣都動不起來的鳥事。
Webhook URL 驗證失敗
當你在 LINE Developers Console 填上你的 Webhook URL 後,有個「Verify」按鈕。 你按下去,如果出現紅色錯誤,先不要慌。這通常代表 LINE 的伺服器沒辦法成功跟你剛部署好的程式溝通。可能的原因有:
- 你的網址打錯了。
- 你的伺服器沒有正常運作,或者防火牆擋住了。
- 你的程式沒有正確回傳 `200 OK` 的狀態碼給 LINE 的驗證請求。
這個驗證請求是一個...嗯...沒有任何事件內容的空請求,你的程式要能處理這種情況,並回傳一個成功的狀態碼。 如果不處理,驗證就會失敗。
最痛苦的 `InvalidSignatureError`
這個錯誤,我敢說...九成的新手都遇過。 就是 `InvalidSignatureError`,簽章驗證失敗。當你的 Webhook 收到 LINE 的請求時,請求的標頭 (header) 裡會有一個 `X-Line-Signature`。 你的程式需要用你的 `Channel Secret`,對收到的請求內容 (body) 做一個 HMAC-SHA256 的加密運算,然後比對結果跟 `X-Line-Signature` 是不是一樣。 這個機制是為了確保這個請求真的是從 LINE 平台發出來的,而不是被偽造或竄改的。
聽起來很複雜,但好消息是,官方 SDK 都會自動幫你做這件事。 那...為什麼還是會錯?
最常見的原因是...嗯...很蠢但也很真實:**你在 SDK 處理之前,就先去動了請求的 body**。 很多網站框架會自動幫你解析 JSON 格式的 body。但簽章驗證需要的是「未經處理的原始 body 內容」。 如果框架先幫你轉成了一個物件,那 SDK 拿去算出來的簽章...當然就會不一樣。所以,你必須確保 SDK 是第一個拿到最原始 `request body` 的傢伙。這一點在不同的框架(例如 Python Flask 跟 Node.js Express)有不同的處理方式,一定要去看你用的 SDK 文件怎麼說。
另一個可能的原因,是你複製 `Channel Secret` 的時候...多複製了一個空格,或是用錯了 Channel 的 Secret。聽起來很扯,但...真的會發生。
