← 所有文章
教學

WhatsApp 引用回覆:reply_token 與父訊息 ID 的差別

透過 UnifyPort 引用回覆 WhatsApp 訊息時,請將所選訊息的 data.message.reply_token 原樣放入獨立傳送請求的 reply_to.reply_token。不要使用 data.message.reply_to_message_id 取代:它指向收到的引用回覆所關聯的父訊息,而非剛收到的這則訊息。若沒有 token,不要根據 ID 自行產生,也不要悄悄改成一般訊息傳送。

重點

  • 目前訊息 ID、父訊息 ID 與不透明的回覆 token 是不同的值。
  • 傳送帳號與目標對話應取自所選訊息,而非聊天室中的最新訊息。
  • 目前文件中的引用傳送操作僅支援 WhatsApp。
  • 歷史訊息沒有回覆 token;是否改傳一般訊息,必須明確決定。

回覆到底引用哪則訊息?

以下是假設情境:訊息 A 提問,訊息 B 引用 A 並補充更正,客服希望回覆時引用 B。

A ← B ← 你的新回覆

標準 webhook 文件區分以下欄位:

B 中的欄位意義應用用途
data.message.idB 的識別碼儲存並在收件匣選取 B
data.message.reply_to_message_idA 的識別碼顯示 B 的父訊息關係
data.message.reply_token用於引用 B 的不透明控制代碼原樣傳入傳送請求
data.conversation.id 與 type原始對話填入傳送目標
account_id已連結的訊息帳號保留正確的傳送帳號

若在介面選取 A,就需要 A 自己儲存下來的 token。B 的父訊息 ID 無法取代它。若本機資料庫沒有父訊息,只顯示引用內容無法取得,不要猜測其文字。

這與「能否在 HTTP webhook 回應中傳送訊息」是不同的問題。Webhook 回應與獨立傳送請求比較說明傳輸方式;本文處理的是傳出的引用指向哪則訊息。

從所選事件建立請求

先驗證傳入事件,再持久化儲存。設定 signing_secret,依照 webhook 投遞規範對時間戳記、一個點號與原始請求本文計算 HMAC-SHA256,驗證後才能信任酬載。時間戳記有效範圍與去重仍是獨立檢查,詳見 HMAC 重放防護教學。

以下 JavaScript 是請求建構函式,不是完整接收器或自動傳送迴圈。輸入應為已驗證、已儲存,並由有權限的客服選取的即時事件。函式名稱與錯誤文字屬於應用程式,不是 API 欄位或服務錯誤碼。

function buildQuotedReply(event, text) {
  const conversation = event.data?.conversation;
  const message = event.data?.message;

  if (event.type !== 'message.received' ||
      event.provider !== 'whatsapp' ||
      message?.direction !== 'inbound') {
    throw new Error('Select an inbound WhatsApp message');
  }
  if (!event.account_id || !conversation?.id || !conversation.type) {
    throw new Error('Missing destination context');
  }
  if (typeof message.reply_token !== 'string' || !message.reply_token) {
    throw new Error('Quoted reply unavailable');
  }
  if (typeof text !== 'string' || !text.trim()) {
    throw new Error('Reply text is required');
  }

  return {
    account_id: event.account_id,
    to: { id: conversation.id, type: conversation.type },
    message: { type: 'text', text },
    reply_to: { reply_token: message.reply_token }
  };
}

依照引用回覆 API 文件,使用 POST /v1/messages 傳送產生的本文,以 X-Api-Key 驗證身分,金鑰僅存放於後端。群組中的 conversation 代表群組;改用 data.sender.id 會改變傳送目的地,而不是選取引用。

實際傳送前,確認操作人員有權存取該訊息帳號與對話。將所選訊息識別碼保存在本機傳送工作中,避免新訊息抵達後改變引用目標。限制已儲存 token 的存取權限,不要放入一般日誌或 AI 提示詞。

token 缺漏、無效,還是平台不支援?

狀況文件規定的界線建議處理
即時訊息沒有 tokenWhatsApp 在設定回覆 token 簽章時提供它核對事件來源與設定,明確提供一般訊息選項
訊息來自 conversation.history歷史訊息沒有 reply_token不自行產生 token,也不承諾從歷史資料還原
400 invalid_reply_tokentoken 被修改、以不同金鑰加密,或無法讀取檢查儲存值及序列化流程,保留錯誤以供調查
501 unsupported_by_provider所選平台未實作引用傳送停用此引用傳送流程,不要持續重試
省略 reply_to會傳送一般訊息必須明確選擇此替代行為

Webhook 的 signing_secret 用來驗證投遞,不應假設更換它就能修復無法讀取的加密回覆控制代碼。錯誤參考定義錯誤意義,但未承諾 token 修復方法或有效期限。

驗收案例與能力限制

測試 B 引用 A 時,選取 B 仍會引用 B。也要測試撰寫草稿時收到新訊息、群組、token 缺漏、只有歷史訊息,以及重複投遞。重複接收不應建立另一個傳送工作。這些是建議測試,不是已執行的結果。

記錄實際傳送結果。data.status: accepted 不是已讀回條,網路逾時也不代表訊息沒有傳出。不要盲目重傳,或在錯誤後自動移除 reply_to。

UnifyPort 提供非官方介面。統一事件格式不代表每個平台都支援引用傳送。例如 Telegram 官方 Bot API 文件定義自己的 reply_parameters 與 ReplyParameters,不能直接套入這裡的請求。需要原生功能時,應使用對應的原生 API。UnifyPort 沒有 REST 訊息歷史讀取 API,也不保證重放遺漏的酬載。

常見問題

可以將 reply_to_message_id 放入 reply_to.reply_token 嗎?

不行。前者指向傳入訊息的父訊息;後者必須是所選訊息原樣保存的不透明 token。

有歷史訊息 ID 就能引用它嗎?

沒有對應 token,就不能使用這項文件記載的 token 操作。歷史酬載不提供 token。一般訊息只能作為明確選擇的替代方案。

UnifyPort 的 Telegram、LINE、Zalo 也支援嗎?

目前引用傳送文件限定為 WhatsApp。不能因為傳入訊息有引用關係,就推論平台支援引用傳送。

下一步與參考資料

先依照引用回覆文件實作訊息選取檢查,再啟用收件匣的「引用」按鈕。

核對日期:2026-09-26。

UnifyPort API

讓訊息接入變成一條穩定的產品管線。

先用統一 API 跑通傳送,再用標準事件把所有入站訊息接回業務系統。