Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

236
Vistas
Encoding request body with HMAC sha256 and base64

How to encode a request body using HMAC sha 256 and base64.

The request object that i receives from xero webhook.

HEADER:
   "x-xero-signature" : HASH_VALUE
PAYLOAD:
  {
     "events": [],
     "lastEventSequence": 0,
     "firstEventSequence": 0,
     "entropy": "S0m3r4Nd0mt3xt"
  } 

The note from xero documentation says "If the payload is hashed using HMACSHA256 with your webhook signing key and base64 encoded, it should match the signature in the header. This is a correctly signed payload. If the signature does not match the hashed payload it is an incorrectly signed payload."

And I followed this example : https://devblog.xero.com/using-xero-webhooks-with-node-express-hapi-examples-7c607b423379

const express = require("express");
const router = express.Router();
const base64 = require('base-64');
const crypto = require('crypto')
const bodyParser = require('body-parser')
const xero_webhook_key = '00fRRlJBYiYN4ZGjmTtG+g/pulyb1Eru68YYL3PFoLsa78dadfQtGrOMuISuVBHxpXeEYo0Yy1Gc+hHMhDkSI/EEcgtrA==';

let options = {
    type: 'application/json'
  };
let itrBodyParser = bodyParser.raw(options);

router.post("/", itrBodyParser, async (req, res, next) =>{
//     console.log('::::WebhookPost:::');
const reSign = req.headers['x-xero-signature'];
 console.log(req.headers['x-xero-signature']);
 console.log('::::::::');
 console.log(req.body);
    console.log("Body: "+JSON.stringify(req.body))
    console.log(req.body.toString());
    console.log("Xero Signature: "+ reSign);
    console.log('Server key::::',xero_webhook_key);
    // Create our HMAC hash of the body, using our webhooks key
    let hmac = crypto.createHmac("sha256", xero_webhook_key).update(req.body.toString()).digest('base64');
    console.log("Resp Signature: ",hmac)

    if (req.headers['x-xero-signature'] == hmac) {
        res.statusCode = 200
    } else {
        res.statusCode = 401
    }
    console.log("Response Code: "+res.statusCode)
    return res.send();
 

});
over 4 years ago · Santiago Trujillo
2 Respuestas
Responde la pregunta

0

Hey I recently did a video on implementing webhooks with Xero, let me know if this gets you unstuck. I found that trying to pass itrBodyParser on the route the way you have wasn't working for me so I switched it with an app.use statement on my specific webhooks endpoint. If you prefer a written guide over video, here's the blog post

over 4 years ago · Santiago Trujillo Denunciar

0

I solved it using this solution.! I was using express framework and the request were not getting as raw request also .toString of didn't worked as mentioned in xero documentation.

 const server = http.createServer(async (req, resp) => {
  try {
      console.log(`::::Webhook::: ${webhookPort}`);
      console.log("::::x-xero-signature:::");
      console.log(req.headers["x-xero-signature"]);
      console.log(`--------------------------------------`);
      if (req.method === "POST") {
        if(req.headers["x-xero-signature"]){
          const rData = await new Promise((resolve, reject) => {
            return collectRequestData(req, (result) => {
                
                console.log(result);
                let hmac = crypto
                  .createHmac("sha256", xero_webhook_key)
                  .update(result)
                  .digest("base64");
                  console.log("Resp Signature: ", hmac);
                 
               
                return resolve({
                  hmac,result
                });
              });
          });
           console.log(">>Resp Signature: ", rData);
           console.log('>>x-xero-signature:::',req.headers["x-xero-signature"]);
           if(rData.result){
             const result = JSON.parse(rData.result);
             console.log('result:::',result);
             for(let { resourceId } of result.events) {
              console.log('::INVOICE ID = ',resourceId);
                getInvoiceData(resourceId);
             }
           }

           if(rData.hmac == req.headers["x-xero-signature"] ){
            console.log('::YES');
              resp.statusCode = 200;
          }else{
            console.log('::NO');
            resp.statusCode = 401;
          }
        }
        resp.end();
      }

        console.log("::::Webhookgetsssss:::");
        resp.message = 'Get API'
        resp.end();
     
  } catch (error) {
    resp.statusCode = 200;
    resp.end();
  }
      
     
  });
  server.listen(webhookPort);

function collectRequestData(request, callback) {
    let body = "";
    request.on("data", (chunk) => {
      body += chunk.toString();
    });
    request.on("end", () => {
      callback(body);
    });
  }
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda