Blu Pantheon
الأتمتة وRPAمنصات RPA

Power Automate

Ricevere webhook Blu Pantheon in Power Automate, validare la firma HMAC e chiamare le API con l azione HTTP e Azure Key Vault.

Guida per costruire flussi Power Automate (cloud flow) che ricevono eventi da Blu Pantheon e scrivono nei sistemi Microsoft 365, Dataverse o in gestionali on-premise tramite gateway.

Prima di iniziare

  • Licenza Power Automate Premium (le azioni HTTP e Key Vault sono connettori premium)
  • Un ambiente Power Platform con permessi di creazione flussi
  • Un Azure Key Vault con i segreti bp-api-key e bp-webhook-secret
  • La chiave API bp_live_xxxxxxxxxxxxxxxx e il segreto whsec_xxxxxxxxxxxxxxxx

Licenze premium

Le azioni HTTP, HTTP con Azure AD e il connettore Azure Key Vault richiedono un piano Power Automate Premium (o Per-flow). Il trigger "Quando viene ricevuta una richiesta HTTP" richiede a sua volta un piano premium per l'uso in produzione. Verifica le licenze prima di progettare il flusso.

Parte 1 — Ricevere il webhook

Crea il flusso

In make.powerautomate.com scegli Crea → Flusso cloud automatizzato istantaneo. Nome: BluPantheon - Ricezione eventi. Come trigger seleziona Quando viene ricevuta una richiesta HTTP (When an HTTP request is received).

Imposta il metodo

Espandi Mostra opzioni avanzate e imposta Metodo su POST.

Incolla lo schema JSON del corpo

Nel riquadro Schema JSON del corpo della richiesta incolla lo schema seguente. Definisce l'envelope comune e i campi più usati.

Request Body JSON Schema
{
  "type": "object",
  "properties": {
    "id": { "type": "string" },
    "event": { "type": "string" },
    "apiVersion": { "type": "string" },
    "createdAt": { "type": "string" },
    "tenantId": { "type": "string" },
    "projectId": { "type": "string" },
    "data": {
      "type": "object",
      "properties": {
        "sessionId": { "type": "string" },
        "clientId": { "type": "string" },
        "bookingId": { "type": "string" },
        "documentId": { "type": "string" },
        "reason": { "type": "string" },
        "priority": { "type": "string" },
        "queue": { "type": "string" },
        "summary": { "type": "string" },
        "status": { "type": "string" },
        "reference": { "type": "string" },
        "startAt": { "type": "string" },
        "endAt": { "type": "string" },
        "timezone": { "type": "string" },
        "traceId": { "type": "string" },
        "client": {
          "type": "object",
          "properties": {
            "id": { "type": "string" },
            "displayName": { "type": "string" },
            "email": { "type": "string" },
            "phone": { "type": "string" }
          }
        },
        "service": {
          "type": "object",
          "properties": {
            "id": { "type": "string" },
            "name": { "type": "string" },
            "durationMinutes": { "type": "integer" }
          }
        },
        "classification": {
          "type": "object",
          "properties": {
            "category": { "type": "string" },
            "confidence": { "type": "number" }
          }
        }
      }
    }
  },
  "required": ["id", "event", "apiVersion", "createdAt", "tenantId", "projectId", "data"]
}

Salva e copia l'URL

Salva il flusso. Torna sul trigger: l'URL POST HTTP è ora popolato. Ha questa forma:

https://prod-42.westeurope.logic.azure.com:443/workflows/<id>/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=<firma>

Copialo integralmente, inclusi i parametri di query.

Registra l'endpoint in Console

ConsoleConfigurazioneWebhookNuovo webhook

Incolla l'URL completo nel campo URL e seleziona gli eventi da sottoscrivere.

La firma SAS dell URL non basta

Il parametro sig nell'URL rende l'endpoint difficile da indovinare, ma chiunque lo intercetti può invocare il flusso. La validazione HMAC descritta sotto è obbligatoria.

Parte 2 — Leggere i segreti da Key Vault

Prepara Key Vault

In Azure crea (o riusa) un Key Vault e aggiungi due segreti:

Nome segretoValore
bp-api-keybp_live_xxxxxxxxxxxxxxxx
bp-webhook-secretwhsec_xxxxxxxxxxxxxxxx

Aggiungi l'azione Key Vault

Nel flusso aggiungi Azure Key Vault → Ottieni segreto (Get secret).

CampoValore
Nome del segretobp-webhook-secret

Rinomina l'azione in Ottieni segreto webhook.

Nascondi il valore nei log

Apri Impostazioni dell'azione e attiva Impostazioni sicure → Proteggi output. Senza questa impostazione il segreto compare in chiaro nella cronologia di esecuzione del flusso.

Ripeti per la chiave API

Duplica l'azione impostando Nome del segreto su bp-api-key e rinominala Ottieni chiave API. Attiva anche qui Proteggi output.

Parte 3 — Validare la firma HMAC

Power Automate non dispone di una funzione HMAC nativa nelle espressioni. Usa l'azione Inline Code → Esegui codice JavaScript (Execute JavaScript Code), disponibile negli ambienti con Power Platform e Node abilitati.

Recupera il corpo grezzo e gli header

Aggiungi un'azione Componi (Compose) rinominata Corpo grezzo con espressione:

string(triggerOutputs()?['body'])

Aggiungi un'altra Componi rinominata Header firma:

triggerOutputs()?['headers']?['X-BP-Signature']

E una terza rinominata Header consegna:

triggerOutputs()?['headers']?['X-BP-Delivery']

Aggiungi l'azione JavaScript

Inserisci Esegui codice JavaScript rinominata Verifica firma con questo codice:

Esegui codice JavaScript
const crypto = require('crypto');

const rawBody = workflowContext.actions['Corpo_grezzo'].outputs;
const signatureHeader = workflowContext.actions['Header_firma'].outputs || '';
const secret = workflowContext.actions['Ottieni_segreto_webhook'].outputs.body.value;

const TOLERANCE_SECONDS = 300;

let timestamp = null;
const signatures = [];

for (const segment of signatureHeader.split(',')) {
  const index = segment.indexOf('=');
  if (index === -1) continue;
  const key = segment.slice(0, index).trim();
  const value = segment.slice(index + 1).trim();
  if (key === 't') timestamp = Number(value);
  if (key === 'v1') signatures.push(value);
}

if (!Number.isFinite(timestamp)) {
  return { valid: false, reason: 'timestamp-non-valido' };
}

const now = Math.floor(Date.now() / 1000);
if (Math.abs(now - timestamp) > TOLERANCE_SECONDS) {
  return { valid: false, reason: 'timestamp-fuori-tolleranza' };
}

if (signatures.length === 0) {
  return { valid: false, reason: 'firma-assente' };
}

const expected = crypto
  .createHmac('sha256', secret)
  .update(timestamp + '.' + rawBody, 'utf8')
  .digest('hex');

const expectedBuffer = Buffer.from(expected, 'utf8');
let valid = false;

for (const candidate of signatures) {
  const candidateBuffer = Buffer.from(candidate, 'utf8');
  if (
    candidateBuffer.length === expectedBuffer.length &&
    crypto.timingSafeEqual(candidateBuffer, expectedBuffer)
  ) {
    valid = true;
    break;
  }
}

return { valid, reason: valid ? 'ok' : 'firma-non-corrispondente' };

Nomi delle azioni negli indirizzamenti

In workflowContext.actions i nomi delle azioni usano l'underscore al posto degli spazi. Corpo grezzo diventa Corpo_grezzo. Se rinomini un'azione, aggiorna il codice.

Interrompi se la firma non è valida

Aggiungi una Condizione (Condition) rinominata Firma valida?:

Lato sinistroOperatoreLato destro
body('Verifica_firma')?['valid']è uguale atrue

Nel ramo Se no inserisci:

  1. Risposta (Response) con Codice di stato 401 e Corpo {"error": "firma non valida"}.
  2. Termina (Terminate) con Stato Failed, Codice errore SIGNATURE_INVALID, Messaggio errore Firma HMAC non verificata.

Rispondi subito nel ramo positivo

Nel ramo Se sì, come prima azione inserisci Risposta con Codice di stato 202 e corpo vuoto. Poi prosegui con la logica di business.

Rispondi prima di elaborare

Il trigger HTTP attende la prima azione Risposta. Se la inserisci dopo dieci azioni lente, Blu Pantheon andrà in timeout e ritenterà.

Parte 4 — Chiamare le API di Blu Pantheon

Aggiungi l'azione HTTP (connettore premium) e compila:

CampoValore
MetodoPOST
URIhttps://api.blupantheon.com/identity/v1/sessions/@{triggerBody()?['data']?['sessionId']}/notes
Intestazionivedi tabella sotto
Corpovedi JSON sotto

Intestazioni da inserire nella vista chiave/valore:

ChiaveValore
AuthorizationBearer @{body('Ottieni_chiave_API')?['value']}
X-BP-Projectbp_proj_7f3a9c21
Content-Typeapplication/json
Idempotency-Key@{outputs('Header_consegna')}

Corpo della richiesta:

{
  "body": "Ticket aperto in ServiceNow: @{body('Crea_ticket')?['number']}",
  "visibility": "internal",
  "author": "power-automate"
}

Proteggi gli input dell azione HTTP

Apri Impostazioni dell'azione HTTP e attiva Proteggi input. Senza questa opzione l'header Authorization con la chiave API è visibile nella cronologia esecuzioni a chiunque possa aprire il flusso.

Gestione dei limiti di frequenza

Configura in Impostazioni dell'azione HTTP:

ImpostazioneValore
Criterio dei tentativiIntervallo esponenziale
Numero di tentativi4
IntervalloPT10S
Intervallo minimoPT5S
Intervallo massimoPT2M
TimeoutPT30S

Parte 5 — Gestione degli errori

Configura Ambito e Configura esecuzione dopo

Raggruppa la logica di business in un Ambito (Scope) rinominato Elaborazione. Aggiungi un secondo ambito Gestione errori e configura Configura esecuzione dopo selezionando è non riuscita, è stata ignorata e è scaduta.

Notifica il fallimento

Dentro Gestione errori inserisci Invia messaggio di posta elettronica (V2) verso automazioni@acme.it con oggetto:

[Blu Pantheon] Flusso fallito - evento @{triggerBody()?['event']}

E corpo che includa @{triggerBody()?['id']}, @{outputs('Header_consegna')} e @{result('Elaborazione')}.

Termina con stato coerente

Chiudi con Termina e Stato Failed. Questo rende il fallimento visibile nella dashboard delle analisi del flusso.

SituazioneComportamento consigliato
Firma non valida401 + Terminate Failed. Nessun ritentativo utile.
Sistema a valle non rispondeRitentativo automatico dell'azione, poi Terminate Failed.
Dato mancante nel payloadTerminate Failed con messaggio esplicito. Non ritentare.
429 dalle API Blu PantheonRitentativo esponenziale già configurato sull'azione HTTP.
Evento duplicatoControlla X-BP-Delivery in una tabella Dataverse prima di elaborare.

Test del flusso

Invia un evento di prova

ConsoleConfigurazioneWebhookInvia evento di prova

Seleziona webhook.test e invia. Il flusso deve completarsi con esito positivo.

Controlla la cronologia

Apri il flusso, sezione Cronologia esecuzioni (Run history). Verifica che Verifica firma restituisca valid: true e che la Risposta sia 202.

Verifica il rifiuto

Modifica temporaneamente il segreto in Key Vault con un valore errato ed esegui di nuovo il test. Il flusso deve terminare con SIGNATURE_INVALID. Ripristina subito il valore corretto.

Verifica la chiamata inbound

Controlla in Console che la nota sia stata aggiunta alla sessione di prova.

Passi successivi

في هذه الصفحة