Verifica e test
Verifichi il corpo originale della richiesta, gestisca i duplicati e testi il ricevitore in modo sicuro.
Verifichi ogni webhook prima di utilizzarne il payload, quindi invii un test per confermare che il ricevitore funzioni dall'inizio alla fine.
Prima di iniziare
- Una destinazione salvata e il relativo signing secret (chiave di firma),
twhsec_.... Non utilizzi il Server Secret Token per verificare i webhook. - Una route del ricevitore in grado di leggere il corpo originale della richiesta prima che un parser JSON lo modifichi.
- Un archivio con un vincolo di unicità sull'
iddell'evento, così che i duplicati siano gestiti in modo sicuro.
Ricevere un webhook
Leggere il corpo originale
Tapaya invia una richiesta POST JSON con questi header. Mantenga il corpo come byte originali; un corpo sottoposto a parsing e serializzato di nuovo non corrisponde più alla firma.
Content-Type: application/json
X-Tapaya-Event-Id: 019a0000-0000-7000-8000-000000000001
X-Tapaya-Signature: t=1793361600,v1=<lowercase hexadecimal HMAC-SHA256>- Con Express, utilizzi
express.raw({ type: "application/json" })per questa route, prima di un parser JSON globale.
Controllare la firma
Calcoli HMAC-SHA256 sul timestamp, un punto e il corpo originale, quindi lo confronti con v1 tramite un confronto a tempo costante.
import { createHmac, timingSafeEqual } from "node:crypto";
export function verifyTapayaWebhook(rawBody, signatureHeader, secret, now = Date.now()) {
if (!Buffer.isBuffer(rawBody) || typeof signatureHeader !== "string") {
throw new Error("Missing raw body or signature");
}
if (typeof secret !== "string" || !secret.startsWith("twhsec_")) {
throw new Error("Missing signing secret");
}
const match = /^t=(\d+),v1=([0-9a-f]{64})$/.exec(signatureHeader);
if (!match) throw new Error("Malformed signature");
const timestamp = Number(match[1]);
if (!Number.isSafeInteger(timestamp) || Math.abs(now / 1000 - timestamp) > 300) {
throw new Error("Expired signature");
}
const expected = createHmac("sha256", Buffer.from(secret, "utf8"))
.update(`${match[1]}.`, "utf8")
.update(rawBody)
.digest();
const received = Buffer.from(match[2], "hex");
if (!timingSafeEqual(expected, received)) throw new Error("Invalid signature");
return JSON.parse(rawBody.toString("utf8"));
}- Utilizzi il segreto completo
twhsec_...come chiave UTF-8. Non lo decodifichi e non ne rimuova il prefisso. - Rifiuti i timestamp che differiscono di oltre cinque minuti dal Suo orologio e mantenga l'orologio sincronizzato.
- Durante la rotazione del signing secret, provi prima il nuovo segreto, poi quello precedente, finché la coda non si è svuotata.
Memorizzare e confermare
Accetti l'evento solo dopo averlo memorizzato in modo sicuro, così che un errore da parte Sua generi un nuovo tentativo.
import express from "express";
import { verifyTapayaWebhook } from "./verify-tapaya-webhook.mjs";
import { saveEventOnce } from "./events.mjs"; // your store, unique on event id
const app = express();
app.post(
"/webhooks/tapaya",
express.raw({ type: "application/json" }),
async (req, res) => {
let event;
try {
event = verifyTapayaWebhook(
req.body,
req.get("X-Tapaya-Signature"),
process.env.TAPAYA_WEBHOOK_SECRET,
);
} catch {
return res.sendStatus(400);
}
if (event.organizationId !== process.env.TAPAYA_ORGANIZATION_ID) {
return res.sendStatus(400);
}
await saveEventOnce(event); // skips an id it already stored
res.sendStatus(204);
},
);- Restituisca
2xxper un evento già memorizzato. I tentativi successivi mantengono lo stessoide lo stesso corpo, con un timestamp e una firma nuovi. - Restituisca una risposta diversa da
2xxquando non può memorizzare un nuovo evento, così che la consegna riprovi. - Elabori gli eventi memorizzati dalla Sua coda. L'ordine di consegna non è garantito, quindi riconcili le istantanee meno recenti con lo stato corrente.
Inviare un webhook di test
L'azione di test della Platform invia una richiesta webhook.test firmata all'URL salvato. Funziona anche se i webhook sono disabilitati o il tipo non è incluso nella Sua iscrizione, e non crea alcun pagamento, rimborso o esercente.
- Apra API Keys per la Sua organizzazione e salvi la destinazione.
- Utilizzi l'azione di test del webhook.
- Controlli il risultato, la durata e il JSON inviato mostrati nella Platform.
{
"id": "019a0000-0000-7000-8000-000000000010",
"type": "webhook.test",
"apiVersion": "1",
"organizationId": "019a0000-0000-7000-8000-000000000002",
"merchantId": null,
"createdAt": "2026-10-30T12:00:00.000000Z",
"test": true,
"data": {
"message": "This is a test webhook from Tapaya. No payment was created."
}
}Ricevitori locali e di automazione
Indirizzi un webhook verso una macchina di sviluppo o uno strumento no-code quando il Suo server di produzione non è ancora pronto.
Gestire gli errori
Tipi di evento
Scelga le modifiche a pagamenti, rimborsi, esercenti e onboarding necessarie alla Sua integrazione.
Panoramica
Accetti pagamenti con carta ovunque i Suoi esercenti incontrino i loro clienti, dal bancone del negozio al tavolo del ristorante fino alla colonnina di ricarica per veicoli elettrici, sugli smartphone e sui tablet che già utilizzano.