refactoring tpv controller

parent 5dc50182
...@@ -6,8 +6,48 @@ ...@@ -6,8 +6,48 @@
*/ */
const moment = require('moment'); const moment = require('moment');
//
// RedSys Javascript API
//
const cryptojs = require("crypto-js"); const cryptojs = require("crypto-js");
function cipherMerchantKey(order, key) {
// Decode key
var keyWordArray = cryptojs.enc.Base64.parse(key);
// Generate transaction key
var iv = cryptojs.enc.Hex.parse("0000000000000000");
var cipher = cryptojs.TripleDES.encrypt(order, keyWordArray, {
iv:iv,
mode: cryptojs.mode.CBC,
padding: cryptojs.pad.ZeroPadding
});
return cipher.ciphertext;
}
function encodeMerchantParams(object) {
// Base64 encoding of parameters
var merchantWordArray = cryptojs.enc.Utf8.parse(JSON.stringify(tpvdata));
return merchantWordArray.toString(cryptojs.enc.Base64);
}
function decodeMerchantParams(string) {
// Base64 encoding of parameters
var merchantWordArray = cryptojs.enc.Base64.parse(string);
return JSON.parse(merchantWordArray.toString(cryptojs.enc.Utf8));
}
function signMerchantParams(params, key) {
// Sign
var signature = cryptojs.HmacSHA256(params, key);
return signature.toString(cryptojs.enc.Base64);
}
//
// TPV Controller
//
module.exports = { module.exports = {
/** /**
...@@ -20,35 +60,16 @@ module.exports = { ...@@ -20,35 +60,16 @@ module.exports = {
if (!params.id_stu || !params.id_sup || !params.type) if (!params.id_stu || !params.id_sup || !params.type)
return res.badRequest(); return res.badRequest();
//
// Generate new license and use ID for order
//
new Promise((resolve, reject) => {
License.genLicenseNumber((number) => {
if (number)
resolve(number);
else
reject();
});
})
.then((number) => {
return License.create({
number: number,
duration: params.type == 'forever' ? 1200 : 12,
creator: req.token.email
});
})
.then((license) => {
if (!license)
throw new Error("Unable to create license");
// //
// Prepare submit data // Prepare submit data
// //
var product_desc = sails.__("license_annual");
var amount = sails.config.pictogram.tpv.prices.oneYearEuro; var amount = sails.config.pictogram.tpv.prices.oneYearEuro;
if (params.type == 'forever') if (params.type == 'forever') {
amount = sails.config.pictogram.tpv.prices.foreverEuro; amount = sails.config.pictogram.tpv.prices.foreverEuro;
var product_desc = sails.__("license_pro");
}
var tpvdata = var tpvdata =
{ {
...@@ -58,10 +79,16 @@ module.exports = { ...@@ -58,10 +79,16 @@ module.exports = {
DS_MERCHANT_CURRENCY: '978', // Terminal currency DS_MERCHANT_CURRENCY: '978', // Terminal currency
DS_MERCHANT_TRANSACTIONTYPE: "0", // Type of the transaction (0: authorized) DS_MERCHANT_TRANSACTIONTYPE: "0", // Type of the transaction (0: authorized)
DS_MERCHANT_AMOUNT: amount + "00", // Amount DS_MERCHANT_AMOUNT: amount + "00", // Amount
DS_MERCHANT_ORDER: moment().format('YYMMDD') + license.id.toString().slice(-6), // hast to be from 4 to 12 characters long DS_MERCHANT_ORDER: moment().format('YYMMDD') + params.id_stu.toString().slice(-6), // hast to be from 4 to 12 characters long
DS_MERCHANT_MERCHANTURL: 'https://' + req.headers.host + "/license/" + license.number + "/stu/" + params.id_stu, // notification to activate DS_MERCHANT_MERCHANTURL: 'https://' + req.headers.host + "/tpv/notify/" + params.id_stu, // notification to activate
DS_MERCHANT_URLOK: 'https://' + req.headers.host + '/app/#/student/' + params.id_stu + "/setup/renewed/1", // Returning URL (success) DS_MERCHANT_URLOK: 'https://' + req.headers.host + '/app/#/student/' + params.id_stu + "/setup/renewed/1", // Returning URL (success)
DS_MERCHANT_URLKO: 'https://' + req.headers.host + '/app/#/student/' + params.id_stu + "/setup/renewed/0" // Returning URL (error) DS_MERCHANT_URLKO: 'https://' + req.headers.host + '/app/#/student/' + params.id_stu + "/setup/renewed/0", // Returning URL (error)
DS_MERCHANT_PRODUCTDESCRIPTION: product_desc,
DS_MERCHANT_MERCHANTDATA: JSON.stringify({
type: params.type,
creator: req.token.email,
id_stu: params.id_stu
})
}; };
sails.debug.log("Data: " + JSON.stringify(tpvdata)); sails.debug.log("Data: " + JSON.stringify(tpvdata));
...@@ -69,24 +96,9 @@ module.exports = { ...@@ -69,24 +96,9 @@ module.exports = {
// Sign submit data // Sign submit data
// //
// Base64 encoding of parameters var key = cipherMerchantKey(tpvdata.DS_MERCHANT_ORDER, sails.config.pictogram.tpv.key);
var merchantWordArray = cryptojs.enc.Utf8.parse(JSON.stringify(tpvdata)); var merchantBase64 = encodeMerchantParams(tpvdata);
var merchantBase64 = merchantWordArray.toString(cryptojs.enc.Base64); var signatureBase64 = signMerchantParams(merchantBase64, key);
// Decode key
var keyWordArray = cryptojs.enc.Base64.parse(sails.config.pictogram.tpv.key);
// Generate transaction key
var iv = cryptojs.enc.Hex.parse("0000000000000000");
var cipher = cryptojs.TripleDES.encrypt(tpvdata.DS_MERCHANT_ORDER, keyWordArray, {
iv:iv,
mode: cryptojs.mode.CBC,
padding: cryptojs.pad.ZeroPadding
});
// Sign
var signature = cryptojs.HmacSHA256(merchantBase64, cipher.ciphertext);
var signatureBase64 = signature.toString(cryptojs.enc.Base64);
// Done, we can return response // Done, we can return response
var response = { var response = {
...@@ -97,8 +109,60 @@ module.exports = { ...@@ -97,8 +109,60 @@ module.exports = {
sails.log.debug(JSON.stringify(response)); sails.log.debug(JSON.stringify(response));
res.ok(response); res.ok(response);
},
/**
* Notification of payment from RedSys
*/
notify: function(res, req) {
var params = res.allParams();
if (!params.DS_SIGNATURE || !params.DS_MERCHANTPARAMETERS)
return res.badRequest();
var postSignature = params.DS_SIGNATURE;
var postParams = params.DS_MERCHANTPARAMETERS;
var params = decodeMerchantParams(postParams);
var ownParams = JSON.parse(params->DS_MERCHANT_MERCHANTDATA);
var key = cipherMerchantKey(params->DS_MERCHANT_ORDER, sails.config.pictogram.tpv.key);
var signatureBase64 = signMerchantParams(postParams, key);
if (postSignature != signatureBase64)
return res.badRequest("Invalid signature");
// Everything is correct: generate serial number and activate it
//
// Generate new license and use ID for order
//
new Promise((resolve, reject) => {
License.genLicenseNumber((number) => {
if (number)
resolve(number);
else
reject();
});
})
.then((number) => {
return License.create({
number: number,
duration: ownParams.type == 'forever' ? 1200 : 12,
creator: ownParams.creator
});
})
.then((license) => {
if (!license)
throw new Error("Unable to create license");
License.activate(license.number, ownParams.id_stu, function(err, license) {
if (err)
return res.badRequest(err);
return res.ok(license);
});
}) })
.catch((err) => {return res.serverError(err)}); .catch((err) => {return res.serverError(err)});
}, }
}; };
{ {
"A brand new app.": "A brand new app.", "A brand new app.": "A brand new app.",
"change_password_mail": "To change your password, please click on the following link:\n", "change_password_mail": "To change your password, please click on the following link:\n",
"license_annual": "Pictogram 12-months License",
"license_pro": "Pictogram PRO license",
"login": "login", "login": "login",
"notification_from_pictogram": "Notification from Pictogram", "notification_from_pictogram": "Notification from Pictogram",
"no_name": "No name", "no_name": "No name",
......
{ {
"A brand new app.": "Una aplicación de la nueva marca.", "A brand new app.": "Una aplicación de la nueva marca.",
"change_password_mail": "Para cambiar su contraseña, haga click en el siguiente enlace:\n", "change_password_mail": "Para cambiar su contraseña, haga click en el siguiente enlace:\n",
"license_annual": "Pictogram licencia 12 meses",
"license_pro": "Pictogram licencia PRO",
"login": "acceder", "login": "acceder",
"notification_from_pictogram": "Notificación desde Pictogram", "notification_from_pictogram": "Notificación desde Pictogram",
"no_name": "Sin nombre", "no_name": "Sin nombre",
......
...@@ -130,7 +130,6 @@ module.exports.policies = { ...@@ -130,7 +130,6 @@ module.exports.policies = {
// create: ['tokenAuth', 'isAdmin'], // create: ['tokenAuth', 'isAdmin'],
// activate: ['tokenAuth'] // activate: ['tokenAuth']
create: ['tokenAuth'], create: ['tokenAuth'],
activate: true,
getByEmail: ['tokenAuth'] getByEmail: ['tokenAuth']
}, },
......
...@@ -149,4 +149,5 @@ module.exports.routes = { ...@@ -149,4 +149,5 @@ module.exports.routes = {
'POST /ws/:id_ws/close': 'WorkingSessionController.close', 'POST /ws/:id_ws/close': 'WorkingSessionController.close',
'POST /tpv/init': 'TPVController.init', 'POST /tpv/init': 'TPVController.init',
'POST /tpv/notify': 'TPVController.notify',
}; };
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment