2012-04-24 18 views
7

Estoy intentando autenticar un mensaje enviado desde TrialPay usando Node.js y Express. TrialPay firma solicitudes con un hash HMAC-MD5 y proporciona these instructions al validar.Validación de HMAC MD5 con Node.js, Express y Trialpay

Este es mi código:

app.post('/trialpay', function(req, res) { 

    var key = "[MY MERCHANT KEY]"; 
    var hash = req.header("TrialPay-HMAC-MD5"); 
    var data = req.body.toString(); 

    var crypted = require("crypto").createHmac("md5", key) 
     .update(data) 
     .digest("hex"); 

    if (hash == crypted) { 
     res.writeHead(200, {"Content-Type": "plain/text"}); 
     res.end("Success!"); 
    } else { 
     throw new Error("Invalid TrialPay Hash"); 
    } 
}); 

Esto es, obviamente, no funciona (hash no coincide).

Descargo de responsabilidad: Soy muy nuevo en Node.js, y tengo poca experiencia con Javascript, para empezar.

ACTUALIZACIÓN

No me daba cuenta de que el enlace estaba protegido.

TrialPay usa su Notification-Key (configurada en la información de su cuenta) como la clave secreta para firmar el HMAC. Para solicitudes GET, la cadena de consulta que sigue al signo de interrogación (en la URL) está firmada. Para las solicitudes POST , todo el cuerpo POST está firmado.

Aquí es un ejemplo de cómo TrialPay le indica que debe validar en Google App Engine (Python):

class MyHandler(webapp.RequestHandler): 
    def post(self): 
    key = '[YOUR MERCHANT KEY]' 
    tphash = self.request.headers['TrialPay-HMAC-MD5'] 
    if hmacmd5(key,self.request.body) != tphash: 
    logging.info('invalid trialpay hash') 
    return 

ACTUALIZACIÓN 2

Los req.body imprime como:

{ 
    oid: 'sample-order-id', 
    sid: 'customer-sid', 
    order_date: '04/24/2012', 
    timestamp: '04/24/2012 16:28:46', 
    first_name: 'customer-firstname', 
    last_name: 'customer-lastname', 
    email: '[email protected]', 
    revenue: '10.00', 
    zip_code: '94041', 
    country: 'US' 
} 
+1

Su enlace no funciona, no me dejará iniciar sesión. Dicho esto, debe mantenerse alejado de 'throw'ing dentro de sus controladores de solicitudes (básicamente, en cualquier lugar del nodo). Acepte el tercer parámetro (callback, 'next' en express lingo) y pase el error a' next' en su lugar. O mejor aún, maneje el error aquí, donde pueda, y 'res.send (403, 'Invalid TrialPay Hash')'. Además, no mencionas qué tipo de datos estás publicando, sería interesante ver qué contiene 'req.body' y especialmente' req.body.toString() ', si pudieras' console.log' que . –

+0

Gracias por el comentario y consejo @LinusGThiel. Cuando probé 'console.log (req.body.toString());' solo imprime "[object Object]". Disculpe mi ignorancia, aquí. –

+0

¡Eso es lo que sospechaba! ¿Qué le proporciona 'console.log (req.body)'? –

Respuesta

4

Esto debería hacer el truco:

var crypto = require('crypto'); 

function calculateSignature(key) { 
    return function(req, res, next) { 
     var hash = req.header("TrialPay-HMAC-MD5"), 
      hmac = crypto.createHmac("md5", key); 

     req.on("data", function(data) { 
      hmac.update(data); 
     }); 

     req.on("end", function() { 
      var crypted = hmac.digest("hex"); 

      if(crypted === hash) { 
       // Valid request 
       return res.send("Success!", { "Content-Type": "text/plain" }); 
      } else { 
       // Invalid request 
       return res.send("Invalid TrialPay hash", { "Content-Type": "text/plain" }, 403); 
      } 
     }); 

     req.on("error", function(err) { 
      return next(err); 
     }); 
    } 
} 

app.post("/trialpay", calculateSignature("[MY MERCHANT KEY]")); 
+0

¡Esto funciona! Muchas gracias por su ayuda. Solo un problema, agregué 'res.writeHead (200, {'Content-Type': 'plain/text'});' above 'res.end (" Success! ")' Porque el servidor TrialPay simplemente está colgando. He registrado el hash y coinciden, así que no estoy seguro de lo que está pasando. –

+0

¡Genial! En realidad no es un 'res.end' sino un' res.send' - un regalo de Express. Consulte [documentación res.send] (http://expressjs.com/guide.html#res.send%28%29). Wow, mirando eso, veo que las cadenas siempre se enviarán con 'Content-Type: text/html'. Mi error. Actualizado arriba. –

+0

Solo lo cambié a 'fin' porque' enviar' también estaba colgado. Intenté 'console.log ('Success!');' En 'app.post()' encima 'res.send (" Success! ");' Y no se registró nada. –

-1

Para analizan el código de la nube: (he probado) El punto es express.bodyParser será analizar la cadena codificada URL que se utiliza para hash.

var parseExpressRawBody = require('parse-express-raw-body'); 
var queryString = require('querystring'); 
app.post('/trialpay',parseExpressRawBody(),function(req, res) { 
var hmac, calculatedSignature,payloadStr=req.body.toString(); 
hmac = crypto.createHmac('md5', TrialPayMerchentKey); 
hmac.update(payloadStr); 
calculatedSignature = hmac.digest('hex'); 

if (req.headers['trialpay-hmac-md5'] === calculatedSignature) { 
    ~~~~~~ 
+0

Agregue algunas explicaciones. – Nilambar

+0

Su fragmento es realmente malo. ¿Qué debería hacer? Tómese un tiempo para revisar su mensaje antes de publicarlo. –

Cuestiones relacionadas