Webhooks
Der Tab Webhooks von /nay (Scope nay.admin) sendet Ereignisse der Skripte an deine URLs. Wähle die Ereignisse aus (oder alle), drücke Testen, um die Einrichtung zu prüfen, und sieh dir die letzte Antwort jedes Webhooks an.
Es gibt zwei Typen:
- Discord: Füge die Webhook-URL eines Discord-Kanals ein (
https://discord.com/api/webhooks/...). Jedes Ereignis wird zu einem Embed, mit Titel und Beschriftungen in der Serversprache und den Feldern des Ereignisses in ihrer Reihenfolge. Discord-Markdown in Werten wird maskiert, niemand wird erwähnt, und lange Nachrichten werden auf das Limit von 6000 Zeichen gekürzt. - Signiertes JSON: für deine eigene Website oder deinen Bot. Jeder Webhook bekommt ein Geheimnis, das beim Erstellen oder Neugenerieren angezeigt wird.
Zustellungen
Eine Zustellung ist ein POST mit JSON:
{ "id": "3f9c2a1b7d4e8f60", "event": "nay_car_wash.wash", "resource": "nay_car_wash", "time": 1791670794, "data": { "player": "John", "price": 150 } }Header: X-Nay-Event, X-Nay-Delivery (gleich id), X-Nay-Timestamp (Unix-Sekunden) und X-Nay-Signature: sha256=<hex>.
- Antworte mit einem beliebigen 2xx-Status. Keine Antwort innerhalb von 15 Sekunden zählt als Netzwerkfehler.
- Netzwerkfehler sowie 5xx- und 429-Antworten werden nach 1, 10 und 60 Sekunden mit demselben
X-Nay-Deliveryerneut gesendet. Andere 4xx-Antworten werden nicht wiederholt. - Nach 20 fehlgeschlagenen Zustellungen in Folge wird der Webhook deaktiviert. Aktiviere ihn im Tab wieder oder speichere ihn mit einer neuen URL.
- Discord-Zustellungen werden nicht signiert und halten sich bei einem Rate Limit an Discords
retry_after.
Ereignisse
Ereignisse von nay_lib:
| Ereignis | Wann | Daten |
|---|---|---|
nay.setting | Eine Einstellung wird geändert oder zurückgesetzt. | resource, key, action, actor |
nay.permission | Eine Berechtigungsregel wird erteilt oder entzogen. | action, type, identifier, scope, actor |
nay.token | Ein API-Token wird erstellt oder widerrufen. | action, id, label, actor |
nay.test | Die Schaltfläche Testen. | message |
Jedes Skript listet seine eigenen Ereignisse auf seiner Seite, zum Beispiel Car Wash.
Die Signatur prüfen
Bevor du einer signierten Zustellung vertraust, prüfe ihre Signatur: HMAC-SHA256 von <X-Nay-Timestamp>.<raw body>, mit dem Geheimnis genau so als Schlüssel, wie es angezeigt wird (der Hex-Text selbst). Lehne alte Zeitstempel ab.
Node.js (Express):
import { createHmac, timingSafeEqual } from "node:crypto";
import express from "express";
const app = express();
app.post("/nayretis", express.raw({ type: "application/json" }), (req, res) => {
const timestamp = req.get("X-Nay-Timestamp") ?? "";
const expected = "sha256=" + createHmac("sha256", process.env.NAY_WEBHOOK_SECRET).update(`${timestamp}.${req.body}`).digest("hex");
const given = req.get("X-Nay-Signature") ?? "";
const valid = given.length === expected.length && timingSafeEqual(Buffer.from(given), Buffer.from(expected));
if (!valid || Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) {
return res.sendStatus(401);
}
const delivery = JSON.parse(req.body);
res.sendStatus(204);
});PHP:
<?php
$body = file_get_contents('php://input');
$timestamp = $_SERVER['HTTP_X_NAY_TIMESTAMP'] ?? '';
$expected = 'sha256=' . hash_hmac('sha256', $timestamp . '.' . $body, getenv('NAY_WEBHOOK_SECRET'));
if (!hash_equals($expected, $_SERVER['HTTP_X_NAY_SIGNATURE'] ?? '') || abs(time() - (int) $timestamp) > 300) {
http_response_code(401);
exit;
}
$delivery = json_decode($body, true);
http_response_code(204);