// Boostigo webhook receiver (Express). npm i express — then: BOOSTIGO_WEBHOOK_SECRET=whsec_... node webhook.js // 1) keep the RAW body 2) verify HMAC + timestamp 3) de-duplicate on X-Boostigo-Delivery 4) process 5) respond 200 fast. import express from "express"; import { verifyBoostigoSignature } from "./webhook-signature.js"; const app = express(); const SECRET = process.env.BOOSTIGO_WEBHOOK_SECRET || "whsec_YOUR_SECRET"; // API key -> Callback Secret in the Client Dashboard const seen = new Set(); // replace with your database in production app.post("/api/boostigo/webhook", express.raw({ type: "application/json" }), (req, res) => { const raw = req.body.toString("utf8"); // RAW body — do not JSON.parse before verifying const ok = verifyBoostigoSignature(SECRET, req.header("X-Boostigo-Timestamp") || "", raw, req.header("X-Boostigo-Signature") || ""); if (!ok) return res.status(401).json({ received: false, error: "invalid signature" }); const deliveryId = req.header("X-Boostigo-Delivery") || ""; if (seen.has(deliveryId)) return res.status(200).json({ received: true }); // duplicate redelivery seen.add(deliveryId); const event = JSON.parse(raw); const order = event.data; switch (event.event) { case "order.success": // mark order (order.request_id / order.order_id) as delivered: order.diamond diamonds break; case "order.failed": case "order.cancelled": // mark as failed; amount refunded to your API key; order.error.code === "RECHARGE_FAILED" break; case "order.processing": case "order.delayed": break; // optional progress updates default: break; // unknown/new events: ignore gracefully } res.status(200).json({ received: true }); }); app.listen(3000, () => console.log("Webhook receiver on :3000"));