如何使用 nodejs 验证 shopify webhook api

How to validate the shopify webhook api using nodejs

我无法使用 "shopify-node-api" 验证来自 shopify 的 webhook 响应。我正在使用以下代码来验证签名。

下面的代码是app.js

app.use(bodyParser.json({
type:'application/json',
limit: '50mb',
verify: function(req, res, buf, encoding) {
     if (req.url.startsWith('/webhook')){
         req.rawbody = buf;
     }
   }
 })
);
app.use("/webhook", webhookRouter);

下方 webhook.router.js

router.post('/orders/create', verifyWebhook, async (req, res) => {    
    console.log(' We got an order')
    res.sendStatus(200)
 });

下面为验证函数

function verifyWebhook(req, res, next) {
  let hmac;
  let data;
  try {
    hmac = req.get("X-Shopify-Hmac-SHA256");
    data = req.rawbody;
  } catch (e) {
    console.log(`Webhook request failed from: ${req.get("X-Shopify-Shop-Domain")}`);
    res.sendStatus(200);
  }
  if (verifyHmac(JSON.stringify(data), hmac)) { // Problem Starting from Here
    req.topic = req.get("X-Shopify-Topic");
    req.shop = req.get("X-Shopify-Shop-Domain");
    return next();
  }

  return res.sendStatus(200);
}

验证签名功能

function verifyHmac(data, hmac) {
    if (!hmac) {
      return false;
    } else if (!data || typeof data.data !== "object") {
        // I am Getting Error HERE
        console.log('Error in data', data);
        return false;
    }
    const sharedSecret = config.shopify_shared_secret;
    const calculatedSignature = crypto
      .createHmac("sha256", sharedSecret)
      .update(Buffer.from(data), "utf8")
      .digest("base64");
      console.log('calculatedsecret', calculatedSignature);

    return calculatedSignature === hmac;
  };

我得到的正文是未定义的。建议我如何解决 shopify webhook 中的这个问题 API

而不是使用 bodyparser.json() 使用 bodyparser.raw 来获取所有有效负载来处理 shopify webhook 验证。

router.use(bodyparser.raw({ type: "application/json" }));

// Webhooks
router.post("/", async (req, res) => {
  console.log("Webhook heard!");
  // Verify
  const hmac = req.header("X-Shopify-Hmac-Sha256");
  const topic = req.header("X-Shopify-Topic");
  const shop = req.header("X-Shopify-Shop-Domain");

  const verified = verifyWebhook(req.body, hmac);

  if (!verified) {
    console.log("Failed to verify the incoming request.");
    res.status(401).send("Could not verify request.");
    return;
  }

  const data = req.body.toString();
  const payload = JSON.parse(data);
  console.log(
    `Verified webhook request. Shop: ${shop} Topic: ${topic} \n Payload: \n ${data}`
  );

  res.status(200).send("OK");
});

// Verify incoming webhook.
function verifyWebhook(payload, hmac) {
  const message = payload.toString();
  const genHash = crypto
    .createHmac("sha256", process.env.API_SECRET)
    .update(message)
    .digest("base64");
  console.log(genHash);
  return genHash === hmac;
}