Race-Nation-Shopify-Backend/routes/privacyLawWebhooks.js
2026-04-13 17:31:26 +05:30

57 lines
1.6 KiB
JavaScript

require("dotenv").config();
const express = require("express");
const crypto = require("crypto");
const router = express.Router();
router.use(express.raw({ type: "*/*" }));
const SHOPIFY_API_SECRET = process.env.SHOPIFY_API_SECRET;
function verifyHmac(rawBody, hmacHeader) {
if (!SHOPIFY_API_SECRET || !hmacHeader || !rawBody) {
return false;
}
const digest = crypto
.createHmac("sha256", SHOPIFY_API_SECRET)
.update(rawBody)
.digest("base64");
const generated = Buffer.from(digest, "utf8");
const received = Buffer.from(hmacHeader, "utf8");
if (generated.length !== received.length) {
return false;
}
return crypto.timingSafeEqual(generated, received);
}
function parseJsonSafe(buf) {
try {
return JSON.parse(buf.toString("utf8"));
} catch {
return null;
}
}
function handleWebhook(req, res, topicName) {
const hmacHeader = req.header("x-shopify-hmac-sha256");
const shop = req.header("x-shopify-shop-domain");
const topic = req.header("x-shopify-topic") || topicName;
if (!verifyHmac(req.body, hmacHeader)) {
return res.status(401).send("Invalid HMAC");
}
const payload = parseJsonSafe(req.body) || {};
console.log(`[WEBHOOK:${topic}] shop=${shop}`, payload);
return res.status(200).json({ status: "ok", topic, shop, received: payload });
}
router.post("/customers/data_request", (req, res) => handleWebhook(req, res, "customers/data_request"));
router.post("/customers/redact", (req, res) => handleWebhook(req, res, "customers/redact"));
router.post("/shop/redact", (req, res) => handleWebhook(req, res, "shop/redact"));
module.exports = router;