Tapaya
PrehľadWebhookyOverenie a testovanie

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 id udalosti, 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.

verify-tapaya-webhook.mjs
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.

server.mjs
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é id a 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.

  1. Otvorte stránku API Keys svojej organizácie a uložte cieľovú adresu.
  2. Použite testovaciu akciu webhooku.
  3. 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

Chýba vám niečo na tejto stránke?Navrhnite funkciu. Pripojíme túto stránku, aby tím videl súvislosti.