- 基本情報
- ベスト プラクティス
- テナント
- リソース カタログ サービス
- フォルダー コンテキスト
- 自動化
- プロセス
- ジョブ
- トリガー
- ログ
- 監視
- キュー
- アセット
- ストレージ バケット
- Test Suite - Orchestrator
- その他の構成
- Integrations
- クラシック ロボット
- ホストの管理
- 組織管理者
- トラブルシューティング
Webhook
Webhook を使用すると、UiPath のオートメーションとお使いのアプリケーション エコシステム全体とをより適切に連携させることができます。Orchestrator のイベントをサブスクライブし、その情報を外部のいずれかの DCM、BPM、CRM ソリューションに送信することで、さまざまなユーザーに情報 (たとえば処理可能なキュー アイテムが新しく存在すること、トリガーが失敗したこと、プロセスが更新されたことなど) を伝えられます。
Webhook では、さまざまな種類の Orchestrator イベントを外部システムがサブスクライブしてリッスンすることができます。[Webhooks] ページでは、サブスクライブするイベントを簡単に設定でき、作成済みのものを確認することもできます。また、Webhook の無効化、検索、編集、削除も行えます。
イベントは、ジョブ、ロボット、キュー、キュー アイテム、プロセス、トリガーで利用可能です。
各イベントは、情報を含む指定した URL にペイロードを送信します。プロパティには、すべてに共通なものとイベントの種類に固有のものがあります。
Webhook イベントはフォルダーごとに作成されるため、フォルダー間で共有されるリソース (キューなど) に Webhook イベントが関連付けられている場合は、フォルダーごとに個別の Webhook イベントが生成されます。
プロパティ名 |
プロパティの種類 |
説明および例 |
---|---|---|
入力 |
string |
通知をトリガーするイベントの種類です。 このプロパティはすべてのイベントの種類で表示されます。 例:
|
EventId |
string |
イベント発生時に、イベントに対して一意に生成される ID です。 このプロパティはすべてのイベントの種類で表示されます。 例:
|
Timestamp |
RFC 8601 日付 |
イベントが生成された日付と時刻です。 このプロパティはすべてのイベントの種類で表示されます。 例:
|
TenantId |
integer |
イベントが生成されたテナントの ID です。既定のテナントは 1 です。 このプロパティはすべてのイベントの種類で表示されます。 例:
|
UserId |
integer |
イベントをトリガーしたアクションを実行したユーザーの ID です。 イベントが、ロボットまたはトリガーのいずれかによってトリガーされた場合、このパラメーターは表示されません。 このプロパティはすべてのイベントの種類で表示されます。 例:
|
FolderId |
integer |
イベントが生成されたフォルダーの ID です。 イベントがモダン ロボットによってトリガーされた場合、このパラメーターは表示されません。 例:
|
[Webhooks] ページでさまざまな操作を行うには、Webhook 上で該当する権限を持っていなければなりません。
- 表示 - Webhook とその詳細を表示できます。また、それらの情報の API を使用した取得、Ping 要求の送信、Webhook がサブスクライブできる全イベントのリストの取得が可能です。
- 作成 - この権限があると、新しい Webhook を追加できます。これには、[表示] 権限も必要になります。
- 編集 - UI または API を使用して Webhook を編集する権限が付与されます。これには、[表示] 権限も必要になります。
- 削除 - Webhook を削除できる権限です。これには、[表示] 権限も必要になります。
X-UiPath-Signature
HTTP ヘッダーを通じて送信されます。
Orchestrator の要求を受信するクライアント アプリケーションは、要求の信頼性をチェックする必要があります。要求の署名は、次のパターンに従って行われます。
- クライアント アプリケーションは、Orchestrator からの要求を受信します。
- クライアント アプリケーションは、要求に基づいて署名を計算します。
-
クライアント アプリケーションは、自身が計算した署名と要求の署名を照合します。
- 署名が一致しない場合、クライアント アプリケーションは要求を処理しません。
- 署名が一致した場合、クライアント アプリケーションは要求を処理します。
署名の計算は、次のように行われます。
X-UiPath-Signature
HTTP ヘッダーを取得します。- 署名のローバイトを取得するには、Base64 からヘッダーの値をデコードします。
-
生の (ロー) 要求本文を取得します。
注: Orchestrator の要求は常に UTF-8 でエンコードされています。 - SHA256 と (UTF-8 でエンコードされた) 署名鍵を使用してハッシュを計算します。
-
計算した署名と
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)