diff --git a/config/config_exemple.json b/config/config_exemple.json index bcb8693..55b3bfa 100644 --- a/config/config_exemple.json +++ b/config/config_exemple.json @@ -20,5 +20,11 @@ }, "from": "Contact Email ", "contact": "Your Contact " + }, + "lyfPay": { + "url": "https://lyf.eu/some/api/url", + "posUuid": "330fc62c-f549-4c57-8f65-fc977079b283", + "warningEmail": "contact@your-email.fr", + "secureKey": "0123456789ABCDEF0123456789ABCDEF01234567" } } diff --git a/models/order.js b/models/order.js index 709fc0a..9426281 100644 --- a/models/order.js +++ b/models/order.js @@ -8,6 +8,7 @@ module.exports = (sequelize, DataTypes) => { Order.belongsToMany(models.Sandwich, {through: {model: models.SandwichOrder, unique: false}}); Order.belongsTo(models.Department); Order.belongsTo(models.User); + Order.belongsTo(models.Payment, {foreignKey: "ShopOrderReference"}); } } Order.init({ diff --git a/models/payment.js b/models/payment.js new file mode 100644 index 0000000..713c420 --- /dev/null +++ b/models/payment.js @@ -0,0 +1,40 @@ +"use strict"; +let maxLength = 80; +function idGen() { + let id = ""; + while (id.length < maxLength) { + let tmp = id + Math.random().toString(36).substring(2, 15); + if (tmp.length <= maxLength) + id = tmp; + else + break; + } + return id; +} + +const { + Model +} = require("sequelize"); +module.exports = (sequelize, DataTypes) => { + class Payment extends Model { + static associate(models) { + Payment.hasOne(models.Order); + } + } + Payment.init({ + shopReference: { + type: DataTypes.STRING(maxLength), + primaryKey: true, + defaultValue: idGen + }, + date: { + type: DataTypes.DATE, + allowNull: false, + defaultValue: DataTypes.NOW + } + }, { + sequelize, + modelName: "Payment", + }); + return Payment; +}; diff --git a/package-lock.json b/package-lock.json index 99c109b..45324b3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3334,9 +3334,9 @@ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" }, "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", + "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", "dev": true, "optional": true, "requires": { diff --git a/routes/order.js b/routes/order.js index ed96e59..2c7a3a1 100644 --- a/routes/order.js +++ b/routes/order.js @@ -2,6 +2,7 @@ let express = require("express"); let router = express.Router(); let models = require("../models"); let error = require("./utils/error"); +let sendPayment = require("./utils/lyfPay").sendPayment; router.post("/", async (req, res) => { @@ -67,7 +68,8 @@ router.post("/", async (req, res) => { error(req, res, "Invalid order !", 500); throw e; } - res.send("Ok"); + + await sendPayment(req, res, order); }); module.exports = router; diff --git a/routes/utils/lyfPay.js b/routes/utils/lyfPay.js new file mode 100644 index 0000000..6d16f89 --- /dev/null +++ b/routes/utils/lyfPay.js @@ -0,0 +1,51 @@ +const crypto = require("crypto"); +const models = require("../../models"); + + +function macCalculator(params, key) { + return crypto.createHmac("sha1", key).update(Object.values(params).join("*")).digest("hex"); +} + +async function sendPayment(req, res, order) { + let payment = await models.Payment.create(); + await order.setPayment(payment); + await payment.reload(); + + let baseUrl = `${req.protocol}://${req.hostname}/order`; + let config = req.app.get("config").lyfPay; + let url = config.url + "/Payment.aspx?"; + + let params = { + lang: "fr", + version: "v2.0", + timestamp: Math.floor(payment.date/1000), + posUuid: config.posUuid, + shopReference: payment.shopReference, + shopOrderReference: order.id, + deliveryFeesAmount: 0, + amount: order.price*100, + currency: "EUR", + mode: "IMMEDIATE", + onSuccess: baseUrl + "/success", + onCancel: baseUrl+"/cancel", + onError: baseUrl+"/error", + additionalData: JSON.stringify({ + "callBackUrl": baseUrl+"/callback", + "callBackEmail":config.warningEmail + }), + enforcedIdentification: false + }; + + params.mac = macCalculator(params, config.secureKey); + params.additionalDataEncoded = Buffer.from(params.additionalData).toString("base64"); + params.additionalData = undefined; + + url += Object.keys(params) + .map(k => encodeURIComponent(k) + "=" + encodeURIComponent(params[k])) + .join("&"); + + res.redirect(307, url); +} + + +module.exports = {sendPayment: sendPayment};