← 所有文章
教學

透過 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 跑通發送,再用標準事件將所有入站訊息接返去業務系統。