X Chat 私訊故障排查:登入狀態、金鑰版本與訊息簽署
X 帳戶登入到,不等於每個加密對話都可以正常使用。帳戶存取權、正確的對話金鑰,以及有效的訊息簽署,是不同條件。排查時,先分清問題出在驗證、準備加密訊息、傳送請求,還是訊息送到業務系統的一段。只見到「傳送失敗」,未足以判斷是簽署錯誤、流量限制或帳戶受限。
先查清楚四件事
- 是單一對話有問題,還是整個帳戶都受影響?傳送、接收,抑或兩邊都失敗?
- 加密訊息要用對應版本的對話金鑰,不能只看快取內有沒有金鑰。
- X Chat 訊息簽署與 UnifyPort Webhook 驗證是兩回事。
- 重試或更改帳戶連線之前,先記錄請求識別碼和時間。
帳戶連線與聊天金鑰,各有不同職責
X 官方加密介紹分開說明身分金鑰、簽署金鑰和帶版本的對話金鑰。排查可以按以下分工進行:
| 材料 | 用途 | 要確認甚麼 |
|---|---|---|
| 帳戶工作階段 | 存取帳戶 | 是否正確的帳戶,工作階段是否仍可用? |
| 身分私密金鑰 | 解開分發給該用戶的對話金鑰 | 有沒有相符的身分金鑰材料? |
| 簽署私密金鑰 | 簽署訊息及支援的狀態變更 | 是否選對簽署金鑰及版本? |
| 對話金鑰 | 加密或解密對話內容 | 有沒有這則訊息所需版本的金鑰? |
不同層要查的資料不同。使用託管連接器的應用開發者,一般先看公開帳戶狀態及錯誤回應,再交由連接器維護者檢查協定層金鑰。API 驗證成功,未足以證明其餘條件都已經滿足。
恢復聊天金鑰所用的 Chat 通行碼,也不同於 API key 或帳戶登入憑證。恢復失敗時,應沿用帳戶持有人原有的 Chat 設定,不要將重設通行碼當成普通重試。X 的 Chat 說明列明了無法取得通行碼時,恢復加密歷史紀錄的限制。
改設定之前,先收窄問題範圍
保留一次失敗請求,跟已知正常的操作比較。例如,用戶資料查詢正常,但一個對話傳送失敗,應先查該對話,不能直接認定整個服務連不上。比較只幫助定位範圍,並非根因證據。
| 症狀 | 要保留的資料 | 下一步 |
|---|---|---|
| 帳戶無法存取 | 驗證回應、帳戶與執行狀態 | 按現行授權文件處理存取問題。 |
| 單一對話傳送失敗 | 請求 ID、對話 ID、準確錯誤類別 | 請維護者查對話狀態、金鑰版本、token 和簽署輸入。 |
| 部分訊息無法解密 | 受影響訊息 ID,以及可取得的金鑰版本 | 確認所需的歷史版本金鑰是否存在。 |
| 不肯定是否已傳送 | 請求時間、回應或逾時、接收方結果 | 核對這次操作後才決定重發;逾時可能代表結果未明。 |
| X 收到訊息,業務系統沒收到 | Webhook 設定、傳送嘗試及接收端回應 | 將事件傳送和 Chat 加密分開排查。 |
直接使用 X Chat SDK 的開發者,可查閱 X 官方故障排查,內容包括金鑰初始化、缺少對話金鑰、解密與簽署失敗。當中的 SDK 方法和錯誤訊息,並不是 UnifyPort 公開 API 的契約。
缺少金鑰後,要有明確的恢復決策
連接器可以採用以下恢復流程:
- 確認對話,以及事件要求的準確金鑰版本。
- 查找該版本的快取。
- 透過整合方案支援的恢復途徑取得封裝金鑰材料。
- 驗證材料,以相應的身分私密金鑰解開,再儲存版本紀錄。
- 重新讀取快取,在有限的重試策略內繼續原有操作。
這是設計方法,不代表每個已連接帳戶都可以恢復所有歷史訊息。如果請求成功但目標金鑰仍不存在,就不算恢復完成。同一金鑰的並行請求可以共用恢復工作,但每則訊息的處理結果仍要分開記錄。舊金鑰可保留來讀取歷史訊息,同時不應蓋過較新的預設金鑰。
接收和傳送的失敗處理也要分開。接收端應在支援的重試期限內保留原始事件,不能把密文當成解密完成的訊息。傳送端要明確決定:恢復失敗時回報錯誤,還是容許現有替代路徑。如果替代路徑改變了加密屬性,就不能當作等效的加密傳送。兩種情況都不應無限重試。
簽署錯誤要有對應證據
只有當上游回應確實指出簽署失敗,維護者才應針對金鑰選擇、傳送者身分、金鑰版本,以及參與簽署的實際位元組作檢查。重複提交相同的無效內容,不會修正輸入;停用簽署驗證亦不能解決根因。
單靠 HTTP 錯誤或籠統的 Provider 錯誤,不能證明簽署失敗。同樣,連接器修正簽署實作,不代表 X 改了推薦演算法,也不能據此認定 X 最近更新了協定。
用 UnifyPort 公開 API 排查
UnifyPort 為已連接的訊息帳戶提供非官方介面。先核對現行 X 授權指南,再檢查 GET /v1/accounts/{account_id}/auth 和 GET /v1/accounts/{account_id}。驗證狀態與 runtime_status 用來判斷連線狀態,並不是逐個對話的加密健康檢查。
對於已有的 POST /v1/messages 操作,可以保留簡短診斷摘要。以下函式接收已取得的 Response,本身不會傳送或重試訊息:
async function recordMessageAttempt(response) {
const body = await response.clone().json().catch(() => null);
console.info({
observed_at: new Date().toISOString(),
http_status: response.status,
request_id: body?.request_id ?? response.headers.get('X-Request-Id'),
code: body?.error?.code,
numeric_code: body?.error?.numeric_code,
});
}
訊息帳戶 ID、相關對話和訊息 ID,應放在限制存取的事故紀錄內。公開 code 和 numeric_code 的定義,以錯誤參考為準。provider_unavailable 這類概括回應並不揭示個別 X 簽署錯誤,也不能自行將內部錯誤逐一對應到公開錯誤碼。
函式刻意不記錄訊息內容、cookies、工作階段 URL、PIN 或金鑰。若連 HTTP 回應都沒有收到,應記錄客戶端錯誤、操作和時間;當時未必有伺服器請求 ID。不要自行產生 ID,再當成伺服器證據。
Webhook 簽署保護另一段連線
| 簽署 | 驗證對象 | 排查位置 |
|---|---|---|
| X Chat 訊息簽署 | 已簽署的 Chat 事件 | X Chat 客戶端或連接器協定實作 |
X-Device-Signature | UnifyPort 傳到接收端的請求 | Webhook 接收端及其 signing_secret |
後者使用 HMAC-SHA256 計算「時間戳記、一個句點、原始請求內容」,詳見 Webhook 傳送文件。修正 HMAC 驗證不會補回 X 對話金鑰;HMAC 驗證成功,也不代表對方收到某則傳出訊息。
可按 Webhook 優先的接入清單檢查接收設定,下游應用則可參考 X 私訊及提及監聽器實作。驗證收到的事件後,先儲存,再做較慢的路由工作。
常見問題
重新登入一定會補回缺少的金鑰嗎?
不一定。更新工作階段不代表指定身分金鑰或對話金鑰版本已經可用。先找出缺少的材料,再決定是否重做帳戶設定。
金鑰恢復成功,是否等於訊息送達?
不是。金鑰可用、提交獲接納、接收方收到訊息,以及 Webhook 服務完成處理,是不同的觀察結果。要確認工作流程真正需要的結果。
可以呼叫 UnifyPort 公開端點恢復 Chat 金鑰嗎?
本文沒有新增這類公開端點。請用文件列出的公開 API,並向支援團隊提供診斷識別碼。內部連接器操作不能直接當成公開 API 路由。
所有 X 私訊都是加密訊息嗎?
不是。X 的 Chat 文件列出了未加密訊息請求的情況。應先確認實際對話與傳送路徑,再說明加密屬性。
下一步
測試需要的訊息類型前,先看現行訊息支援矩陣。如果直接串接 X 官方 Chat API,請使用其 SDK 和恢復文件;它的驗證方式和事件契約與 UnifyPort 不同。
一手資料來源
核對日期:2026 年 9 月 10 日。
令訊息接入變成一條穩定嘅產品管線。
先用統一嘅 API 跑通發送,再用標準事件將所有入站訊息接返去業務系統。