客服系統點樣接入 WhatsApp 語音通話:由建立連結到接通回調
要喺客服系統接入 UnifyPort WhatsApp 語音通話,後端先用 media_type: "voice" 準備通話,再將私人瀏覽器連結交畀負責嘅客服。客服開啟連結並撳 Start call 之後先會撥號。後端將回傳嘅 call_id 同客服任務關聯,再透過通話事件跟進結果。
本文涵蓋內測中由人工發起嘅一對一撥出通話。UnifyPort 用非官方介面;呢篇唔係 Meta WhatsApp Business Calling API 接入教學。功能概覽同申請方法可以睇通話內測公告。
1. 準備訊息帳戶,再揀對話
先向技術支援申請工作區通話資格。建立 API Key 唔會自動開通;is_beta 係唯讀資格標記,唔可以靠修改工作區 metadata 自己開啟。
顯示通話操作之前,確認 WhatsApp 訊息帳戶已授權,而且 runtime_status 係 running。喺同一帳戶揀私人對話,保留介面回傳嘅 conversation_id,唔好換成電話號碼,亦唔好自己拼砌平台識別碼。
應用程式要將揀好嘅工作區、帳戶、對話同客服任務綁定到今次操作,再由後端檢查操作人權限。有新訊息或者客服轉咗另一個對話,都唔應該暗中改變已準備好嘅通話對象。
以下流程會將 API Key 留喺伺服器,瀏覽器只會收到今次需要嘅私人通話連結。
2. 喺後端準備語音通話
將預留值換成工作區 API Key、已連接帳戶同揀好嘅對話,再喺伺服器執行:
curl -X POST 'https://api.unifyport.ai/v1/calls' \
-H 'X-Api-Key: <YOUR_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{
"account_id": "acc_example",
"to": { "id": "<conversation_id>", "type": "user" },
"media_type": "voice"
}'
建立通話文件列明成功會回傳 201 Created,回應結構如下。以下數值只係示例,唔係真實通話回執:
{
"request_id": "req_example",
"data": {
"call_id": "call_example",
"direction": "outbound",
"media_type": "voice",
"state": "preparing",
"join_url": "https://calls.example.com/call/call_example#ticket=example-only",
"expires_at": "2026-10-27T08:02:00Z"
}
}
將 data.call_id 同揀好嘅帳戶、對話及任務一齊儲存,保留 request_id 方便排查。將 data.join_url 當作機密,原樣交畀今次負責嘅客服;完整連結唔可以進入日誌、分析追蹤或者公開訊息。
201 同 preparing 只代表連結準備好,唔代表客戶手機已經響,亦唔代表客戶已經接聽。
3. 由客服喺瀏覽器開始通話
喺業務介面顯示揀好嘅客戶同「可以開始通話」提示,只向今次操作人提供 join_url。客服喺通話頁允許咪高峰存取,並喺 expires_at 之前撳 Start call。
準備期預設由建立起計兩分鐘,但伺服器可以調整,所以要讀取 expires_at,唔好寫死截止時間。準備期限唔會限制已接通嘅通話長度。咪高峰權限係必需,鏡頭權限則可選。
等候建立回應期間,要停用重複提交。如果回應遺失,先顯示結果待確認並查詢目前通話,再考慮要唔要重新建立。單靠停用按鈕協調唔到多位客服,後端亦要處理帳戶層面嘅通話衝突。
4. 用 Webhook 關聯客服任務
如果 Webhook 端點用明確事件清單,保留仍然需要嘅其他訂閱,再加入下面兩個名稱。呢段只係欄位片段,唔係完整嘅端點建立請求:
{
"subscribed_events": ["call.answered", "call.ended"]
}
內測工作區用 *、空清單或者省略清單時,都會包括有權接收嘅通話事件。非內測工作區唔會因為用萬用訂閱而取得通話事件權限。
| 觀察到嘅結果 | 應用程式點處理 |
|---|---|
建立回應嘅 data.call_id | 同揀好嘅客服任務建立關聯 |
call.answered 嘅 data.call.id | 記錄今次通話已接通 |
call.ended 嘅 data.call.id、data.reason、data.duration_seconds | 記錄結束原因同接通時長 |
處理簽章事件之前,先為端點設定 signing_secret,並將簽章密鑰留喺伺服器。
按照 Webhook 投遞契約,用原始請求內容驗證簽章,並按事件信封嘅 id 去重。用事件嘅 account_id 同 data.call.id 配對已儲存嘅關聯。處理延遲或者重複事件時,唔好令已結束通話喺畫面上重新變成進行中。
另外保留「已接通」證據:duration_seconds 會向下取整,所以單憑 0 唔能夠證明未接通。建立階段同步失敗可能冇結束事件,HTTP 錯誤要獨立記錄。完整內容見接通事件同結束事件文件。通話結束亦唔代表客服任務自動解決。
5. 查詢或者結束受管理通話
要恢復狀態,或者遺失咗通話識別碼時,可以用查詢目前通話介面:
curl --get 'https://api.unifyport.ai/v1/calls/active' \
-H 'X-Api-Key: <YOUR_API_KEY>' \
--data-urlencode 'account_id=acc_example'
data: {} 代表呢個帳戶目前冇 UnifyPort 管理嘅通話。佢唔係通話歷史,唔能夠證明上次嘗試嘅結果,亦偵測唔到 WhatsApp 原生應用程式入面嘅通話。回應唔會重新簽發一次性 join_url。
操作人決定結束一通已知通話時,用儲存嘅 call_id 同所屬帳戶:
curl -X POST 'https://api.unifyport.ai/v1/calls/call_example/hangup' \
-H 'X-Api-Key: <YOUR_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{"account_id":"acc_example"}'
掛線介面會回傳 ended 或 failed 終態;重複掛線可能會回傳已有終態。唔好只因為狀態係 failed 就繼續掛線,亦唔好為咗消除建立衝突而結束其他客服嘅通話。
常見接入問題
| 情況 | 下一步 |
|---|---|
403 beta_feature_not_enabled | 聯絡支援核對工作區資格,修改 metadata 開通唔到 |
| 準備連結過期 | 停止重用;檢查目前通話後,由客服明確決定要唔要重新準備 |
| 瀏覽器用唔到咪高峰 | 先檢查通話頁嘅咪高峰權限,再確認撥號係咪正常 |
| 建立請求同已有通話衝突 | 查詢受管理通話,喺業務系統確認負責客服同用途 |
| 建立或者掛線請求逾時 | 保持結果待確認,綜合目前狀態同已收到事件後,再決定要唔要重試 |
驗收一條完整客服流程
喺已獲同意嘅測試對話中,檢查正常接通同掛線、準備連結過期、拒絕咪高峰權限、重複點擊、帳戶衝突及 HTTP 回應遺失。確認重複投遞唔會產生重複任務記錄,完整通話連結亦唔會進入日誌。呢啲係接入時應該執行嘅驗收項目,唔係本文聲稱做過嘅實測結果。
可以自動打一批電話號碼嗎?
唔可以。呢個流程需要帳戶下嘅 conversation_id,而且要由人工喺瀏覽器撳 Start call。
同一套接入可以接聽來電嗎?
目前內測唔可以。call.incoming 係預留契約,出現喺事件目錄唔代表已經開放來電。群組通話、錄音、轉寫、SIP/PBX 整合同 AI 語音客服,亦唔屬於今次內測範圍。
團隊應該由邊度開始?
未有資格嘅話,可以提供工作區 ID 同預計使用嘅客服場景,聯絡技術支援申請,唔好傳 API Key 或私人通話連結。開通後,先按照建立通話文件驗證一個明確揀好嘅對話,再將操作入口接入客服流程。
令訊息接入變成一條穩定嘅產品管線。
先用統一嘅 API 跑通發送,再用標準事件將所有入站訊息接返去業務系統。