用 message.updated Webhook 處理 LINE 訊息編輯
LINE 在 2026 年 8 月 12 日為 Messaging API 新增編輯事件。使用者在包含 LINE 官方帳號的適用群組聊天室中修改已傳送的文字訊息後,LINE 可以送出 messageEdited Webhook。共用收件匣不應新增第二則訊息,而應更新原訊息;在 UnifyPort 中,對應的標準事件是 message.updated,並以原始 data.message.id 關聯。
重點整理
- LINE 原生事件名稱是
messageEdited,UnifyPort 標準事件名稱是message.updated。 - 以訊息帳號、對話與
data.message.id的組合定位原訊息。 - 編輯是狀態變更,不應再次增加入站訊息數量。
- 先驗證 HMAC-SHA256 簽章,再剖析並寫入資料。
- 能接收 LINE 編輯事件,不代表可以透過 UnifyPort 主動編輯 LINE 訊息。
LINE 群組聊天室有哪些變化
LINE 的官方 Messaging API 新聞頁記錄了 2026 年 8 月 12 日的更新:使用者可在包含 LINE 官方帳號的群組聊天室中編輯訊息,Messaging API 的 Webhook 事件物件也新增 messageEdited。目前的官方 API Reference已將 Edit event 列入 Webhook 事件物件。
這項變更會影響共用收件匣、CRM 時間軸、搜尋索引與 AI 上下文。客戶若更正訂單編號、地址或問題,而系統仍保存舊文字,後續自動化可能繼續處理過期資訊;若把編輯內容插入成新訊息,又會造成重複計數,時間軸也與 LINE 不一致。
正確的資料模型是:同一則平台訊息發生一次狀態更新。
LINE messageEdited 與 UnifyPort message.updated
LINE 官方酬載採用平台專屬結構。UnifyPort 將更新放入統一事件信封,讓同一個處理器能接收不同平台的訊息編輯:
{
"id": "evt_7f42c18a9d",
"type": "message.updated",
"provider": "line",
"account_id": "acc_8c21d0",
"occurred_at": "2026-08-22T09:15:30Z",
"data": {
"conversation": {
"id": "c8f2a4d91e",
"type": "group",
"title": "訂單支援"
},
"sender": {
"id": "u71b9d420f",
"type": "user",
"name": "Jordan Lee"
},
"message": {
"id": "551842037194",
"text": "更正:訂單編號是 A1234。",
"direction": "inbound",
"sent_at": "2026-08-22T09:12:04Z"
},
"event": {
"kind": "message_updated"
}
}
}
兩個 ID 用途不同:
- 頂層
id標識這次 Webhook 事件,可用於排除重複投遞。 data.message.id標識被修改的原訊息。
可在各平台 Webhook 標準事件差異核對目前的能力矩陣。矩陣列出 LINE 對 message.updated 的支援,但實際欄位仍可能受上游帳號與部署狀態影響。
不建立重複訊息的歸併流程
不要假設平台訊息 ID 在全域唯一,建議使用組合鍵:
(account_id, conversation_id, provider_message_id)
接著把編輯當成冪等狀態更新:
- 驗證原始請求內容的簽章。
- 以 Webhook 事件 ID 排除重複投遞。
- 用
account_id、data.conversation.id與data.message.id查找原訊息。 - 以
data.message.text取代目前文字。 - 將
occurred_at保存為觀察到編輯的時間。 - 保留最初接收時間;若有稽核需求,另存內部修訂歷程。
- 資料持久化成功後再回傳 2xx。
以下是精簡的 Express 處理器,資料庫方法保持抽象,讓真實事件欄位更清楚:
import crypto from 'crypto';
import express from 'express';
const app = express();
const secret = process.env.WEBHOOK_SIGNING_SECRET;
app.post('/webhook', express.raw({ type: 'application/json' }), async (req, res) => {
const timestamp = req.get('X-Device-Timestamp') || '';
const signature = req.get('X-Device-Signature') || '';
const expected = crypto.createHmac('sha256', secret)
.update(timestamp + '.')
.update(req.body)
.digest('hex');
const valid = signature.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
if (!valid) return res.sendStatus(401);
const event = JSON.parse(req.body.toString('utf8'));
if (await db.hasWebhookEvent(event.id)) return res.sendStatus(200);
if (event.type === 'message.updated') {
await db.applyMessageEdit({
accountId: event.account_id,
conversationId: event.data.conversation.id,
messageId: event.data.message.id,
text: event.data.message.text,
editedAt: event.occurred_at
});
}
await db.rememberWebhookEvent(event.id);
return res.sendStatus(200);
});
簽章字串、重試條件與事件順序注意事項可查看Webhook 投遞與簽章文件。若要深入處理時間戳記與冪等性,請閱讀Webhook HMAC 重送防護教學。
原訊息缺少或事件順序顛倒時
Webhook 不保證投遞順序。編輯事件可能比原訊息更早完成寫入;接收器離線時,也可能漏掉原訊息。這時不要立即建立一般時間軸項目,也不要增加入站統計。
較穩妥的方式,是先將更新暫存在以組合訊息識別值為鍵的短期資料表。收到原始 message.received 後,先套用待處理文字,再顯示給客服。若原訊息始終沒有到達,應把記錄標示為「不完整的編輯觀察」,交由人員檢查,而不是當成完整訊息呈現。
表情回應也適用相同的狀態思維。可參考如何在統一 Webhook 中處理訊息回應,區分「事件」與「被事件改變的訊息狀態」。
UnifyPort 的適用範圍與限制
小型團隊若同時接收 LINE、WhatsApp、Telegram、TikTok、Zalo 或 X,並希望下游只維護一種已簽章事件格式,UnifyPort 的非官方介面可以減少各平台專用剖析器。處理器只需針對 message.updated 分支。
若系統以 LINE 官方帳號為中心,且需要 LINE 原生能力或原始平台酬載,官方 Messaging API 仍較合適。也要注意目前的動作邊界:UnifyPort 可標準化收到的 LINE 訊息更新,但目前不支援透過 POST /v1/messages/edit 主動編輯 LINE 訊息。接收編輯與發起編輯是兩種不同能力。
常見問題
LINE messageEdited 是什麼?
它是 LINE Messaging API 針對適用訊息編輯提供的官方 Webhook 事件。LINE 於 2026 年 8 月 12 日宣布,此事件可用於包含 LINE 官方帳號的群組聊天室。
UnifyPort 應訂閱哪個事件名稱?
訂閱 message.updated。若端點確實要接收所有公開標準事件,也可使用 "*";正式環境的精確篩選應採完整事件名稱。
編輯後的 LINE 訊息要建立新收件匣項目嗎?
不需要。請用 data.message.id 找到並更新原訊息;若有稽核需求,再單獨保存修訂記錄。
可以透過 UnifyPort 編輯 LINE 訊息嗎?
目前不行。現有平台動作矩陣未列出 LINE 對主動編輯動作的支援。本文只處理接收及歸併編輯事件。
下一步
先核對各平台 Webhook 事件矩陣,把 message.updated 加入訂閱,並在正式共用收件匣啟用前測試冪等更新與事件亂序流程。
官方來源
核對日期:2026 年 8 月 22 日。
讓訊息接入變成一條穩定的產品管線。
先用統一 API 跑通傳送,再用標準事件把所有入站訊息接回業務系統。