From 3196debe172b3b1d87c7dd541738f56212d3d4ac Mon Sep 17 00:00:00 2001 From: Dominik Hebeler <dominik@suma-ev.de> Date: Mon, 14 Nov 2022 14:20:10 +0100 Subject: [PATCH] loading purchase data from stored order --- pass/app/Order.js | 62 ++++++++++++++++++++++++++------ pass/resources/js/checkout.js | 8 +++-- pass/routes/checkout/checkout.js | 2 +- pass/routes/checkout/paypal.js | 61 +++++++++++++++++++++++++------ 4 files changed, 107 insertions(+), 26 deletions(-) diff --git a/pass/app/Order.js b/pass/app/Order.js index 8390709..93fa3b6 100644 --- a/pass/app/Order.js +++ b/pass/app/Order.js @@ -5,6 +5,11 @@ class Order { static get STORAGE_KEY_PREFIX() { return "order_"; } + + static get PURCHASE_TAX_AMOUNT() { + return 0.07; + } + static get PURCHASE_STORAGE_TIME_MONTHS() { return 6; } @@ -30,6 +35,7 @@ class Order { #price_per_unit; #encrypted_sales_receipts; #payment_completed; + #payment_method_link; // Stores a link to an entry of the payment methods payment i.e. PayPal order id /** * Data populated by context @@ -44,10 +50,10 @@ class Order { price_per_unit, encrypted_sales_receipts ) { - this.#order_id = order_id; - this.#amount = amount; - this.#unit_size = unit_size; - this.#price_per_unit = price_per_unit; + this.#order_id = parseInt(order_id); + this.#amount = parseInt(amount); + this.#unit_size = parseInt(unit_size); + this.#price_per_unit = parseFloat(price_per_unit); this.#encrypted_sales_receipts = encrypted_sales_receipts; this.#payment_completed = false; @@ -59,15 +65,48 @@ class Order { }); } + set_create_mode(create_mode) { + this.#create_mode = create_mode; + } + + getAmount() { + return this.#amount; + } + + getPricePerUnit() { + return this.#price_per_unit; + } + + setPaymentMethodLink(payment_method_link) { + this.#payment_method_link = payment_method_link; + } + static async LOAD_ORDER_FROM_ID(order_id) { - let Redis = require("ioredis"); - let redis_client = new Redis({ - host: config.get("redis.host"), - }); + return new Promise((resolve, reject) => { + let Redis = require("ioredis"); + let redis_client = new Redis({ + host: config.get("redis.host"), + }); - let redis_key = Order.STORAGE_KEY_PREFIX + order_id; - let order_data = await redis_client.hgetall(redis_key); - console.log(order_data); + let redis_key = Order.STORAGE_KEY_PREFIX + order_id; + redis_client.hgetall(redis_key).then((order_data) => { + if (Object.keys(order_data).length === 0) { + return reject("Could not find Order in our database!"); + } + let loaded_order = new Order( + order_data.order_id, + order_data.amount, + order_data.unit_size, + order_data.price_per_unit, + order_data.encrypted_sales_receipts + ); + if (order_data.payment_method_link) { + loaded_order.setPaymentMethodLink(order_data.payment_method_link); + } + loaded_order.set_create_mode(false); + resolve(loaded_order); + }); + }); } async save() { @@ -93,6 +132,7 @@ class Order { price_per_unit: this.#price_per_unit, encrypted_sales_receipts: this.#encrypted_sales_receipts, payment_completed: this.#payment_completed, + payment_method_link: this.#payment_method_link, }) .then((result) => { this.#create_mode = false; diff --git a/pass/resources/js/checkout.js b/pass/resources/js/checkout.js index 12266d9..1d4b654 100644 --- a/pass/resources/js/checkout.js +++ b/pass/resources/js/checkout.js @@ -61,9 +61,11 @@ function execute_payment_paypal(e) { body: JSON.stringify({ order_id: document.querySelector("input[name=order_id]").value, amount: document.querySelector("input[name=amount]").value, - unit_size: document.querySelector("input[name=unit_size]"), - price_per_unit: - document.querySelector("input[name=price]").value, + unit_size: document.querySelector("input[name=unit_size]") + .value, + price_per_unit: document.querySelector( + "input[name=price_per_unit]" + ).value, public_key_n: document.querySelector("input[name=public_key_n]") .value, public_key_e: document.querySelector("input[name=public_key_e]") diff --git a/pass/routes/checkout/checkout.js b/pass/routes/checkout/checkout.js index 6e295ca..e71c0df 100644 --- a/pass/routes/checkout/checkout.js +++ b/pass/routes/checkout/checkout.js @@ -57,7 +57,7 @@ router.get( router.use( "/payment/order", body("amount") - .isInt({ min: 1, max: 4 }) + .isInt({ min: 1, max: 12 }) .withMessage("Invalid amount submitted") .toInt(), body("unit_size").isIn(["100", "250"]).toInt(), diff --git a/pass/routes/checkout/paypal.js b/pass/routes/checkout/paypal.js index b2b2451..a25d26b 100644 --- a/pass/routes/checkout/paypal.js +++ b/pass/routes/checkout/paypal.js @@ -2,6 +2,7 @@ var express = require("express"); var router = express.Router(); const config = require("config"); +const Order = require("../../app/Order.js"); const CLIENT_ID = config.get("payments.paypal.testing.client_id"); const APP_SECRET = config.get("payments.paypal.testing.secret"); @@ -9,9 +10,13 @@ const base = "https://api-m.sandbox.paypal.com"; /* Client initiates payment */ router.post("/", async (req, res, next) => { - // All Submitted data is verified at this point - const order = await createOrder(req); - res.json(order); + Order.LOAD_ORDER_FROM_ID(req.body.order_id) + .then((order) => { + createOrder(order).then((order_result) => res.json(order_result)); + }) + .catch((error) => { + return res.status(400).json({ errors: [{ msg: error }] }); + }); }); module.exports = router; @@ -24,10 +29,17 @@ module.exports = router; // use the orders api to create an order -async function createOrder(req) { +async function createOrder(loaded_order) { + console.log(loaded_order); const accessToken = await generateAccessToken(); const url = `${base}/v2/checkout/orders`; + let tax_amount_per_unit = ( + loaded_order.getPricePerUnit().toFixed(2) * Order.PURCHASE_TAX_AMOUNT + ).toFixed(2); + let item_amount_per_unit = ( + loaded_order.getPricePerUnit().toFixed(2) - tax_amount_per_unit + ).toFixed(2); let order = { intent: "CAPTURE", @@ -37,13 +49,39 @@ async function createOrder(req) { description: "MetaGer Pass Einkauf", amount: { currency_code: "EUR", - value: req.body.price.toFixed(2), + value: + item_amount_per_unit * loaded_order.getAmount() + + tax_amount_per_unit * loaded_order.getAmount(), + breakdown: { + item_total: { + currency_code: "EUR", + value: (item_amount_per_unit * loaded_order.getAmount()).toFixed( + 2 + ), + }, + tax_total: { + currency_code: "EUR", + value: (tax_amount_per_unit * loaded_order.getAmount()).toFixed( + 2 + ), + }, + }, }, items: [ { - name: "MetaGer Pass: Suchanfragen (100x)", - quantity: 1, - unit_amount: 0, + name: "MetaGer Pass: Suchanfragen (250x)", + quantity: loaded_order.getAmount(), + unit_amount: { + currency_code: "EUR", + value: item_amount_per_unit, + }, + tax: { + currency_code: "EUR", + value: tax_amount_per_unit, + }, + category: "DIGITAL_GOODS", + description: + "MetaGer Pass Suchanfragen zur Nutzung der Suchmaschine MetaGer", }, ], }, @@ -53,7 +91,6 @@ async function createOrder(req) { shipping_preference: "NO_SHIPPING", }, }; - console.log(order.purchase_units[0].amount); const response = await fetch(url, { method: "post", @@ -67,8 +104,10 @@ async function createOrder(req) { }); const data = await response.json(); - - return data; + loaded_order.setPaymentMethodLink({ id: data.id }); + return loaded_order.save().then(() => { + return data; + }); } // use the orders api to capture payment for an order -- GitLab