Salta ai contenuti

Ricevere webhook

Un webhook è AssinaJá che bussa alla porta del suo sistema quando succede qualcosa a un documento, invece di costringere il suo sistema a chiedere di continuo. È una richiesta POST che la piattaforma invia a un suo indirizzo.

Questa pagina è rivolta a chi integra AssinaJá con un altro programma. Se vuole solo vedere che cosa è successo a un documento, usi la cronologia del documento.

I webhook dell’organizzazione si configurano in Impostazioni → Sviluppatori → Webhook, e solo il Proprietario dell’organizzazione ha accesso a questa scheda. La pagina ha tre parti: Indirizzo ed eventi, Segreto del webhook e, sotto, Consegne.

In Indirizzo ed eventi:

  1. In Indirizzo del webhook, scriva l’indirizzo del suo sistema — “HTTPS, porta 443 o 8443, su un indirizzo pubblico. Nomi interni e indirizzi privati vengono rifiutati.”
  2. In Eventi da ricevere, scelga gli eventi — veda Gli eventi. “Senza eventi selezionati non viene inviato nulla. Ne scelga almeno uno.”
  3. Verifichi che Invio attivo sia attivato, e prema Salva.

Invia evento di prova invia una richiesta all’indirizzo e Le dice che cosa ha risposto — “L’indirizzo ha risposto {codice}.” oppure “Invio di prova non riuscito: {errore}”.

L’indirizzo non è libero. La piattaforma lo convalida prima di salvarlo, per non poter essere usata per raggiungere macchine che non sono sue:

  • HTTPS, sempre.
  • Porta 443 o 8443, e nessun’altra.
  • Un host pubblico: né localhost, né *.localhost, né *.internal, né metadata.google.internal.
  • Un indirizzo pubblico. Se il nome si risolve in un indirizzo privato o riservato — 10.x, 172.16–31.x, 192.168.x, 127.x, 169.254.x, 100.64.x, multicast, o gli equivalenti in IPv6 — viene rifiutato. Vengono verificati tutti gli indirizzi in cui il nome si risolve, non solo il primo.

Il rifiuto compare nella sua lingua:

Rifiuto Che cosa fare
“Indichi l’indirizzo del webhook.” il campo è vuoto
“L’indirizzo non è un URL valido.” manca lo schema, o c’è un errore di battitura
“L’indirizzo deve usare HTTPS.” sostituisca http:// con https://
“La porta deve essere 443 o 8443.” tolga la porta dall’indirizzo, oppure ne usi una di queste
“L’host è riservato (localhost, .internal, metadati cloud) e non può ricevere webhook.” usi un nome raggiungibile da Internet
“L’indirizzo IP non è pubblico.” ha scritto direttamente un IP privato
“Il nome host non si risolve in alcun indirizzo.” verifichi il DNS
“Impossibile risolvere il nome host.” il DNS non ha risposto; riprovi
“L’host si risolve in un indirizzo non pubblico.” il nome punta all’interno della sua rete

Nella scelta degli eventi, “Uno degli eventi scelti non è riconosciuto.” significa che l’elenco inviato contiene un nome che la piattaforma non conosce — lo verifichi nella tabella degli eventi, più sotto. E “Nessun indirizzo webhook configurato — ne indichi uno o salvi prima la sottoscrizione.” compare quando si tenta di sottoscrivere eventi prima che ci sia un indirizzo.

Evento Sullo schermo Quando viene inviato
document.completed Documento completato Tutti hanno firmato e il documento finale è pronto
document.rejected Documento rifiutato Un firmatario ha rifiutato
document.canceled Documento annullato Il documento è stato annullato
document.expired Documento scaduto La scadenza è passata senza che il documento fosse completato
document.pdf_application_failed Errore nell’applicazione delle firme al PDF Non è stato possibile applicare la firma al PDF
recipient.signed Il firmatario ha firmato Un firmatario ha firmato — una volta per firmatario
document.sent Documento inviato in firma Il documento è stato pubblicato e gli inviti sono partiti

Gli ultimi due non sono finali: il documento continua il suo percorso dopo di essi. Non tratti nessun evento come “è finito” — guardi lo stato del documento che arriva nel corpo.

document.pdf_application_failed è quello da non ignorare: significa che qualcuno ha firmato ma la firma non è entrata nel file. In AssinaJá compare come Problema tecnico nel dettaglio del documento, con Riprova — veda Seguire e gestire i documenti.

L’intestazione Idempotency-Key serve al suo sistema per scartare le ripetizioni, ma non ha un formato unico. Dipende da dove va l’evento e da quale evento è:

Destinazione Evento Chiave
Indirizzo del documento (webhookUrl) qualsiasi, tranne recipient.signed {documentPublicId}:{event}
Indirizzo del documento recipient.signed {documentPublicId}:{event}:{recipientId}
Indirizzo dell’organizzazione qualsiasi, tranne recipient.signed {documentPublicId}:{event}:org
Indirizzo dell’organizzazione recipient.signed {documentPublicId}:{event}:{recipientId}:org

Conservi e confronti la chiave intera, come un testo opaco. Non la spezzi. Se ha un vincolo di unicità su (documento, evento) nel suo database, rifiuterà consegne legittime: recipient.signed arriva una volta per firmatario, e un documento con un indirizzo proprio in un’organizzazione che ha anch’essa un indirizzo configurato produce due consegne dello stesso evento, con chiavi diverse.

Il segreto è ciò che Le permette di essere certo che la richiesta provenga davvero da AssinaJá. Si trova in Impostazioni → Sviluppatori, nella scheda Webhook, nel riquadro Segreto del webhook. Lo vede solo il Proprietario dell’organizzazione.

Segreto del webhook:

Il segreto serve a verificare la firma degli eventi inviati al suo webhook.

Usi Genera segreto la prima volta, e Copia per conservarlo. Da quel momento il riquadro mostra il segreto nascosto, con Copia e Ruota. Non lasci la pagina senza averlo salvato:

Salvi questo valore adesso — non verrà più mostrato.

Ruota genera un nuovo segreto senza interrompere le consegne:

Vuole davvero ruotare il segreto? Il segreto precedente resterà valido per 24 ore.

Durante quelle 24 ore — “Segreto precedente valido per altre 24 h.” — le richieste vengono firmate con entrambi i segreti, separati da una virgola nella stessa intestazione. Per questo la verifica deve accettare un elenco, e non un valore unico. Trascorso quel periodo, viene usato solo quello nuovo.

Ogni richiesta contiene queste intestazioni:

Intestazione Che cos’è
X-AssinaJa-Signature La firma, v1=<hex>, o più firme separate da virgola durante una rotazione
X-AssinaJa-Event Il nome dell’evento
X-AssinaJa-Delivery Un identificativo nuovo a ogni tentativo — non serve a scartare le ripetizioni
X-AssinaJa-Timestamp L’ora, in secondi Unix
Idempotency-Key Veda la tabella sopra — quattro formati possibili

La firma è un HMAC-SHA256 calcolato sull’ora e sul corpo della richiesta uniti da un punto — {timestamp}.{corpo} — in esadecimale minuscolo e con il prefisso v1=.

La chiave non è il segreto così come l’ha copiato. Il segreto è codificato in base64url; la chiave dell’HMAC sono i byte che si ottengono decodificandolo. Passare il testo direttamente alla funzione HMAC produce una firma che non corrisponde mai — è la causa più comune di verifica fallita.

const crypto = require('crypto');
function verifyWebhookSignature(secret, timestamp, body, signatureHeader) {
const message = `${timestamp}.${body}`;
// o segredo é base64url — a chave são os bytes descodificados, não o texto
const secretBytes = Buffer.from(secret, 'base64url');
const expected = 'v1=' + crypto
.createHmac('sha256', secretBytes)
.update(message)
.digest('hex');
// durante uma rotação vêm as duas assinaturas
const signatures = signatureHeader.split(',').map(s => s.trim());
return signatures.some(sig => sig === expected);
}

Usi il corpo così come è arrivato, grezzo. Se lo passa a un parser JSON e lo riserializza, i byte cambiano e la firma non corrisponde più.

Che cosa risponde Che cosa succede
2xx Consegnata. Nessun nuovo tentativo. Il corpo della risposta non deve superare 4 KB.
3xx Ritenta — i reindirizzamenti non vengono seguiti.
4xx Ritenta, come per un 5xx.
5xx Ritenta.
Nessuna risposta entro 10 secondi Ritenta.

Solo una risposta 2xx conta come consegnata. Non esiste alcun codice che faccia desistere di proposito la piattaforma: se vuole che una consegna si fermi, risponda 2xx e scarti il contenuto dal suo lato.

I tentativi sono distanziati di 1 min, 2 min, 5 min, 15 min, 30 min, 60 min e 60 min. Sono otto in tutto, e l’ottavo è una consegna vera e propria — solo quando anche quest’ultimo fallisce la consegna viene contrassegnata come non riuscita.

Il dettaglio di ogni documento mostra l’ultima consegna di quel documento, qualunque sia l’evento, nel riquadro Integrazione — con Webhook (il nome dell’evento), Stato, Tentativi, Consegnato il e, se non è riuscita, l’Errore. È il punto più rapido per distinguere “AssinaJá non ha inviato” da “il mio server non ha accettato”. In questo riquadro non c’è un pulsante per reinviare.

Per vedere lo storico completo dell’organizzazione e reinviare le consegne non riuscite, vada in Impostazioni → Sviluppatori → Webhook, alla sezione Consegne, sotto l’indirizzo e il segreto:

Ogni evento inviato, con la risposta del suo indirizzo. Le consegne non riuscite possono essere reinviate.

Ogni riga ha Evento, Indirizzo, Stato (Consegnata o Non riuscita), Tentativi, Data e Ultimo errore; quelle non riuscite hanno Reinvia, che risponde “Consegna reinviata. L’indirizzo ha risposto {codice}.” Solo il Proprietario dell’organizzazione ha accesso a questa schermata.

Quando il reinvio non va a buon fine, la schermata dice perché:

Questa consegna non esiste più.

Questa consegna è già stata ricevuta — si reinviano solo quelle non riuscite.

Al momento non è possibile reinviare questa consegna.