UiPath
Integrare UiPath con Blu Pantheon: HTTP Request activity, Orchestrator Assets, code di lavoro, retry scope e verifica HMAC in VB.NET.
Guida completa per collegare UiPath Studio e Orchestrator a Blu Pantheon nelle due direzioni: chiamare le API della piattaforma e ricevere webhook.
Prima di iniziare
- UiPath Studio 2023.10 o superiore con il pacchetto UiPath.Web.Activities installato
- Accesso a Orchestrator con permessi su Assets e Queues
- Una chiave API bp_live_xxxxxxxxxxxxxxxx creata in Console
- Il segreto whsec_xxxxxxxxxxxxxxxx del webhook
- Un listener HTTP raggiungibile da Internet che alimenta una coda Orchestrator
Architettura consigliata
UiPath non espone endpoint HTTP pubblici. Il pattern corretto prevede un listener
intermedio che riceve il webhook, verifica la firma e inserisce un elemento nella coda
Orchestrator tramite l'API Add Queue Item.
Blu Pantheon ──webhook firmato──► Listener (Azure Function / IIS / Nginx+app)
│ verifica HMAC + risposta 202
▼
Orchestrator Queue "BluPantheonEvents"
│ Queue Trigger
▼
Robot UiPath
│
├──► Gestionale (UI automation)
└──► API Blu Pantheon (HTTP Request)Perché non chiamare direttamente il robot
Un robot impegnato o offline farebbe fallire la consegna. La coda disaccoppia la ricezione
dall'esecuzione e consente di rispondere 202 in millisecondi.
Parte 1 — Conservare la chiave API in Orchestrator
Crea il Credential asset
In Orchestrator apri Tenant → Assets → Add asset.
| Campo | Valore |
|---|---|
| Name | BluPantheon_ApiKey |
| Type | Credential |
| Username | api |
| Password | bp_live_xxxxxxxxxxxxxxxx |
| Description | Chiave API Blu Pantheon — progetto bp_proj_7f3a9c21 |
| Value per Robot | disattivato |
Crea gli asset di configurazione
Aggiungi due asset di tipo Text:
| Name | Value |
|---|---|
BluPantheon_BaseUrl | https://api.blupantheon.com |
BluPantheon_ProjectId | bp_proj_7f3a9c21 |
Leggi la credenziale nel workflow
Inserisci l'attività Get Credential:
| Proprietà | Valore |
|---|---|
| AssetName | "BluPantheon_ApiKey" |
| Username | out_Username (String) |
| Password | out_ApiKeySecure (SecureString) |
Converti la SecureString in String solo al momento dell'uso:
apiKey = New System.Net.NetworkCredential(String.Empty, out_ApiKeySecure).PasswordElimina la variabile dopo l'uso
Al termine della sequenza azzera la variabile per non lasciare il segreto in memoria e nei log di verbose logging:
apiKey = String.EmptyMai in chiaro
Non salvare la chiave in un asset di tipo Text, in un file di configurazione Config.xlsx
versionato o in un argomento di default del workflow. Gli asset Text sono leggibili in
chiaro da chiunque abbia accesso a Orchestrator.
Parte 2 — Chiamare le API di Blu Pantheon
Configurare HTTP Request
Trascina l'attività HTTP Request (pacchetto UiPath.Web.Activities) e compila:
| Proprietà | Valore |
|---|---|
| EndPoint | baseUrl + "/identity/v1/sessions/" + sessionId + "/notes" |
| Method | POST |
| AcceptFormat | JSON |
| BodyFormat | application/json |
| Body | requestBody (String) |
| Headers | collezione, vedi sotto |
| TimeoutMS | 15000 |
| Result | responseBody (String) |
| StatusCode | statusCode (Int32) |
Popola la collezione Headers con un Build Collection oppure con un Assign su un
Dictionary(Of String, String):
headers = New Dictionary(Of String, String) From {
{"Authorization", "Bearer " & apiKey},
{"X-BP-Project", projectId},
{"Content-Type", "application/json"},
{"Accept", "application/json"},
{"Idempotency-Key", deliveryId}
}Idempotency-Key da X-BP-Delivery
Usa l'identificativo della consegna che ha originato il lavoro come Idempotency-Key. Se il
robot fallisce a metà e la coda ritenta, la piattaforma non creerà un duplicato.
Costruire il corpo della richiesta
Non concatenare stringhe a mano: usa JObject per evitare problemi di escaping con apostrofi e
accenti.
requestBody = New Newtonsoft.Json.Linq.JObject(
New Newtonsoft.Json.Linq.JProperty("body", "Pratica aperta nel gestionale: " & numeroPratica),
New Newtonsoft.Json.Linq.JProperty("visibility", "internal"),
New Newtonsoft.Json.Linq.JProperty("author", "rpa-uipath")
).ToString(Newtonsoft.Json.Formatting.None)Deserializzare la risposta
Inserisci l'attività Deserialize JSON (pacchetto UiPath.WebAPI.Activities):
| Proprietà | Valore |
|---|---|
| JsonString | responseBody |
| TypeArgument | Newtonsoft.Json.Linq.JObject |
| JsonObject | responseJson (JObject) |
Accedi ai campi con indicizzazione tipizzata:
noteId = responseJson("data")("id").ToString()
createdAt = DateTime.Parse(responseJson("data")("createdAt").ToString())Per gli array usa Deserialize JSON Array con TypeArgument JArray:
For Each item As Newtonsoft.Json.Linq.JToken In responseJson("data")
Log Message: "Cliente: " & item("displayName").ToString()
NextGestione degli errori con Retry Scope
Avvolgi l'attività HTTP Request in un Retry Scope:
| Proprietà | Valore |
|---|---|
| NumberOfRetries | 3 |
| RetryInterval | 00:00:05 |
Nella sezione Condition inserisci un Is True con:
statusCode >= 200 AndAlso statusCode < 300Aggiungi un Try Catch esterno per distinguere gli errori:
| Codice ricevuto | Azione nel Catch |
|---|---|
401 | Errore di configurazione: interrompi, non ritentare, invia notifica |
403 | Scope insufficienti: interrompi, apri segnalazione |
409 | Conflitto: leggi la risorsa esistente e prosegui |
429 | Leggi Retry-After e attendi con Delay, poi ritenta |
5xx | Ritenta con backoff, poi marca l'elemento in coda come Failed |
retryAfterSeconds = If(
response.Headers.ContainsKey("Retry-After"),
Convert.ToInt32(response.Headers("Retry-After")),
30
)Parte 3 — Ricevere i webhook
Listener intermedio
Il listener può essere una Azure Function, un servizio ASP.NET o qualsiasi endpoint HTTPS. Deve verificare la firma e inserire l'elemento in coda tramite l'API di Orchestrator.
using System.Net.Http.Json;
using System.Security.Cryptography;
using System.Text;
public sealed class OrchestratorQueueClient
{
private readonly HttpClient _http;
public OrchestratorQueueClient(HttpClient http) => _http = http;
public async Task AddQueueItemAsync(string rawBody, string deliveryId, string eventType)
{
var request = new
{
itemData = new
{
Name = "BluPantheonEvents",
Priority = eventType.Contains("handover") ? "High" : "Normal",
Reference = deliveryId,
SpecificContent = new Dictionary<string, object>
{
["EventType"] = eventType,
["DeliveryId"] = deliveryId,
["Payload"] = rawBody
}
}
};
using var response = await _http.PostAsJsonAsync(
"/odata/Queues/UiPathODataSvc.AddQueueItem", request);
response.EnsureSuccessStatusCode();
}
}Reference come chiave di deduplica
Imposta Reference uguale a X-BP-Delivery e attiva Unique Reference sulla coda.
Orchestrator rifiuterà automaticamente i duplicati con errore Conflict, che il listener può
trattare come successo rispondendo 202.
Verifica HMAC in VB.NET
Se il listener è realizzato con un processo UiPath in modalità servizio, oppure se devi verificare la firma dentro un Invoke Code activity, usa questo snippet VB.NET.
Configura l'attività Invoke Code con:
| Proprietà | Valore |
|---|---|
| Language | VBNet |
| Arguments | in_RawBody (String), in_SignatureHeader (String), in_Secret (String), out_IsValid (Boolean), out_Reason (String) |
Dim toleranceSeconds As Integer = 300
Dim timestamp As Long = -1
Dim signatures As New List(Of String)
out_IsValid = False
out_Reason = "firma-non-corrispondente"
If String.IsNullOrWhiteSpace(in_SignatureHeader) Then
out_Reason = "header-mancante"
Exit Sub
End If
For Each segment As String In in_SignatureHeader.Split(","c)
Dim separatorIndex As Integer = segment.IndexOf("="c)
If separatorIndex < 0 Then Continue For
Dim key As String = segment.Substring(0, separatorIndex).Trim()
Dim value As String = segment.Substring(separatorIndex + 1).Trim()
If key = "t" Then
Long.TryParse(value, timestamp)
ElseIf key = "v1" Then
signatures.Add(value)
End If
Next
If timestamp < 0 Then
out_Reason = "timestamp-non-valido"
Exit Sub
End If
Dim nowSeconds As Long = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
If Math.Abs(nowSeconds - timestamp) > toleranceSeconds Then
out_Reason = "timestamp-fuori-tolleranza"
Exit Sub
End If
If signatures.Count = 0 Then
out_Reason = "firma-assente"
Exit Sub
End If
Dim signedPayload As Byte() = System.Text.Encoding.UTF8.GetBytes(
timestamp.ToString() & "." & in_RawBody)
Using hmac As New System.Security.Cryptography.HMACSHA256(
System.Text.Encoding.UTF8.GetBytes(in_Secret))
Dim hash As Byte() = hmac.ComputeHash(signedPayload)
Dim builder As New System.Text.StringBuilder(hash.Length * 2)
For Each b As Byte In hash
builder.Append(b.ToString("x2"))
Next
Dim expected As String = builder.ToString()
Dim expectedBytes As Byte() = System.Text.Encoding.UTF8.GetBytes(expected)
For Each candidate As String In signatures
Dim candidateBytes As Byte() = System.Text.Encoding.UTF8.GetBytes(candidate)
If candidateBytes.Length = expectedBytes.Length Then
If System.Security.Cryptography.CryptographicOperations.FixedTimeEquals(
candidateBytes, expectedBytes) Then
out_IsValid = True
out_Reason = "ok"
Exit For
End If
End If
Next
End UsingQueue Trigger
In Orchestrator apri Automations → Triggers → Add trigger → Queue trigger.
| Campo | Valore |
|---|---|
| Name | BluPantheon — eventi |
| Process | BluPantheon.EventProcessor |
| Queue | BluPantheonEvents |
| Minimum number of items | 1 |
| Maximum number of pending jobs | 5 |
| Allocate dynamically | attivo |
Elaborare l'elemento nel processo
eventType = in_TransactionItem.SpecificContent("EventType").ToString()
deliveryId = in_TransactionItem.SpecificContent("DeliveryId").ToString()
payloadJson = Newtonsoft.Json.Linq.JObject.Parse(
in_TransactionItem.SpecificContent("Payload").ToString())
sessionId = payloadJson("data")("sessionId").ToString()
clientName = payloadJson("data")("client")("displayName").ToString()Concludi con Set Transaction Status:
| Esito | Status | Note |
|---|---|---|
| Operazione riuscita | Successful | Nessuna azione ulteriore |
| Errore applicativo (dato non valido) | Failed → BusinessException | Nessun ritentativo |
| Errore tecnico (gestionale non risponde) | Failed → ApplicationException | Ritentativo automatico |
Test dell'integrazione
Verifica la chiamata API
Esegui in Studio un workflow minimo con HTTP Request su /identity/v1/me. Il risultato
atteso è statusCode = 200 e un corpo JSON con i dati del tenant.
Verifica il listener
Dalla Console usa Invia evento di prova con webhook.test. Controlla nei log consegne che
la risposta sia 202 e che in Orchestrator compaia un nuovo elemento in coda con
Reference uguale al X-BP-Delivery.
Verifica la deduplica
Nei log consegne clicca Riprova sulla stessa consegna. Orchestrator deve rifiutare il
duplicato per Unique Reference e il listener deve comunque rispondere 202.
Verifica il ciclo completo
Genera un handover reale dal widget di test. Verifica che il robot apra la pratica nel gestionale e che la nota compaia nella sessione in Console.
Verifica la gestione errori
Sospendi temporaneamente il robot e osserva l'accumulo in coda. Al ripristino gli elementi devono essere elaborati senza perdite e senza duplicati.