裕普智汇

Webhook 回调配置

实时事件通知,让您的系统与裕普智汇无缝集成

Webhook 概述

Webhook 允许裕普智汇在特定事件发生时主动通知您的服务器,无需频繁轮询 API。当任务完成、状态变更等事件发生时,系统会自动向您配置的 URL 发送 POST 请求。

支持的事件类型

task.completed- 任务执行完成

携带数据:任务ID、状态、结果摘要

task.failed- 任务执行失败

携带数据:任务ID、错误码、错误信息

report.generated- 报告生成完成

携带数据:报告ID、下载链接

device.offline- 设备离线

携带数据:设备ID、离线时间

alert.triggered- 告警触发

携带数据:告警ID、告警类型、严重程度

scan.completed- 安全巡检完成

携带数据:巡检ID、风险等级、问题数量

配置步骤

1

创建 Webhook

在控制台"开发者中心"-"Webhook"页面,点击"创建 Webhook",填写回调地址和事件类型。

2

配置签名密钥

系统会生成一个签名密钥,用于验证请求的真实性。请妥善保存。

3

实现回调接口

在您的服务器上实现接收 POST 请求的接口,验证签名并处理事件数据。

4

测试验证

使用"测试事件"功能发送测试请求,验证您的接口是否正常工作。

签名验证

为确保安全性,每个请求都包含 X-Yupu-Signature 头,用于验证请求确实来自裕普智汇。

签名算法:HMAC-SHA256
签名格式:timestamp + "." + payload 的 HMAC-SHA256 签名

验证步骤:
1. 从 Header 中提取 X-Yupu-Timestamp 和 X-Yupu-Signature
2. 计算当前时间与 timestamp 的差值,确保在 5 分钟内
3. 构造签名内容:timestamp + "." + request_body
4. 使用密钥计算 HMAC-SHA256,与 signature 比对

Python 示例:

import hmac
import hashlib

def verify_signature(payload: bytes, timestamp: str, signature: str, secret: str):
    # 检查时间戳
    import time
    if abs(time.time() - int(timestamp)) > 300:
        return False

    # 计算签名
    content = f"{timestamp}.{payload.decode()}"
    expected = hmac.new(
        secret.encode(),
        content.encode(),
        hashlib.sha256
    ).hexdigest()

    return hmac.compare_digest(expected, signature)

Node.js 示例:

import crypto from 'crypto';

function verifySignature(payload, timestamp, signature, secret) {
    // 检查时间戳
    if (Math.abs(Date.now() / 1000 - parseInt(timestamp)) > 300) {
        return false;
    }

    // 计算签名
    const content = `${timestamp}.${payload}`;
    const expected = crypto
        .createHmac('sha256', secret)
        .update(content)
        .digest('hex');

    return crypto.timingSafeEqual(
        Buffer.from(signature),
        Buffer.from(expected)
    );
}

重试机制

如果您的服务器在收到请求后返回非 2xx 状态码,或在 10 秒内未响应,系统会认为投递失败。失败后会按照以下策略重试:5秒后、30秒后、2分钟后、10分钟后、1小时后。最多重试 5 次,仍失败则标记为投递失败。

完整示例

Python Flask 示例:

from flask import Flask, request, jsonify
import hmac
import hashlib
import time

app = Flask(__name__)
WEBHOOK_SECRET = "your_webhook_secret"

@app.route('/webhook', methods=['POST'])
def handle_webhook():
    # 获取 Header
    timestamp = request.headers.get('X-Yupu-Timestamp')
    signature = request.headers.get('X-Yupu-Signature')
    event_type = request.headers.get('X-Yupu-Event')

    # 验证签名
    if not verify_signature(request.data, timestamp, signature):
        return jsonify({"error": "Invalid signature"}), 401

    payload = request.json

    # 处理事件
    if event_type == 'task.completed':
        print(f"任务完成: {payload['task_id']}")
    elif event_type == 'report.generated':
        print(f"报告生成: {payload['report_id']}")

    return '', 200

def verify_signature(payload, timestamp, signature, secret):
    if abs(time.time() - int(timestamp)) > 300:
        return False
    content = f"{timestamp}.{payload.decode()}"
    expected = hmac.new(secret.encode(), content.encode(), hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature)

常见问题

Webhook 请求超时时间是多少?

服务器需要在 10 秒内返回响应,否则会被视为失败。

可以配置多个 Webhook 吗?

可以,企业账户支持配置多个 Webhook 端点。

签名密钥可以更换吗?

可以,在 Webhook 设置页面可以重新生成签名密钥。

如何查看 Webhook 投递日志?

在控制台"开发者中心"-"Webhook 日志"中可以查看每次投递的详情。