Orchestrator
2023.4
False
横幅背景图像
Orchestrator 用户指南
上次更新日期 2024年4月19日

Webhooks

Webhook 用于在整个应用程序生态系统中更出色地集成 UiPath 自动化。您可以订阅 Orchestrator 事件并将其发送到任何外部 DCM、BPM 或 CRM 解决方案,同时通知不同的用户存在可供处理的新队列项目、触发器失败或已更新流程等事项。

Webhook 允许外部系统订阅和侦听不同类型的 Orchestrator 事件Webhooks 页面使您可以轻松地设置它们,以及查看先前创建的内容。您还可以禁用 Webhook,搜索特定的 Webhook,编辑或删除 Webhook。

事件适用于作业、机器人、队列、队列项目、流程和计划。有关事件类型的完整列表和一些示例,请查看此页面

每个事件都会向指定的 URL 发送包含信息的有效负载。一些属性是所有事件的通用属性,而另一些属性则特定于每种事件类型。

Webhook 事件按文件夹创建,因此,如果您有一个 Webhook 事件与在文件夹之间共享的资源(例如队列)相关联,则系统将为每个文件夹生成一个单独的 Webhook 事件。

通用有效负载属性

属性名称

属性类型

说明和示例

类型

字符串

触发通知的事件类型。

对于所有类型的事件,都会显示此属性。

示例:

"Type": "job.created"

"Type":"process.updated"

活动 ID

字符串

发生时为每个事件生成的唯一标识符。

对于所有类型的事件,都会显示此属性。

示例:

"EventId":"3e5af0113e674ae597c579cb35ed8630"

时间戳

RFC 8601 日期

生成事件的日期和时间。

对于所有类型的事件,都会显示此属性。

示例:

"Timestamp":"2018-11-02T11:47:48.5790797Z"

租户 ID

整数

在其中生成事件的租户的 ID。默认租户为 1。

对于所有类型的事件,都会显示此属性。

示例:

"TenantId":3

用户 ID

整数

操作触发事件的用户 ID。

如果事件是由机器人或触发器触发的,则不会显示此参数。

对于所有类型的事件,都会显示此属性。

示例:

"UserId": 4947

文件夹 ID

整数

生成事件的文件夹的 ID。

对于由新式机器人触发的事件,不会显示此参数。

示例:

"FolderId": 26

权限

要在“Webhook”页面上执行各种操作,需要获得对 Webhook 的相应权限:

身份验证

所有 Webhook HTTP 请求都使用您在创建 Webhook 时添加的密码进行身份验证。它通过 HMAC-SHA256 键控哈希与请求正文结合在一起。这将产生一个不包含任何密码信息的安全签名,该签名对于每个请求都是唯一的,并通过 X-UiPath-Signature HTTP 标头发送。

接收 Orchestrator 请求的客户端应用程序必须检查请求的真实性。请求签名遵循以下模式:

  • 客户端应用程序收到 Orchestrator 发出的 Webhook 请求;
  • 客户端应用程序根据请求计算签名;
  • 客户端应用程序尝试将其计算的签名与请求签名进行匹配:

    • 如果签名不匹配,则客户端应用程序不应处理请求。
    • 如果签名匹配,则客户端应用程序应处理请求。

签名计算应按以下步骤完成:

  1. 检索 X-UiPath-Signature HTTP 标头。
  2. 要获取原始签名字节,请从 Base64 解码标头的值。
  3. 检索原始请求正文。

    注意:Orchestrator 请求始终使用 UTF-8 编码。
  4. 使用 SHA256 和签名密钥(UTF-8 编码)计算哈希值。
  5. 将计算得出的签名与 X-UiPath-Signature HTTP 标头中的值进行比较:
    • 如果签名不匹配,则不会处理请求。
    • 如果签名匹配,则客户端应用程序应处理请求。

签名验证示例

using System;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
 
 
public async Task<bool> IsValidRequestAsync(HttpRequestMessage request, string secret)
{
    if (!request.Headers.TryGetValues("X-UiPath-Signature", out var headerValues))
        return false;
 
    var orchestratorSignature = Convert.FromBase64String(headerValues.First());
    using (var sha = new HMACSHA256(key: Encoding.UTF8.GetBytes(secret)))
    {
        var computedSignature = sha.ComputeHash(await request.Content.ReadAsByteArrayAsync());
        return ByteArrayEquals(orchestratorSignature, computedSignature);
    }
}using System;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
 
 
public async Task<bool> IsValidRequestAsync(HttpRequestMessage request, string secret)
{
    if (!request.Headers.TryGetValues("X-UiPath-Signature", out var headerValues))
        return false;
 
    var orchestratorSignature = Convert.FromBase64String(headerValues.First());
    using (var sha = new HMACSHA256(key: Encoding.UTF8.GetBytes(secret)))
    {
        var computedSignature = sha.ComputeHash(await request.Content.ReadAsByteArrayAsync());
        return ByteArrayEquals(orchestratorSignature, computedSignature);
    }
}
const { createServer } = require('http');
const { createHmac } = require('crypto');
 
const PORT = 9090
const WEBHOOK_SECRET = '<same secret as configured in Orchestrator>'
 
const isValidRequest = (body /* Buffer */, secret /* string */, expectedSignature /* string */) =>
    expectedSignature == null || createHmac('sha256', secret)
        .update(body)
        .digest('base64') === expectedSignature
 
const server = createServer((req, resp) => {
 
    let body = new Buffer([])
 
    req.on('data', chunk => body = Buffer.concat([body, chunk]))
 
    req.on('end', () => {
 
        if (!isValidRequest(body, WEBHOOK_SECRET, req.headers['x-uipath-signature'])) {
            console.error('Invalid signature')
            resp.statusCode = 401 // Unauthorized
        } else {
 
            let payload = JSON.parse(body.toString('utf8'))
 
            // Process request
            console.log(payload)
 
            resp.statusCode = 202 // Accepted
        }
 
        resp.end()
    })
 
})
 
server.listen(PORT)const { createServer } = require('http');
const { createHmac } = require('crypto');
 
const PORT = 9090
const WEBHOOK_SECRET = '<same secret as configured in Orchestrator>'
 
const isValidRequest = (body /* Buffer */, secret /* string */, expectedSignature /* string */) =>
    expectedSignature == null || createHmac('sha256', secret)
        .update(body)
        .digest('base64') === expectedSignature
 
const server = createServer((req, resp) => {
 
    let body = new Buffer([])
 
    req.on('data', chunk => body = Buffer.concat([body, chunk]))
 
    req.on('end', () => {
 
        if (!isValidRequest(body, WEBHOOK_SECRET, req.headers['x-uipath-signature'])) {
            console.error('Invalid signature')
            resp.statusCode = 401 // Unauthorized
        } else {
 
            let payload = JSON.parse(body.toString('utf8'))
 
            // Process request
            console.log(payload)
 
            resp.statusCode = 202 // Accepted
        }
 
        resp.end()
    })
 
})
 
server.listen(PORT)
  • 通用有效负载属性
  • 权限
  • 身份验证
  • 签名验证示例

此页面是否有帮助?

获取您需要的帮助
了解 RPA - 自动化课程
UiPath Community 论坛
Uipath 白色徽标
信任与安全
© 2005-2024 UiPath. All rights reserved.