← 所有文章
教學

透過 UnifyPort 新增與移除訊息表情回應

透過 UnifyPort 新增訊息表情回應時,呼叫 POST /v1/messages/reaction,提交選定的帳號、對話、訊息、原訊息傳送者及 emoji。要移除連線帳號已有的回應,保留相同目標並傳送 emoji: ""。關鍵是:sender_id 指原訊息的作者,不是操作人員,也不是任意一位你想更改其回應的使用者。

重點

  • 目前傳送操作支援 whatsapp 與 telegram;接收回應事件是另一項能力。
  • 從選定的原訊息取得目標,不要使用回應事件本身的訊息 ID。
  • 回應他人訊息時,明確傳入 sender_id;省略時預設為連線帳號本身。
  • 新增與移除應是明確意圖,不是錯誤後反覆重試的切換開關。

將請求欄位對應到原訊息

訊息回應 API 文件定義的是對既有訊息的操作,不是傳送一則表情文字,也不使用引用回覆 token。

請求欄位從已儲存的 message.received 事件取值
account_id頂層 account_id
conversation_iddata.conversation.id
message_iddata.message.id
sender_iddata.sender.id,即原訊息作者
emoji選定表情;移除時為空字串

在群組中,對話識別群組,傳送者識別成員。不要因為私訊中的值看起來相似,就以傳送者取代對話目標。保留平台回傳的完整識別碼,不要根據聯絡人名稱或電話號碼自行組合。

若入口是 message.reaction 事件,data.message.id 代表回應本身,data.message.target_message_id 才指向原訊息。此事件的傳送者是作出回應的人,不一定是原訊息作者。請先找到已儲存的原訊息,再建立操作。回應 webhook 處理教學處理接收與狀態投影;本文處理主動發出請求。

建立明確的新增或移除請求

以下 JavaScript 是請求建構範例,不是已執行的整合測試或完整接收器。輸入應是已驗證簽章、持久儲存,且由獲授權人員選定的原訊息事件。函式名稱與錯誤文字屬於本機應用程式碼。

function buildReactionRequest(original, emoji) {
  if (original.type !== 'message.received' ||
      !['whatsapp', 'telegram'].includes(original.provider)) {
    throw new Error('Select a supported original message');
  }

  const conversation = original.data?.conversation;
  const message = original.data?.message;
  const sender = original.data?.sender;
  if (!original.account_id || !conversation?.id ||
      !message?.id || !sender?.id) {
    throw new Error('Original message context is incomplete');
  }
  if (typeof emoji !== 'string') {
    throw new Error('Choose an emoji or an empty string');
  }

  return {
    account_id: original.account_id,
    conversation_id: conversation.id,
    message_id: message.id,
    sender_id: sender.id,
    emoji
  };
}

傳入 "👍" 請求新增回應,傳入 "" 請求移除。此函式只檢查上下文與資料型別,不保證上游接受所有表情。不要使用 null、省略欄位或自行新增的 remove 旗標取代空字串。

由後端使用 X-Api-Key,將產生的 JSON 傳至 POST /v1/messages/reaction。金鑰不可放入瀏覽器程式碼。送出前確認人員對訊息帳號與訊息的存取權限,並固定選取目標,避免新訊息到來後改變操作對象。

若要以一句話引用原訊息,應改用獨立的 WhatsApp 引用回覆流程。其不透明 reply_token 不是表情回應識別碼。

依操作能力啟用按鈕,不要依事件能力推定

目前的平台操作矩陣與 webhook 事件矩陣描述不同能力:

平台透過此 API 傳送回應回應事件映射
whatsapp支援支援
telegram支援支援
line不支援支援
twitter、zalo、tiktok、whatsapp-protocol不支援不支援

這些是文件中的介接映射,不保證每個帳號或上游條件下都可使用。LINE 收件匣能顯示傳入回應,不代表可啟用傳送回應按鈕。不支援的組合會回傳 501 unsupported_by_provider,重複呼叫不會增加能力。

UnifyPort 提供連線帳號的非官方介面。Telegram 官方 Bot API另有供機器人使用的 setMessageReaction。需要機器人身分時,請採用對應原生規格;不要將它的請求結構貼到此端點,也不要直接套用其限制來定義 UnifyPort 的行為。

分開儲存意圖、請求結果與觀察狀態

此端點的成功範例為 200 OK,包含 data.ok: true。儲存實際 HTTP 結果與回傳的 request_id,不要將它解讀為其他人已看見回應。

建議應用程式:

  1. 對同一帳號、同一目標訊息依序執行操作,避免舊新增工作在較新的移除之後執行。
  2. 送出前記錄期望表情,另外儲存 HTTP 結果。
  3. 收到 react_message_failed 時檢查錯誤與原目標;逾時則保留結果不確定,不要自動發出相反操作補償。
  4. 收到相符回應事件時,以冪等方式更新觀察狀態;不要假定每次請求必有回呼或回呼必定依序抵達。

接收端設定 signing_secret,並遵循投遞文件:以時間戳、句點和原始本文驗證 HMAC-SHA256,檢查時間是否過舊,持久儲存後才確認投遞。收到 webhook 不等於獲准自動發起另一個操作。

驗收檢查與常見問題

啟用前測試:收到的私訊、其他群組成員的訊息、帳號自行傳送的訊息、空字串移除、不支援的平台與不確定的網路結果。確認新訊息不會改變選取目標。這是建議測試清單,不是已完成的測試結果。

sender_id 能指定由誰作出回應嗎?

不能。它指定被回應訊息的作者。執行操作的是連線帳號,不能用此欄位冒用其他回應者的身分。

再傳一次相同表情就會移除嗎?

文件規定以 emoji: "" 移除,不應假設有切換語義。

為什麼能接收 LINE 回應,卻不能傳送?

入站事件解析與出站操作有不同的支援矩陣。目前出站回應操作只映射到 Telegram 和 WhatsApp。

下一步與參考資料

先對照訊息回應 API實作目標檢查,再加入收件匣控制項。證據不足時維持未確定狀態,不要虛構回應查詢 API 或保證重播的能力。

核對日期:2026-10-16。

UnifyPort API

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

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