Skip to content

任務狀態回檔通知

概述

當外撥任務的狀態發生變更時,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-Typeapplication/json固定值
X-AICC-Signaturestring簽名值,用於驗證請求來源
X-AICC-Timestampstring時間戳,格式為 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
  }
}

回調請求體字段說明

字段名型別說明
eventstring事件類型,固定為 taskStatusChanged
taskIdstring任務 ID
taskNamestring任務名稱
oldStatusinteger舊狀態碼 (0-6)
newStatusinteger新狀態碼 (0-6)
statusNamestring新狀態的中文名稱
reasonstring狀態變更原因 (可選)
updateTimestring更新時間 (ISO 8601 格式)
statisticsobject任務統計信息

回調應答格式

業務系統接收到 Webhook 通知後,應返回以下格式的應答:

成功應答

json
{
  "code": 0,
  "message": "success",
  "data": null
}

應答說明

  • HTTP 狀態碼:200-299 表示成功
  • code 字段:0 表示成功,非 0 表示失敗
  • 重要:必須在 200ms 內返回應答,否則視為超時

重試機制

重試策略

當業務系統未能及時應答或返回錯誤時,AICC 系統會自動進行重試:

重試次數延遲時間說明
1立即首次發送
25 秒第 1 次重試
310 秒第 2 次重試
430 秒第 3 次重試
51 分鐘第 4 次重試
62 分鐘第 5 次重試
75 分鐘第 6 次重試
810 分鐘第 7 次重試
930 分鐘第 8 次重試
101 小時第 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 端點,系統會依次發送通知。

注意事項

  1. HTTPS 必須:Webhook URL 必須使用 HTTPS 協議
  2. 200ms 超時:必須在 200ms 內返回應答,超時視為失敗
  3. 簽名驗證:必須驗證請求簽名,防止非法請求
  4. 冪等性:業務系統應實現冪等性,防止重複處理同一消息
  5. 異步處理:不要在回調中進行耗時操作,應使用異步隊列處理

承暉資訊資源中心