LINE Messaging API 整合教學:自動回覆、推播、Flex Message
太長不看版: LINE Messaging API 讓你的伺服器與 LINE 平台互傳 JSON。整合只有三個必要動作:① 在 LINE Developers 建 Messaging API channel、② 架一個支援 HTTPS 的 webhook endpoint 並驗證 X-Line-Signature、③ 用 reply token 回訊息(免費、有時效)或用 push 主動發(計入訊息用量)。開發本身不難,難的是三個在文件上看不到、上線後才會咬人的坑:webhook 回應後才做的事在 Cloud Run 上會被砍掉、LIFF 的加好友提示只在 LINE App 內有效、以及廣告點擊帶的 fbclid 會在跳轉 OA 時被丟掉導致轉換歸因不回去。這三個下面都有講。
| 發送方式 | 觸發條件 | 費用 | 典型用途 |
|---|---|---|---|
| Reply | 使用者先動作,帶 reply token | 不計入訊息額度 | 自動回覆、關鍵字回應 |
| Push | 你主動發給單一使用者 | 計入月訊息額度 | 訂單通知、個人化提醒 |
| Multicast | 你主動發給多個指定使用者 | 每人各計一則 | 分眾推播 |
| Broadcast | 發給所有好友 | 每人各計一則 | 全體公告 |
Reply token 是有時效的一次性憑證,所以「等資料庫查完再回」這種寫法很容易超時,後面〈webhook 回應之後才做事〉那段會講怎麼避開。
LINE 官方帳號的後台管理功能已經能滿足基本的行銷需求,但如果你想實現更複雜的自動化流程,例如串接訂單系統自動通知、依用戶行為觸發不同回覆、或建立互動式 Chatbot,就需要整合 LINE Messaging API。完整的能力範圍見 LINE 官方 Messaging API 總覽文件↗。
本文將從環境建置開始,帶你完成 Messaging API 的核心功能整合。
前置準備
必要條件
- LINE 官方帳號(認證帳號或一般帳號皆可)
- LINE Developers 帳號
- 伺服器環境(支援 HTTPS 的 Webhook endpoint)
- 基本的程式開發能力(本文以 Node.js 為例)
建立 Messaging API Channel
- 前往 LINE Developers Console↗
- 建立或選擇一個 Provider
- 點擊「Create a Messaging API channel」
- 填寫 Channel 資訊:
- Channel name:你的品牌名稱
- Channel description:簡短描述
- Category / Subcategory:選擇產業類別
- 取得以下憑證:
- Channel ID
- Channel Secret
- Channel Access Token(長期)
[截圖參考:LINE Developers Console 的 Channel 設定頁面,標示 Channel Secret 和 Access Token 的位置]
安全提醒:Channel Secret 和 Access Token 是高度敏感的憑證,請使用環境變數管理,絕不要寫死在程式碼中或 commit 到版本控制。
環境建置(Node.js)
mkdir line-bot && cd line-bot
npm init -y
npm install @line/bot-sdk express dotenv
建立 .env 檔案:
LINE_CHANNEL_SECRET=your_channel_secret_here
LINE_CHANNEL_ACCESS_TOKEN=your_channel_access_token_here
PORT=3000
基本伺服器架構
// server.js
require('dotenv').config();
const express = require('express');
const line = require('@line/bot-sdk');
const config = {
channelSecret: process.env.LINE_CHANNEL_SECRET,
channelAccessToken: process.env.LINE_CHANNEL_ACCESS_TOKEN,
};
const client = new line.messagingApi.MessagingApiClient(config);
const app = express();
// Webhook endpoint
app.post('/webhook', line.middleware(config), (req, res) => {
Promise.all(req.body.events.map(handleEvent))
.then((result) => res.json(result))
.catch((err) => {
console.error(err);
res.status(500).end();
});
});
// Event handler
async function handleEvent(event) {
if (event.type !== 'message' || event.message.type !== 'text') {
return null;
}
return client.replyMessage({
replyToken: event.replyToken,
messages: [{
type: 'text',
text: `你說的是:${event.message.text}`
}]
});
}
const port = process.env.PORT || 3000;
app.listen(port, () => {
console.log(`LINE Bot server running on port ${port}`);
});
設定 Webhook URL
- 在 LINE Developers Console 的 Messaging API 設定中
- 填入你的 Webhook URL:
https://your-domain.com/webhook - 開啟「Use webhook」
- 點擊「Verify」確認連線成功
核心功能一:自動回覆(Reply Message)
Reply Message 是最基本的互動方式:用戶發送訊息 -> Webhook 收到事件 -> 回覆訊息。
文字回覆
async function handleEvent(event) {
if (event.type !== 'message' || event.message.type !== 'text') {
return null;
}
const userMessage = event.message.text;
let replyText = '';
// 關鍵字匹配
switch (true) {
case /營業時間/.test(userMessage):
replyText = '我們的營業時間:\n週一至週五 10:00-20:00\n週六 10:00-18:00\n週日公休';
break;
case /價[格目]/.test(userMessage):
replyText = '請參考我們的價目表:https://example.com/pricing';
break;
case /客服|聯繫/.test(userMessage):
replyText = '請撥打客服專線:02-1234-5678\n或來信:support@example.com';
break;
default:
replyText = '感謝您的訊息!我們的客服人員會盡快回覆您。';
}
return client.replyMessage({
replyToken: event.replyToken,
messages: [{ type: 'text', text: replyText }]
});
}
圖片回覆
return client.replyMessage({
replyToken: event.replyToken,
messages: [{
type: 'image',
originalContentUrl: 'https://example.com/images/product.jpg',
previewImageUrl: 'https://example.com/images/product-preview.jpg'
}]
});
多訊息回覆
一次 Reply 最多可發送 5 則訊息:
return client.replyMessage({
replyToken: event.replyToken,
messages: [
{ type: 'text', text: '以下是我們的熱門商品:' },
{
type: 'image',
originalContentUrl: 'https://example.com/product1.jpg',
previewImageUrl: 'https://example.com/product1-thumb.jpg'
},
{ type: 'text', text: '立即下單享 85 折:https://example.com/order' }
]
});
注意:Reply Message 必須在收到 Webhook 事件後的短時間內使用 replyToken 回覆。replyToken 的有效期很短(約 1 分鐘),過期後無法使用。
核心功能二:主動推播(Push Message)
Push Message 可以在任何時間主動發送訊息給用戶,不需要 replyToken。
單一用戶推播
// 發送訊息給特定用戶
await client.pushMessage({
to: 'USER_ID', // 用戶的 LINE User ID
messages: [{
type: 'text',
text: '您的訂單 #12345 已出貨!預計明天到達。'
}]
});
多人推播(Multicast)
一次最多可發送給 500 個用戶:
await client.multicast({
to: ['USER_ID_1', 'USER_ID_2', 'USER_ID_3'],
messages: [{
type: 'text',
text: '限時優惠:全館 85 折,今天 23:59 截止!'
}]
});
全員推播(Broadcast)
發送給所有好友(計入訊息費用):
await client.broadcast({
messages: [{
type: 'text',
text: '新品上市通知:春季限定系列已上架!'
}]
});
窄播(Narrowcast)
結合受眾條件的精準推播:
await client.narrowcast({
messages: [{
type: 'text',
text: '會員專屬:生日月份消費享雙倍點數!'
}],
recipient: {
type: 'audience',
audienceGroupId: 1234567890 // 預先建立的受眾群組 ID
}
});
費用注意:Push Message 和 Broadcast 都會計入月訊息費用。務必搭配分眾策略,避免訊息費暴增。
核心功能三:Flex Message
Flex Message 是 LINE 最強大的訊息格式,允許你用 JSON 定義複雜的版面配置,實現類似「卡片」或「小型網頁」的效果。
基本結構
const flexMessage = {
type: 'flex',
altText: '商品推薦',
contents: {
type: 'bubble',
hero: {
type: 'image',
url: 'https://example.com/product.jpg',
size: 'full',
aspectRatio: '20:13',
aspectMode: 'cover'
},
body: {
type: 'box',
layout: 'vertical',
contents: [
{
type: 'text',
text: '春季限定保濕乳液',
weight: 'bold',
size: 'xl'
},
{
type: 'text',
text: 'NT$680',
size: 'lg',
color: '#DC2626',
margin: 'md'
},
{
type: 'text',
text: '添加天然植物精華,深層保濕不黏膩。限量 500 組。',
size: 'sm',
color: '#666666',
margin: 'md',
wrap: true
}
]
},
footer: {
type: 'box',
layout: 'vertical',
contents: [
{
type: 'button',
style: 'primary',
color: '#DC2626',
action: {
type: 'uri',
label: '立即購買',
uri: 'https://example.com/buy/product-1'
}
}
]
}
}
};
Carousel 多張卡片
const carouselMessage = {
type: 'flex',
altText: '熱門商品推薦',
contents: {
type: 'carousel',
contents: [
// Bubble 1
{
type: 'bubble',
hero: { /* 商品圖片 */ },
body: { /* 商品資訊 */ },
footer: { /* CTA 按鈕 */ }
},
// Bubble 2
{
type: 'bubble',
hero: { /* 商品圖片 */ },
body: { /* 商品資訊 */ },
footer: { /* CTA 按鈕 */ }
},
// 最多 12 張卡片
]
}
};
訂單通知 Flex Message
const orderNotification = {
type: 'flex',
altText: '訂單確認通知',
contents: {
type: 'bubble',
body: {
type: 'box',
layout: 'vertical',
contents: [
{
type: 'text',
text: '訂單確認',
weight: 'bold',
size: 'xl',
color: '#1DB446'
},
{ type: 'separator', margin: 'lg' },
{
type: 'box',
layout: 'vertical',
margin: 'lg',
contents: [
{
type: 'box',
layout: 'horizontal',
contents: [
{ type: 'text', text: '訂單編號', size: 'sm', color: '#555555', flex: 0 },
{ type: 'text', text: '#20260314001', size: 'sm', color: '#111111', align: 'end' }
]
},
{
type: 'box',
layout: 'horizontal',
margin: 'md',
contents: [
{ type: 'text', text: '訂單金額', size: 'sm', color: '#555555', flex: 0 },
{ type: 'text', text: 'NT$1,280', size: 'sm', color: '#DC2626', align: 'end', weight: 'bold' }
]
},
{
type: 'box',
layout: 'horizontal',
margin: 'md',
contents: [
{ type: 'text', text: '配送方式', size: 'sm', color: '#555555', flex: 0 },
{ type: 'text', text: '7-11 超商取貨', size: 'sm', color: '#111111', align: 'end' }
]
}
]
}
]
}
}
};
Flex Message Simulator
LINE 提供 Flex Message Simulator↗ 線上工具,可以用拖拉的方式設計 Flex Message 並產生 JSON 程式碼。強烈建議使用這個工具來設計複雜版面。
[截圖參考:LINE Flex Message Simulator 介面,左側為設計區域,右側為 JSON 預覽]
核心功能四:Rich Menu API 控制
透過 API 可以實現比後台更靈活的 Rich Menu 管理:
建立 Rich Menu
const richMenu = {
size: { width: 2500, height: 1686 },
selected: true,
name: '主選單',
chatBarText: '選單',
areas: [
{
bounds: { x: 0, y: 0, width: 833, height: 843 },
action: { type: 'uri', uri: 'https://example.com/products' }
},
{
bounds: { x: 833, y: 0, width: 834, height: 843 },
action: { type: 'uri', uri: 'https://example.com/events' }
},
{
bounds: { x: 1667, y: 0, width: 833, height: 843 },
action: { type: 'message', text: '我要客服' }
},
// ... 更多區域
]
};
const richMenuId = await client.createRichMenu(richMenu);
為特定用戶設定 Rich Menu
// 為 VIP 會員顯示 VIP 專屬選單
await client.linkRichMenuIdToUser('USER_ID', 'VIP_RICH_MENU_ID');
// 解除用戶的個人 Rich Menu(恢復為預設)
await client.unlinkRichMenuIdFromUser('USER_ID');
Rich Menu 切換策略
// 用戶加好友時:顯示「新客歡迎版」Rich Menu
async function handleFollow(event) {
await client.linkRichMenuIdToUser(
event.source.userId,
'NEW_FRIEND_RICH_MENU_ID'
);
// 發送歡迎訊息
await client.replyMessage({
replyToken: event.replyToken,
messages: [{ type: 'text', text: '歡迎加入!看看我們為你準備了什麼。' }]
});
}
// 用戶完成首購後:切換為「會員版」Rich Menu
async function handleFirstPurchase(userId) {
await client.linkRichMenuIdToUser(userId, 'MEMBER_RICH_MENU_ID');
await client.pushMessage({
to: userId,
messages: [{ type: 'text', text: '恭喜成為會員!你的專屬選單已更新。' }]
});
}
進階整合:Webhook 事件處理
完整事件處理架構
async function handleEvent(event) {
switch (event.type) {
case 'message':
return handleMessage(event);
case 'follow':
return handleFollow(event); // 用戶加好友
case 'unfollow':
return handleUnfollow(event); // 用戶封鎖
case 'postback':
return handlePostback(event); // Postback 動作
case 'memberJoined':
return handleMemberJoined(event); // 加入群組
default:
return null;
}
}
// 追蹤好友事件
async function handleFollow(event) {
const userId = event.source.userId;
// 取得用戶 Profile
const profile = await client.getProfile(userId);
// 儲存到資料庫
await saveUserToDatabase({
lineUserId: userId,
displayName: profile.displayName,
pictureUrl: profile.pictureUrl,
followedAt: new Date()
});
// 發送歡迎訊息 + 設定 Rich Menu
// ...
}
// 封鎖事件
async function handleUnfollow(event) {
const userId = event.source.userId;
await updateUserStatus(userId, 'blocked');
// 記錄封鎖原因分析用
}
// Postback 事件(來自 Flex Message 按鈕或 Rich Menu)
async function handlePostback(event) {
const data = new URLSearchParams(event.postback.data);
const action = data.get('action');
switch (action) {
case 'check_order':
const orderId = data.get('orderId');
const order = await getOrderFromDatabase(orderId);
// 回覆訂單狀態
break;
case 'book_appointment':
const date = event.postback.params?.date;
// 處理預約
break;
}
}
上線後才會咬人的三個坑(我們自己踩過的)
這三個在官方文件裡都查得到根據,但都不會出現在「快速上手」教學裡,而且症狀都是本機測試完全正常、上線後靜默失敗。
一、webhook 回應之後才做事,在 Cloud Run 上會被砍掉
很自然的寫法是先 res.send(200) 讓 LINE 不要重試,再去慢慢處理業務邏輯。這在傳統常駐伺服器上沒問題,在 Cloud Run 上會間歇性掉資料。
原因是 Cloud Run 預設用「請求計費」模式,官方文件寫明 CPU 只在處理請求期間配置↗,回應送出後 CPU 就收回,閒置的執行個體隨時可能被關掉。你在 res.send() 之後 await 的東西,可能跑完,也可能跑到一半就沒了,取決於那台執行個體活多久。症狀最惡劣的地方在於它是機率性的:流量大、執行個體一直活著的時候完全正常,半夜沒流量時第一則訊息就掉。
三個修法,依情境選:把耗時工作丟進 Cloud Tasks(官方建議,且自帶重試)、改成執行個體計費、或乾脆在回應前把事情做完並確保總時間在 LINE 的 webhook 逾時內。
二、LIFF 的加好友提示只在 LINE App 內會出現
liff.init() 的 botPrompt 參數可以在使用者開啟 LIFF 時提示加官方帳號好友。但 LIFF 官方文件說明↗ LIFF 有兩種執行環境:LINE App 內的 LIFF 瀏覽器,以及外部瀏覽器。部分功能只在 LIFF 瀏覽器內有效,加好友提示就是其中之一。
實務上這代表:你在桌機瀏覽器測試 LIFF 頁面,提示不會出現,很容易被誤判成「參數設錯」而去改一輪程式碼。要驗證這個功能,必須用手機從 LINE 內開。(另一個常見成因是 LINE Login channel 沒有正確關聯到 Messaging API channel,這個從後台設定就能確認。)
三、廣告導 LINE OA 時,fbclid 會在跳轉中被丟掉
如果你的漏斗是「廣告 → 落地頁 → 加 LINE 好友」,中間那一跳會把網址參數吃掉,結果是廣告後台顯示 0 轉換、LINE 後台卻不斷有新好友進來。這不是追蹤沒裝,是參數在跳轉時斷了。
處理方式是不要直接用 OA 的深層連結,改成先進一個自己控制的 LIFF 頁面,在那裡把 fbclid 接住並與使用者的 LINE user ID 綁定,再送轉換事件。這樣廣告端才歸得回去。相關的量測方式見行銷漏斗怎麼量。
安全性注意事項
Webhook 簽章驗證
LINE Bot SDK 會自動驗證 Webhook 請求的簽章,確保請求來自 LINE 伺服器。如果你使用自訂中介層,務必驗證 X-Line-Signature header:
const crypto = require('crypto');
function validateSignature(body, signature, channelSecret) {
const hash = crypto
.createHmac('SHA256', channelSecret)
.update(body)
.digest('base64');
return hash === signature;
}
速率限制
- Reply Message:無限制(只要有有效的 replyToken)
- Push Message:依方案不同有不同的速率限制
- API 呼叫:每分鐘最多 2,000 次
用戶資料保護
- 不要在日誌中記錄用戶的完整 User ID
- 用戶 Profile 資料僅用於服務目的
- 遵守 LINE Platform 的使用條款和隱私政策
常見問題與除錯
Q1:Webhook 收不到事件?
- 確認 Webhook URL 是 HTTPS
- 確認「Use webhook」已開啟
- 確認伺服器回傳 HTTP 200
- 檢查 LINE Developers Console 的 Webhook 測試結果
Q2:Reply 訊息沒有送出?
- replyToken 可能已過期(超過 1 分鐘)
- 一個 replyToken 只能使用一次
- 確認 Channel Access Token 正確
Q3:Push Message 發送失敗?
- 確認 User ID 格式正確(U 開頭的 33 字元字串)
- 確認用戶沒有封鎖帳號
- 檢查月訊息餘額是否用完
結語
LINE Messaging API 提供了強大的自動化能力,從基本的關鍵字回覆到複雜的 Chatbot 流程,都能透過 API 實現。關鍵是從簡單的功能開始,逐步增加複雜度,並持續監控用戶互動數據來優化體驗。
如果你需要專業的 LINE Bot 開發或 Messaging API 整合服務,歡迎聯繫 RedClaw 團隊。我們擁有豐富的 LINE 技術整合經驗,能幫助你建立高效的自動化行銷系統。
資料來源
官方文件,查證於 2026 年 8 月 25 日:
- LINE Messaging API 總覽↗ — 官方說明 bot 伺服器與 LINE 平台之間以 HTTPS JSON 互傳資料,並列出支援的訊息類型(文字、貼圖、圖片、影片、音訊、位置、圖文訊息、範本、Flex Message)、rich menu、帳號連結與訊息額度查詢。
- LINE Messaging API 參考文件↗ — webhook 的簽章驗證(signature validation)、請求標頭與請求主體格式以這份為準。
- LIFF 總覽↗ — LIFF 執行環境差異(LINE 內建瀏覽器 vs 外部瀏覽器)與可取得的使用者資料。
- line-bot-sdk-nodejs(官方 SDK)↗ — LINE 官方維護的 Node.js SDK,目前要求 Node.js 22 以上。
- Cloud Run CPU 配置說明↗ — 預設請求計費模式下 CPU 只在處理請求期間配置,這是上面第一個坑的官方依據。
延伸閱讀:LINE 廣告投放完全指南、GA4 事件追蹤教學。
本文由 RedClaw 團隊撰寫。更多 LINE 技術整合與自動化行銷內容,請持續關注我們的部落格。
相關文章
灰色產業廣告投放策略:合規框架下的受限產業行銷指南
灰色產業廣告投放完整策略:各平台政策解析、帳號結構策略、素材審核技巧、SEO 替代獲客、LINE OA 與 Telegram 角色、風險控管機制,合規框架下的受限產業行銷指南。
LINE 廣告投放完全指南:LAP 設定教學、費用行情與 5 種高效廣告格式 [2026]
完整解析 LINE Ads Platform (LAP) 廣告投放:帳號開設流程、5 種廣告格式比較、費用行情與出價策略、LINE OA 加好友廣告設定教學,以及 LINE LAP vs Meta vs Google 的跨平台比較。附台灣市場 2026 年投放數據。
LINE OA 行銷自動化完全指南:從好友經營到轉換漏斗的自動化策略 [2026]
深入解析 LINE OA 行銷自動化:帳號類型差異、自動化漏斗建置(好友加入→歡迎訊息→標籤分群→自動推播→轉換)、Webhook 與 LIFF 應用、Messaging API 整合、推薦碼追蹤,以及 iGaming 產業的 VIP 分層與出入金通知實戰案例。