用 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 也不表示所有訊息、聯絡人、頭像或其他帳號資料都已同步。
建立獨立的帳號資料檢視
建議流程如下:
- 先訂閱,再依賴更新。 將
account.profile.updated加入所需事件集合,保留其他訂閱和簽章設定。事件篩選指南說明明確列表與萬用字元的選擇。 - 驗證簽章並持久化。 依投遞契約,使用
signing_secret驗證X-Device-Timestamp、句點及原始請求本文的十六進位 HMAC-SHA256,並檢查時間戳是否過舊。可靠儲存已驗證事件後再回應 2xx。 - 找到現有帳號。 使用接收端的工作空間脈絡,以及信封中的 provider、
account_id。新名稱不應建立第二個帳號或把對話移至另一帳號。 - 只更新資料顯示。 保留內部標籤、客戶名稱、授權與執行環境狀態。將名稱作為文字呈現,而不是 HTML。
- 本地記錄來源。 在檢視資料旁保存事件 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。
讓訊息接入變成一條穩定的產品管線。
先用統一 API 跑通傳送,再用標準事件把所有入站訊息接回業務系統。