Abone olduğun event'ler, imzalı POST olarak webhook endpoint'ine teslim edilir (asenkron, fire-and-forget). İmzayı doğrula, 2xx dön ve işle. 2xx dönmezsen Restomenum yeniden dener (retry).
Bir event oluşur (örn. packet.created)
│
▼
Restomenum ──imzalı POST──► https://<senin-origin>/webhook
│ header: X-Restomenum-Signature: t=..,v1=..
│ body: { id, type, version, tenantId, occurredAt, data }
▼
Senin /webhook:
1) imzayı doğrula (raw body) → 401 değilse
2) 200 dön (hızlıca)
3) işle (idempotent — id ile tekrarı yut)// /webhook — Restomenum event alıcısı (Node + Express)
// Ham gövde ŞART: imza ham byte'lar üzerinden doğrulanır (JSON.parse'tan ÖNCE).
import express from 'express';
import crypto from 'node:crypto';
const app = express();
const WEBHOOK_SECRET = process.env.RESTOMENUM_WEBHOOK_SECRET; // /connect exchange'inden geldi
// Bu route'ta JSON parser DEĞİL, raw body kullan:
app.post('/webhook', express.raw({ type: '*/*' }), (req, res) => {
const sig = req.header('X-Restomenum-Signature') || ''; // "t=1730..,v1=<hex>"
const parts = Object.fromEntries(sig.split(',').map((p) => p.split('=')));
const t = parts.t, v1 = parts.v1;
// 1) replay koruması: timestamp 5 dk toleransı
if (!t || Math.abs(Date.now() / 1000 - Number(t)) > 300) return res.sendStatus(401);
// 2) imza: HMAC_SHA256(secret, "<t>.<rawBody>")
const expected = crypto.createHmac('sha256', WEBHOOK_SECRET)
.update(`${t}.${req.body.toString('utf8')}`)
.digest('hex');
const ok = v1 && crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v1));
if (!ok) return res.sendStatus(401);
// 3) artık güvenli: parse et ve işle
const event = JSON.parse(req.body.toString('utf8'));
// event.type, event.data, event.tenantId ...
res.sendStatus(200); // 2xx dönmezsen Restomenum retry eder
});id retry'da tekrar gelebilir — bir kez işle.data için event kataloğu.app.installed / subscription.* / app.uninstalled da alır — type ile dallan (Lifecycle Webhook’ları).events:subscribe scope'u ve events[] listesi gerekir. Geliştirme sırasında portaldaki “Test Event” aracıyla webhook'una sandbox payload gönderebilirsin.