Overenie a testovanie
Overte pôvodné telo požiadavky, spracujte duplicity a bezpečne otestujte svoj prijímač.
Pred použitím payloadu overte každý webhook a potom odošlite test, ktorým potvrdíte, že váš prijímač funguje od začiatku do konca.
Skôr ako začnete
- Uložená cieľová adresa a jej signing secret (podpisový kľúč)
twhsec_.... Na overovanie webhookov nepoužívajte svoj Server Secret Token. - Cesta prijímača, ktorá dokáže načítať pôvodné telo požiadavky skôr, než ho zmení akýkoľvek parser JSON.
- Úložisko s obmedzením jedinečnosti na
idudalosti, aby boli duplicity bezpečné.
Prijmite webhook
Načítajte pôvodné telo
Tapaya odosiela JSON POST s týmito hlavičkami. Telo ponechajte ako pôvodné bajty; rozparsované a znova serializované telo už nezodpovedá podpisu.
Content-Type: application/json
X-Tapaya-Event-Id: 019a0000-0000-7000-8000-000000000001
X-Tapaya-Signature: t=1793361600,v1=<lowercase hexadecimal HMAC-SHA256>- V Express použite pre túto cestu
express.raw({ type: "application/json" })pred globálnym parserom JSON.
Skontrolujte podpis
Vypočítajte HMAC-SHA256 z časovej pečiatky, bodky a pôvodného tela a potom ho porovnajte s v1 v konštantnom čase.
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"));
}- Celý kľúč
twhsec_...použite ako kľúč v UTF-8. Nedekódujte ho a neodstraňujte z neho prefix. - Odmietnite časové pečiatky, ktoré sa od vašich hodín líšia o viac než päť minút, a udržiavajte hodiny synchronizované.
- Počas rotácie signing secret najskôr skúste nový kľúč, potom starý, kým sa front nevyprázdni.
Uložte a potvrďte
Udalosť prijmite až po jej bezpečnom uložení, aby chyba na vašej strane vyvolala opakovaný pokus.
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);
},
);- Pre udalosť, ktorú ste už uložili, vráťte
2xx. Opakované pokusy zachovávajú rovnakéida telo, ale majú novú časovú pečiatku a podpis. - Ak novú udalosť nemôžete uložiť, vráťte odpoveď mimo
2xx, aby doručovanie pokus zopakovalo. - Uložené udalosti spracúvajte z vlastného frontu. Poradie doručenia nie je zaručené, preto staršie snímky odsúhlaste s aktuálnym stavom.
Odošlite testovací webhook
Testovacia akcia v Platform odošle jednu podpísanú požiadavku webhook.test na uloženú URL. Funguje aj vtedy, keď sú webhooky vypnuté alebo typ nie je vo vašom odbere, a nevytvára žiadnu platbu, refundáciu ani obchodníka.
- Otvorte stránku API Keys svojej organizácie a uložte cieľovú adresu.
- Použite testovaciu akciu webhooku.
- Skontrolujte výsledok, trvanie a odoslaný JSON zobrazené v 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."
}
}Lokálne a automatizačné prijímače
Ak váš produkčný server ešte nie je pripravený, nasmerujte webhook na vývojársky počítač alebo na no-code nástroj.
Riešenie chýb
Typy udalostí
Vyberte zmeny platieb, refundácií, obchodníkov a onboardingu, ktoré vaša integrácia potrebuje.
Prehľad
Prijímajte platby kartou všade, kde sa vaši obchodníci stretávajú so zákazníkmi, od pokladne v obchode cez stôl v reštaurácii až po nabíjačku elektromobilov, na telefónoch a tabletoch, ktoré už používajú.