Cosa sono le webhook firmate di Payora
Le webhook firmate di Payora sono richieste HTTP che includono una firma digitale. In questo modo, il tuo endpoint PHP può verificare che l’evento provenga davvero da Payora e che non sia stato manomesso durante il trasferimento. Se stai imparando a verificare le webhook firmate di Payora in PHP, il flusso di base è semplice: Payora invia un evento, il tuo server legge il payload originale e il codice ne verifica la firma prima di fidarsi dei dati contenuti nel corpo della richiesta.
Questa verifica è importante perché una webhook può arrivare da qualsiasi client che conosca il tuo URL. Un malintenzionato potrebbe ricavare l’endpoint dai log e poi inviare con una richiesta POST un evento di pagamento falso, accompagnato da un JSON ben formattato. La firma impedisce questo tipo di attacco.
L’evento è utile solo dopo la verifica. Prima, è soltanto testo.
Pensala come un biglietto numerato all’ingresso. Il corpo è il messaggio, la firma è il timbro e il codice PHP decide se i due elementi corrispondono. Se sì, elabori l’evento. Altrimenti, lo rifiuti subito.
Se sul tuo sito gestisci già i pagamenti, lo stesso principio si applica anche ad altre parti dell’infrastruttura. Chi legge una guida ai gateway di pagamento in criptovalute per l’e-commerce troverà lo stesso approccio: accettare meno, verificare di più e aggiornare l’ordine solo dopo i controlli.
Requisiti per un endpoint webhook in PHP
Non ti serve un framework complesso. È sufficiente un endpoint con PHP 8.x; per alcuni progetti può andare bene anche PHP 7.4. Il codice deve però poter accedere al corpo originale della richiesta e alle intestazioni inviate da Payora. La configurazione del server deve quindi consentire il normale accesso alle richieste HTTP, senza livelli personalizzati che riscrivano o eliminino le intestazioni.
Usa HTTPS. Senza TLS, la webhook viaggia in chiaro e la firma da sola non risolve i problemi di sicurezza del trasporto. Un certificato, una configurazione corretta dell’host virtuale e un URL pubblico raggiungibile sono requisiti fondamentali: sono i primi passi per configurare endpoint webhook Payora sicuro.
In pratica, servono due estensioni o funzionalità di PHP: Hash per il calcolo HMAC e, se gestisci i dati in formato JSON, le funzioni JSON incluse in PHP. Potrebbe esserti utile anche cURL per eseguire test dal tuo lato, ma l’endpoint webhook non ne ha bisogno.
Ti serve inoltre il segreto o la chiave di firma di Payora associata alla configurazione della webhook nel tuo account Payora. Tienila fuori dalla directory pubblica del sito e non inserirla in Git. Un segreto in un repository pubblico trasforma rapidamente la verifica in una messinscena.
Un’altra cosa: l’endpoint dovrebbe accettare solo richieste POST. Per le richieste GET puoi rispondere con 405. È una piccola precauzione che semplifica la diagnosi dei problemi, perché riduce il traffico da esaminare.
Acquisire il payload originale della webhook e le intestazioni
La verifica della firma dipende dagli esatti byte inviati da Payora. In PHP, leggi il corpo originale della richiesta con file_get_contents('php://input'). Non ricostruire il payload a partire da $_POST o dal JSON decodificato: entrambi i passaggi possono modificare spazi, ordine delle chiavi o codifica.
La stessa regola vale per le intestazioni. Ti serve l’intestazione della firma. Se disponibile, usa getallheaders(); in caso contrario, se il tuo ambiente non fornisce questa funzione, leggi le variabili del server, come $_SERVER['HTTP_X_...']. Le differenze tra ambienti di hosting possono fare la differenza.
Immagina un corpo webhook di 412 byte. Se il codice lo decodifica e poi lo codifica di nuovo, i campi potrebbero sembrare identici, ma i byte non lo saranno più. Basta questa differenza per impedire la verifica.
Ricorda questa regola: prima acquisisci, poi analizza. Salva innanzitutto la stringa originale, quindi controlla le intestazioni. Solo a quel punto dovresti intervenire sulla struttura del payload. Per come verificare una webhook Payora in PHP, preservare il corpo grezzo è quindi un passaggio essenziale.
Seguire questa regola fa risparmiare tempo anche quando provi i pagamenti prima del lancio. L’articolo su come testare un pagamento in criptovalute applica lo stesso principio agli eventi di sandbox, dove preservare fedelmente il payload è essenziale per rendere utile il test.
Ricreare la firma attesa in PHP
In genere, si calcola un HMAC usando il payload originale e un segreto condiviso. Parti dall’algoritmo indicato nella documentazione delle webhook di Payora. Se la documentazione specifica SHA-256, usa SHA-256. Se indica un prefisso, un tag di versione o un formato per il timestamp, riproduci esattamente quella struttura: è il punto centrale della verifica firma webhook HMAC PHP.
Una struttura comune consiste nel creare il messaggio da firmare con il timestamp e il corpo originale, quindi usare hash_hmac() con il segreto condiviso e l’algoritmo di hash indicato. A seconda delle specifiche, il risultato potrebbe dover essere codificato in esadecimale o in base64. Non tirare a indovinare: controlla le impostazioni della webhook.
Ecco un esempio essenziale in stile PHP, con segnaposto nei punti in cui il formato di Payora potrebbe essere diverso:
$rawBody = file_get_contents('php://input');
$timestamp = $_SERVER['HTTP_X_PAYORA_TIMESTAMP'] ?? '';
$signature = $_SERVER['HTTP_X_PAYORA_SIGNATURE'] ?? '';
$secret = getenv('PAYORA_WEBHOOK_SECRET');
$signedPayload = $timestamp . '.' . $rawBody;
$expected = hash_hmac('sha256', $signedPayload, $secret);L’esempio mostra solo una possibile struttura, non garantisce che Payora usi proprio questo formato. Se Payora firma solo il payload, elimina il timestamp dalla stringa. Se firma una versione JSON canonica, segui quel metodo alla lettera, senza sostituirlo con quello che preferisci. Basta un delimitatore sbagliato per far fallire tutte le richieste.
Per i commercianti che vogliono gestire anche le regole di fatturazione e i casi particolari, l’articolo sui limiti delle fatture per i pagamenti in criptovalute è un utile approfondimento: la gestione delle webhook e le regole delle fatture spesso si intrecciano nello stesso ciclo di vita dell’ordine.
Confrontare la firma calcolata con quella di Payora
Una volta calcolata la firma attesa, confrontala con quella ricevuta usando un confronto a tempo costante. Nella maggior parte dei casi, in PHP significa usare hash_equals(). I semplici confronti == o === non sono adatti: possono rivelare informazioni tramite i tempi di esecuzione e sono meno efficaci nel gestire differenze sottili.
Prima del confronto, normalizza il formato esattamente come previsto da Payora. Se l’intestazione contiene un valore esadecimale, confronta valori esadecimali. Se contiene un valore base64, confronta valori base64. Se la firma ricevuta include un prefisso come sha256=, rimuovilo o includilo esattamente come indicato nella documentazione.
Flusso di esempio:
- Leggi il corpo originale della richiesta.
- Leggi l’intestazione della firma.
- Calcola la firma attesa seguendo la formula documentata.
- Confronta le due stringhe con
hash_equals(). - Se non corrispondono, rifiuta la richiesta con un codice 401 o 400.
Il codice 401 è appropriato se la firma non è corretta. Il codice 400 va bene se mancano intestazioni obbligatorie. In entrambi i casi, la risposta dovrebbe essere breve: niente dettagli aggiuntivi.
Qui basta una frase: non stampare mai il segreto. È un errore raro, ma catastrofico.
Gestire timestamp, protezione dai replay e finestre di tolleranza
Se Payora include un timestamp o un nonce, controllalo prima di accettare l’evento. Così si bloccano gli attacchi di replay, in cui un malintenzionato invia di nuovo una webhook valida in un secondo momento per indurre l’app a effettuare un doppio pagamento o una doppia spedizione. La finestra di validità del timestamp deve seguire le regole di Payora, non le tue supposizioni.
Di solito si confronta il timestamp della webhook con l’ora del server e si rifiutano le richieste scadute che superano la finestra di tolleranza. Se la documentazione indica 5 minuti, usa 5 minuti. Se indica 300 secondi, imposta un valore nominato di 300 secondi invece di inserire un numero incomprensibile a mano in tre file.
Un disallineamento dell’orologio può far rifiutare richieste valide. Un server in ritardo di 7 minuti potrebbe respingere una richiesta corretta. Sincronizza i server con NTP e mantieni coerente il fuso orario. Il fuso orario non modifica i timestamp Unix, ma impostazioni locali errate possono comunque rendere più difficile leggere i log.
Quando si usano i nonce, la gestione è ancora più semplice: salva ciascun nonce una sola volta, contrassegnalo come utilizzato e rifiuta i duplicati. Può bastare una piccola cache o una tabella nel database. Un nonce, una sola accettazione.
Se nelle pagine di pagamento accetti anche prezzi fissi, è importante definire le regole. L’articolo su quando usare un prezzo fisso può aiutarti a coordinare le regole sul tasso di cambio con le tempistiche delle webhook, evitando di confermare un importo errato dopo un evento arrivato in ritardo.
Elaborare gli eventi validi e restituire la risposta HTTP corretta
Dopo aver verificato la firma, analizza il payload e gestisci l’evento in base al suo tipo. Un evento payment.succeeded non dovrebbe seguire lo stesso percorso di un evento refund.updated. Tienili separati: ogni gestore svolgerà così una sola funzione e i log saranno più leggibili.
La logica applicativa dovrebbe essere eseguita prima di inviare una risposta 2xx. Se contrassegni un ordine come pagato, aggiorna prima il database. Se devi mettere in coda un’email, aggiungila prima alla coda. Se uno dei due passaggi fallisce, restituisci un errore 500 e lascia che Payora riprovi più tardi.
Quest’ordine è importante perché una risposta 2xx comunica in genere a Payora che l’evento è stato accettato. Se restituisci un 200 troppo presto e poi si verifica un errore durante la scrittura nel database, potresti creare una discrepanza tra Payora e la tua app. Un problema del genere può costare caro alle due di notte.
Basta un corpo di risposta breve: “OK” va bene. Meglio ancora, non restituire alcun corpo e mantieni chiaro il codice di stato. Non rimandare indietro il payload.
Per i team che generano anche fatture ai clienti in base agli eventi di pagamento, l’articolo sul gateway di pagamento in criptovalute per freelance mostra come trasformare una webhook da evento tecnico a operazione di fatturazione concreta, senza passaggi superflui.
Risolvere i problemi di verifica della firma
La maggior parte degli errori dipende da cinque cause: il corpo originale è stato modificato, il nome dell’intestazione è sbagliato, il segreto non è corretto, la codifica non corrisponde oppure il timestamp è fuori dalla finestra di tolleranza. Inizia dal corpo. Se hai registrato il payload originale e la firma calcolata, confrontali prima di intervenire sul database.
Le modifiche al corpo sono frequenti. I middleware dei framework possono eliminare spazi, decodificare il JSON o uniformare i fine riga. Basta un carattere di nuova linea in più. Se Payora ha firmato {"a":1} ma l’app legge {"a":1}\n, l’HMAC non corrisponderà.
Il problema successivo da controllare è l’intestazione. Alcuni server convertono i trattini in trattini bassi. Alcuni proxy rimuovono le intestazioni personalizzate se non vengono autorizzate esplicitamente. Se in PHP non trovi l’intestazione della firma, controlla la configurazione del server web e del proxy, non solo il codice.
I problemi di codifica sono difficili da individuare. UTF-8 e i caratteri Unicode con escape possono sembrare corretti nei log e produrre comunque byte diversi. Se l’applicazione riscrive il JSON, la firma potrebbe non corrispondere anche se il payload sembra identico nel browser.
Un segreto errato è la causa più semplice, ma anche quella che spesso si controlla per ultima. Verifica separatamente la variabile d’ambiente, il segreto di staging e quello di produzione. Usare per sbaglio il segreto di un altro account può farti perdere un pomeriggio.
Un disallineamento dell’orologio dà un sintomo diverso: la firma corrisponde, ma la richiesta viene comunque rifiutata perché il timestamp è troppo vecchio. In tal caso, controlla NTP, gli orologi dei container e gli eventuali proxy inversi che impostano un proprio orario. Anche un piccolo disallineamento dell’infrastruttura può sembrare un errore di firma.
Se la tua installazione è integrata anche con WordPress o con un sistema di abbonamenti, l’articolo su come accettare pagamenti in USDT è utile perché mostra come collegare gestione delle webhook, controllo degli accessi e conferma del pagamento in un unico flusso.
Un ultimo test può essere molto utile: invia due volte lo stesso payload. La prima richiesta dovrebbe essere accettata. La seconda dovrebbe essere rifiutata se memorizzi e blocchi i nonce già utilizzati; dovrebbe invece essere accettata solo se la tua webhook non usa una protezione dai replay basata sui nonce. Questa richiesta duplicata ti permette di verificare se le protezioni funzionano davvero.




Comments