Tapaya
ÜbersichtWebhooksVerifizieren und testen

Verifizieren und testen

Verifizieren Sie den ursprünglichen Anfrageinhalt, verarbeiten Sie Duplikate und testen Sie Ihren Empfänger sicher.

Verifizieren Sie jeden Webhook, bevor Sie seine Payload verwenden, und senden Sie dann einen Test, um zu bestätigen, dass Ihr Empfänger durchgängig funktioniert.

Vorbereitung

  • Ein gespeichertes Ziel und sein signing secret (Signaturschlüssel), twhsec_.... Verwenden Sie nicht Ihr Server Secret Token, um Webhooks zu verifizieren.
  • Eine Empfängerroute, die den ursprünglichen Anfrageinhalt lesen kann, bevor ein JSON-Parser ihn verändert.
  • Ein Speicher mit einer Eindeutigkeitsbedingung für die Ereignis-id, damit Duplikate unbedenklich sind.

Webhook empfangen

Ursprünglichen Inhalt lesen

Tapaya sendet einen JSON-POST mit diesen Headern. Behalten Sie den Inhalt als ursprüngliche Bytes bei; ein geparster und erneut serialisierter Inhalt stimmt nicht mehr mit der Signatur überein.

Content-Type: application/json
X-Tapaya-Event-Id: 019a0000-0000-7000-8000-000000000001
X-Tapaya-Signature: t=1793361600,v1=<lowercase hexadecimal HMAC-SHA256>
  • Verwenden Sie mit Express für diese Route express.raw({ type: "application/json" }) vor einem globalen JSON-Parser.

Signatur prüfen

Berechnen Sie HMAC-SHA256 über den Zeitstempel, einen Punkt und den ursprünglichen Inhalt, und vergleichen Sie das Ergebnis dann mit konstanter Laufzeit mit v1.

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"));
}
  • Verwenden Sie das vollständige Geheimnis twhsec_... als UTF-8-Schlüssel. Decodieren Sie es nicht und entfernen Sie sein Präfix nicht.
  • Weisen Sie Zeitstempel zurück, die mehr als fünf Minuten von Ihrer Uhrzeit abweichen, und halten Sie die Uhr synchronisiert.
  • Während Sie das signing secret rotieren, prüfen Sie zuerst das neue Secret und dann das alte, bis die Warteschlange abgearbeitet ist.

Speichern und bestätigen

Nehmen Sie das Ereignis erst an, wenn es sicher gespeichert ist, damit ein Fehler auf Ihrer Seite eine Wiederholung auslöst.

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);
  },
);
  • Geben Sie für ein bereits gespeichertes Ereignis 2xx zurück. Wiederholungen behalten dieselbe id und denselben Inhalt, mit neuem Zeitstempel und neuer Signatur.
  • Geben Sie eine Antwort außerhalb von 2xx zurück, wenn Sie ein neues Ereignis nicht speichern können, damit die Zustellung wiederholt wird.
  • Verarbeiten Sie gespeicherte Ereignisse aus Ihrer eigenen Warteschlange. Die Zustellreihenfolge ist nicht garantiert; gleichen Sie ältere Snapshots daher mit dem aktuellen Zustand ab.

Test-Webhook senden

Die Testaktion der Platform sendet eine signierte Anfrage webhook.test an die gespeicherte URL. Sie funktioniert auch, wenn Webhooks deaktiviert sind oder der Typ nicht in Ihrem Abonnement enthalten ist, und erstellt weder eine Zahlung noch eine Erstattung noch einen Händler.

  1. Öffnen Sie API Keys für Ihre Organisation und speichern Sie das Ziel.
  2. Verwenden Sie die Webhook-Testaktion.
  3. Prüfen Sie das Ergebnis, die Dauer und das gesendete JSON, die in der Platform angezeigt werden.
{
  "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."
  }
}

Lokale und Automatisierungsempfänger

Richten Sie einen Webhook auf einen Entwicklungsrechner oder ein No-Code-Tool, wenn Ihr Produktionsserver noch nicht bereit ist.

Fehler behandeln

Fehlt Ihnen etwas auf dieser Seite?Wünschen Sie sich eine Funktion. Wir hängen diese Seite an, damit das Team den Kontext sieht.