← 所有文章
教學

用 account.profile.updated 同步 WhatsApp 帳號自己的名稱

要在應用程式中同步已連結 WhatsApp 帳號自己的名稱,請處理 UnifyPort 的 account.profile.updated 事件,讀取 data.profile.display_name。此名稱優先採用商家名稱,再回退至推播名稱。應更新的是帳號資料顯示,而非客戶聯絡人、內部帳號標籤或連線狀態。文件描述的觸發來源是 WhatsApp 名稱事件,並非所有管道通用的個人資料變更通知。

重點整理

  • 以工作空間、provider 和 account_id 識別帳號,不要用顯示名稱當索引鍵。
  • 帳號設定的 name 與管道公開名稱分開保存。
  • full_sync 說明資料來源,不代表訊息歷史已還原完成。
  • 帳號資料通知不能證明授權有效或連線正在運作。

先確認畫面要顯示哪個名稱

客服系統的帳號選單可以同時顯示團隊內部標籤及管道公開名稱。更名不應無聲無息地改變負責人、路由或權限。

值或事件意義建議呈現位置
帳號設定 name透過帳號設定維護的標籤內部帳號選單
data.profile.display_name依管道資料產生的公開名稱獨立的管道名稱欄
data.profile.business_name / push_name事件文件列出的名稱組成選用的資料詳細頁
contact.updated聯絡人通訊錄名稱客戶聯絡人檢視
account.status.updated授權或執行環境狀態連線健康檢視

聯絡人名稱同步教學處理客戶一側的資料,不能直接拿來更新自身帳號。客戶訊息的寄件者名稱,也不是這個帳號更名的證據。

取得帳號文件會分別傳回帳號設定與 provider_profile,可供畫面初始讀取。公開名稱缺失時應顯示尚無資料,不要將內部標籤假裝成觀測到的公開名稱。

讀懂 account.profile.updated 的範圍

以下使用事件參考的範例結構。識別碼與名稱都是文件範例,不是真實客戶紀錄:

{
  "id": "evt_profile_7e91d2c4",
  "type": "account.profile.updated",
  "provider": "whatsapp",
  "account_id": "acc_8c21d0",
  "occurred_at": "2026-08-28T09:51:51Z",
  "data": {
    "account": { "provider_account_ref": "provider_account_example" },
    "profile": {
      "display_name": "Example Business",
      "business_name": "Example Business",
      "push_name": "Example Account"
    },
    "event": {
      "kind": "account_profile_updated",
      "source": "self_rename"
    }
  }
}

採用事件提供的 display_name,不要另寫一套衝突的優先規則。有商家名稱優先時,即使 push_name 改變,畫面上的名稱也可能維持不變。

data.event.source 的文件值分別是:

  • self_rename:已連結帳號修改了自己的名稱。
  • full_sync:資料來自完整同步快照。

這兩個值都沒有指出是哪位人員修改,不能據此產生虛構的操作人稽核紀錄。full_sync 也不表示所有訊息、聯絡人、頭像或其他帳號資料都已同步。

建立獨立的帳號資料檢視

建議流程如下:

  1. 先訂閱,再依賴更新。 將 account.profile.updated 加入所需事件集合,保留其他訂閱和簽章設定。事件篩選指南說明明確列表與萬用字元的選擇。
  2. 驗證簽章並持久化。 依投遞契約,使用 signing_secret 驗證 X-Device-Timestamp、句點及原始請求本文的十六進位 HMAC-SHA256,並檢查時間戳是否過舊。可靠儲存已驗證事件後再回應 2xx。
  3. 找到現有帳號。 使用接收端的工作空間脈絡,以及信封中的 provider、account_id。新名稱不應建立第二個帳號或把對話移至另一帳號。
  4. 只更新資料顯示。 保留內部標籤、客戶名稱、授權與執行環境狀態。將名稱作為文字呈現,而不是 HTML。
  5. 本地記錄來源。 在檢視資料旁保存事件 ID、發生時間及來源;這是應用程式設計,不是新增 API 欄位。

以下 JavaScript 只從已驗證事件中擷取名稱候選值,不包含儲存、排序或完整接收服務:

function profileNameCandidate(event) {
  if (event.type !== 'account.profile.updated' ||
      event.provider !== 'whatsapp') return null;
  if (typeof event.account_id !== 'string' || !event.account_id) {
    throw new Error('Missing account identity');
  }
  const name = event.data?.profile?.display_name;
  if (typeof name !== 'string') {
    throw new Error('Profile display name needs review');
  }
  return { accountId: event.account_id, displayName: name };
}

回傳物件的鍵是應用程式變數。名稱缺失或格式錯誤時,保留事件供檢查,不要以預設值取代整份資料。空字串應有明確的本地「名稱暫不可用」顯示策略;不要直接套用聯絡人事件的清除規則。

處理舊事件與初始讀取

一般事件重試以事件 ID 去重。投遞順序沒有保證:套用資料事件時依 occurred_at 排序,同時間以事件 ID 決定順序,並將去重紀錄與檢視更新一併提交。

此處沒有文件保證 REST 讀取和 Webhook 共用資料版本號。若初始讀取尚未完成時已套用新事件,不要讓遲到的讀取結果覆寫它。可以序列化初始化與事件處理,或將讀取視為基準,再套用暫存事件。觀測互相矛盾時標記為待核對,而非宣稱已重建上游的完整因果順序。

UnifyPort 是非官方介面。這不是修改原生資料的指令,也不是完整資料封存或保證重播。即使整合 LINE、Zalo、Telegram 或 whatsapp-protocol,相同信封結構也不代表那些管道會送出此事件。

常見問題

為何 push_name 變了,display_name 卻沒變?

文件規則優先採用 BusinessName,再回退至 PushName。請先檢查提供的名稱組成,不要直接認定更新失敗。

full_sync 表示訊息歷史已完整同步嗎?

不是。它只標示此資料事件的來源,與訊息歷史完整性或還原結果無關。

收到事件後應以 PATCH 修改帳號 name 嗎?

不應自動這樣做。那會修改帳號設定,而不是僅顯示觀測到的管道名稱。內部標籤編輯應保持獨立且明確。

下一步與參考資料

依帳號資料事件參考建立帳號卡片。建議測試兩種來源、不同商家與推播名稱、重複及舊事件、缺失或空名稱,以及遲到的初始讀取;確認聯絡人、內部標籤與連線狀態未變。這些是待執行的檢查,不是已完成的測試結果。

資料核對日期:2026-11-05。

UnifyPort API

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

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