任務狀態回檔通知
概述
當外撥任務的狀態發生變更時,AICC 系統會透過 Webhook 機制向業務系統發送實時通知。此機制允許業務系統及時接收任務狀態更新,實現閉環的流程管理。
回調通知機制
基本特性
- 實時性:任務狀態變更時立即發送通知
- 可靠性:支援自動重試機制,最多重試 10 次
- 超時控制:單次請求超時時間為 200ms
- 安全性:支援簽名驗證機制
回調觸發場景
以下任務狀態變更會觸發回調通知:
| 狀態變更 | 說明 | 觸發事件 |
|---|---|---|
| 草稿 → 進行中 | 任務發佈 | taskPublished |
| 進行中 → 暫停 | 任務暫停 | taskPaused |
| 暫停 → 進行中 | 任務繼續 | taskResumed |
| 進行中 → 停止 | 任務停止 | taskStopped |
| 進行中 → 完成 | 任務完成 | taskCompleted |
| 任何 → 失敗 | 任務失敗 | taskFailed |
回調請求格式
HTTP 請求方式
http
POST {webhookUrl}
Content-Type: application/json
X-AICC-Signature: {signature}
X-AICC-Timestamp: {timestamp}請求 Headers
| Header 名稱 | 值 | 說明 |
|---|---|---|
Content-Type | application/json | 固定值 |
X-AICC-Signature | string | 簽名值,用於驗證請求來源 |
X-AICC-Timestamp | string | 時間戳,格式為 Unix 時間戳 (秒) |
簽名驗證
簽名計算方式:
signature = SHA256(payload + secretKey + timestamp)其中:
payload是 JSON 請求體的完整內容secretKey是 Webhook 配置時的密鑰timestamp是請求時間戳
回調請求體
json
{
"event": "taskStatusChanged",
"taskId": "1",
"taskName": "Q1銀行卡推廣",
"oldStatus": 1,
"newStatus": 3,
"statusName": "停止",
"reason": "達到預期目標",
"updateTime": "2026-03-23 16:00:00",
"statistics": {
"totalContacts": 1000,
"callCount": 320,
"successCount": 85,
"failCount": 15,
"noAnswerCount": 220,
"dialRate": 0.32,
"successRate": 0.265625
}
}回調請求體字段說明
| 字段名 | 型別 | 說明 |
|---|---|---|
event | string | 事件類型,固定為 taskStatusChanged |
taskId | string | 任務 ID |
taskName | string | 任務名稱 |
oldStatus | integer | 舊狀態碼 (0-6) |
newStatus | integer | 新狀態碼 (0-6) |
statusName | string | 新狀態的中文名稱 |
reason | string | 狀態變更原因 (可選) |
updateTime | string | 更新時間 (ISO 8601 格式) |
statistics | object | 任務統計信息 |
回調應答格式
業務系統接收到 Webhook 通知後,應返回以下格式的應答:
成功應答
json
{
"code": 0,
"message": "success",
"data": null
}應答說明
- HTTP 狀態碼:200-299 表示成功
code字段:0 表示成功,非 0 表示失敗- 重要:必須在 200ms 內返回應答,否則視為超時
重試機制
重試策略
當業務系統未能及時應答或返回錯誤時,AICC 系統會自動進行重試:
| 重試次數 | 延遲時間 | 說明 |
|---|---|---|
| 1 | 立即 | 首次發送 |
| 2 | 5 秒 | 第 1 次重試 |
| 3 | 10 秒 | 第 2 次重試 |
| 4 | 30 秒 | 第 3 次重試 |
| 5 | 1 分鐘 | 第 4 次重試 |
| 6 | 2 分鐘 | 第 5 次重試 |
| 7 | 5 分鐘 | 第 6 次重試 |
| 8 | 10 分鐘 | 第 7 次重試 |
| 9 | 30 分鐘 | 第 8 次重試 |
| 10 | 1 小時 | 第 9 次重試 |
重試停止條件
- 接收到成功應答 (HTTP 200-299 且 code=0)
- 達到最大重試次數 10 次
配置 Webhook 端點
配置方式
在 AICC 管理後台配置回調通知 URL:
後台路徑: 系統設定 > 通知設定 > Webhook 配置配置參數
| 參數名 | 必填 | 說明 |
|---|---|---|
webhookUrl | 是 | 業務系統的回調端點 URL (必須是 HTTPS) |
secretKey | 是 | 用於簽名驗證的密鑰 |
enabled | 否 | 是否啟用此 Webhook (預設為啟用) |
eventTypes | 否 | 監聽的事件類型 (不指定則監聽所有) |
配置範例
json
{
"webhookUrl": "https://api.example.com/aicc/callback",
"secretKey": "your_secret_key_12345",
"enabled": true,
"eventTypes": [
"taskPublished",
"taskCompleted",
"taskFailed"
]
}業務系統實現示例
Python 實現
python
from flask import Flask, request
import hashlib
import json
from datetime import datetime
app = Flask(__name__)
SECRET_KEY = "your_secret_key_12345"
def verify_signature(payload, signature, timestamp):
"""驗證請求簽名"""
message = payload + SECRET_KEY + timestamp
expected_sig = hashlib.sha256(message.encode()).hexdigest()
return signature == expected_sig
@app.route('/aicc/callback', methods=['POST'])
def handle_callback():
"""處理 AICC 回調通知"""
try:
# 取得簽名和時間戳
signature = request.headers.get('X-AICC-Signature')
timestamp = request.headers.get('X-AICC-Timestamp')
# 取得請求體
payload = request.get_data(as_text=True)
# 驗證簽名
if not verify_signature(payload, signature, timestamp):
return json.dumps({
"code": 401,
"message": "Invalid signature"
}), 401
# 解析請求體
data = json.loads(payload)
# 處理任務狀態變更
task_id = data.get('taskId')
new_status = data.get('newStatus')
print(f"Task {task_id} status changed to {new_status}")
# 返回成功應答
return json.dumps({
"code": 0,
"message": "success",
"data": None
}), 200
except Exception as e:
print(f"Error handling callback: {str(e)}")
return json.dumps({
"code": 500,
"message": "Internal error"
}), 500
if __name__ == '__main__':
app.run(port=5000)Node.js 實現
javascript
const express = require('express');
const crypto = require('crypto');
const app = express();
app.use(express.json({
verify: (req, res, buf) => {
req.rawBody = buf;
}
}));
const SECRET_KEY = 'your_secret_key_12345';
function verifySignature(payload, signature, timestamp) {
const message = payload + SECRET_KEY + timestamp;
const expectedSig = crypto
.createHash('sha256')
.update(message)
.digest('hex');
return signature === expectedSig;
}
app.post('/aicc/callback', (req, res) => {
try {
const signature = req.get('X-AICC-Signature');
const timestamp = req.get('X-AICC-Timestamp');
const payload = req.rawBody.toString();
// 驗證簽名
if (!verifySignature(payload, signature, timestamp)) {
return res.status(401).json({
code: 401,
message: 'Invalid signature'
});
}
const data = JSON.parse(payload);
// 處理任務狀態變更
console.log(`Task ${data.taskId} status: ${data.newStatus}`);
res.status(200).json({
code: 0,
message: 'success',
data: null
});
} catch (error) {
console.error('Error:', error);
res.status(500).json({
code: 500,
message: 'Internal error'
});
}
});
app.listen(3000, () => {
console.log('Webhook server listening on port 3000');
});常見問題
Q1: 超時了還會重試嗎?
是的,如果在 200ms 內未收到應答或收到錯誤狀態碼,系統會進行重試。
Q2: 如何保證消息順序?
每個任務的消息是按時間順序發送的,但不同任務的消息順序無保證。業務系統應根據 updateTime 字段判斷消息順序。
Q3: 可以修改 Webhook URL 嗎?
可以,修改後新的通知將發送到新 URL,舊 URL 將不再接收通知。
Q4: 是否支援多個 Webhook?
支援,可配置多個 Webhook 端點,系統會依次發送通知。
注意事項
- HTTPS 必須:Webhook URL 必須使用 HTTPS 協議
- 200ms 超時:必須在 200ms 內返回應答,超時視為失敗
- 簽名驗證:必須驗證請求簽名,防止非法請求
- 冪等性:業務系統應實現冪等性,防止重複處理同一消息
- 異步處理:不要在回調中進行耗時操作,應使用異步隊列處理