Ambiente:
Skip to main content
Questa documentazione è in versione BETA, per qualsiasi informazione contattaci alla mail api@sibill.it

Webhook

Quando crei un'integrazione con Sibill, potresti essere interessato a ricevere eventi man mano che si verificano nelle entità dei tuoi account Sibill, in modo che i sistemi di backend possano eseguire azioni di conseguenza.

Come si fa

Per iniziare a ricevere eventi nella tua app:

  1. Crea un webhook endpoint per ricevere gli eventi tramite richieste HTTPS in POST
  2. Chiedi la registrazione del webhook su Sibill
  3. Metti in sicurezza l'endpoint

Un webhook endpoint è una destinazione sul tuo server che riceve richieste da Sibill. Aggiungi un nuovo endpoint al tuo server e assicurati che sia pubblicamente accessibile, così possiamo inviare richieste in POST non autenticate. Assicurati inoltre che non ci siano redirect dalla destinazione sul tuo server verso altre destinazioni. Se dovesse succedere, in qualsiasi momento, un redirect, la destinazione verrà identificata come invalida.

1 Creare un endpoint per rispondere al webhook

Crea un servizio HTTPS che possa ricevere richieste con il metodo POST. Il servizio deve restituire una risposta con status code 2xx il prima possibile e poi eseguire logiche di business per evitare eventuali timeout.

Esempio

// Set the content type to application/json
header('Content-Type: application/json');

// Get the raw POST data
$json = file_get_contents('php://input');

// Decode the JSON data
$data = json_decode($json, true);

// Prepare the response array
$response = [];

// Check for JSON decoding errors
if (json_last_error() !== JSON_ERROR_NONE) {
// If there's an error, include it in the response
$response['error'] = 'Invalid JSON';
} else {
// If the JSON is valid, include the parsed data
$response['received'] = $data;
}

// Always return a 200 status code
http_response_code(200);
echo json_encode($response);

2 Registrare il tuo endpoint

Al momento la registrazione deve avvenire facendo richiesta all'indirizzo email api@sibill.it. In tale richiesta sarà necessario fornire l'indirizzo HTTPS dell'enpoint che risponderà alle chiamate.

3 Mettere in sicurezza l'endpoint

È fondamentale garantire che l'integrazione avvenga in totale sicurezza, in modo da essere certi che le richieste ricevute siano effettivamente originate da Sibill. Per questo motivo è necessario verificare le firme delle richieste ricevute.

In seguito sono stati portati alcuni esempi

Verifica manualmente la firma dei webhook

Puoi creare una soluzione personalizzata seguendo questa procedura oppure seguire gli esempi che trovi sotto. L’intestazione X-Sibill-Signature inclusa in ogni evento firmato contiene un timestamp e una firma che devi verificare. Il timestamp ha un prefisso t= e ogni firma ha un prefisso scheme. Attualmente, l’unico schema valido per le firme è v1.

X-Sibill-Signature: t=1492774577, v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd

Sibill genera le firme utilizzando una modalità di autenticazione dei messaggi basata su hash (HMAC) con SHA-256. Per impedire gli attacchi basati su downgrade attack, ignora tutti gli schemi diversi da v1.

Per creare una soluzione manuale per la verifica delle firme, è necessario completare i seguenti passaggi:

Fase 1: estrarre il timestamp e la firma dall’intestazione

Per ottenere un elenco degli elementi, suddividi l’intestazione, utilizzando il carattere , come separatore. Poi suddividi ogni elemento, utilizzando il carattere = come separatore, per ottenere un prefisso e una coppia di valori. Il valore del prefisso t corrisponde al timestamp e v1 corrisponde alla firma. Puoi ignorare tutti gli altri elementi.

Fase 2: preparare la stringa signed_payload

La stringa signed_payload viene creata concatenando:

  • Il timestamp (come stringa)
  • Il carattere .
  • Il payload JSON effettivo, ovvero il corpo della richiesta

Fase 3: determinare la firma prevista

Calcola un HMAC con la funzione hash SHA256. Utilizza la chiave privata di firma dell’endpoint come chiave e la stringa signed_payload come messaggio.

Fase 4: confrontare le firme

Confronta la firma nell’intestazione con la firma prevista. Per una corrispondenza di eguaglianza, calcola la differenza tra il timestamp corrente e quello ricevuto, poi decidi se la differenza rientra nella tolleranza. Per proteggerti dagli attacchi temporizzati, utilizza un confronto di stringhe a tempo costante per confrontare la firma prevista con ogni firma ricevuta.

Esempio di validazione della firma

abstract class WebhookSignature
{
public static function verifyHeader($payload, $header, $secret)
{
// Extract timestamp and signatures from header
$timestamp = self::getTimestamp($header);
$signatures = self::getSignatures($header, 'v1');

if (-1 === $timestamp || empty($signatures)) {
return false;
}

// Check if expected signature is found in list of signatures from header
$signedPayload = "{$timestamp}.{$payload}";
$expectedSignature = self::computeSignature($signedPayload, $secret);
$signatureFound = false;

foreach ($signatures as $signature) {
if (\hash_equals($expectedSignature, $signature)) {
$signatureFound = true;
break;
}
}

return $signatureFound;
}

/**
* Extracts from the headers a prticular header given a key name.
*
* @param string $headers the headers of the reques
* @param string $header the header to be extracted
*
* @return the string value of the header
*/
private static function getHeader($headers, $header)
{
$items = \explode(',', $headers);

$headerValues = [];
foreach ($items as $item) {
$itemParts = \explode('=', $item, 2);
if (\trim($itemParts[0]) === $header) {
$headerValues[] = $itemParts[1];
}
}

return $headerValues;
}


private static function getTimestamp($header)
{
$res = self::getHeader($header, 't');

if (\count($res) != 1) {
return -1;
}

if (!\is_numeric($res[0])) {
return -1;
}

return (int) $res[0];
}

private static function getSignatures($header, $scheme)
{
return self::getHeader($headers, $scheme);
}

private static function computeSignature($payload, $secret)
{
return \hash_hmac('sha256', $payload, $secret);
}
}

Comportamenti di consegna degli eventi

Questa sezione ti aiuta a comprendere i vari comportamenti da aspettarsi per quanto riguarda il modo in cui Sibill invia gli eventi all’endpoint del webhook.

Tentativi automatici

Sibill tenta di consegnare gli eventi alla tua destinazione per un massimo di due giorni con un ritardo di tre ora ad ogni nuovo tentativo.

Ordine degli eventi

Sibill non garantisce la consegna degli eventi nell’ordine in cui sono stati generati nel sistema. Preparati a gestire la consegna in modo appropriato. Puoi anche utilizzare l’API per recuperare eventuali oggetti mancanti o per ricostruire uno stato che sembra non consistente.

Pratiche ottimali di utilizzo dei webhook

Questa sezione elenca alcune pratiche ottimali per proteggere gli endpoint del webhook e assicurarti che funzionino bene con la tua integrazione con Sibill.

Gestire gli eventi duplicati

A volte gli endpoint dei webhook potrebbero ricevere lo stesso evento più di una volta. Per proteggerti dalla ricezione di eventi duplicati, gestisci l'evento e poi non elaborare gli eventi già registrati; puoi affidarti a diversi campi tra cui updated_at o dedurre la validità dell'evento dallo stato dell'entità.

Ascoltare solo i tipi di evento richiesti dalla tua integrazione

Configura gli endpoint dei webhook per ricevere solo i tipi di eventi richiesti dalla tua integrazione e ingorare gli altri. L'ascolto di tutti gli eventi appesantisce inutilmente il server e pertanto è sconsigliato.

Gestire gli eventi in modo asincrono

Configura il tuo sistema per elaborare i prossimi eventi con una coda asincrona. Se scegli di elaborare gli eventi in modo sincrono, potrebbero verificarsi problemi di scalabilità. Un forte aumento delle consegne di webhook (ad esempio, alla fine del mese, e secondo la periodicità del tuo business) può sovraccaricare gli host degli endpoint.

Ricevere eventi con un server HTTPS

Per ricevere eventi dal webhook di Sibill, il tuo server deve essere configurato correttamente per supportare il protocollo HTTPS e deve disporre di un certificato valido.

Impedire gli attacchi di tipo replay

Un attacco di tipo replay si verifica quando un utente malintenzionato intercetta un paylod valido e la sua firma e poi li ritrasmette. Per mitigare questi attacchi, Sibill include un timestamp nell’intestazione X-Sibill-Signature. Dato che il timestamp fa parte del payload firmato, viene anch’esso verificato dalla firma: quindi un utente malintenzionato non può modificare il timestamp senza invalidare la firma. Se la firma è valida ma il timestamp è troppo vecchio, puoi fare in modo che la tua applicazione rifiuti il payload.

Restituire rapidamente una risposta 2xx

L’endpoint deve restituire rapidamente un codice di stato riuscito (2xx) prima che l’esecuzione di qualsiasi logica complessa possa causare un timeout. Ad esempio, è necessario restituire una risposta 200 prima che il sistema riceventi effettui qualsiasi operazione.