diff --git a/lib/partner-listener/index.js b/lib/partner-listener/index.js index 573d83a..e5c2ecc 100644 --- a/lib/partner-listener/index.js +++ b/lib/partner-listener/index.js @@ -14,6 +14,7 @@ const routerPay = require('./routers/pay'); const routerTopup = require('./routers/topup'); const routerTrxStatus = require('./routers/trx-status'); const routerProductTree = require('./routers/product-tree'); +const routerProductPrice = require('./routers/product-price'); const app = express(); @@ -50,6 +51,7 @@ app.use('/inquiry', routerInquiry); app.use('/pay', routerPay); app.use('/topup', routerTopup); app.use('/trx-status', routerTrxStatus); +app.use('/product-price', routerProductPrice); app.use('/product-tree', routerProductTree); app.use('/', routerTopup); diff --git a/lib/partner-listener/routers/product-price.js b/lib/partner-listener/routers/product-price.js new file mode 100644 index 0000000..8168ac2 --- /dev/null +++ b/lib/partner-listener/routers/product-price.js @@ -0,0 +1,99 @@ +const MODULE_NAME = 'PARTNER-LISTENER.ROUTERS.PRODUCT-PRICE'; + +const axios = require('axios').default; +const express = require('express'); +const urlJoin = require('join-path'); + +const coreUrl = require('komodo-sdk/core-url'); +const logger = require('tektrans-logger'); +const { orderBy } = require('natural-orderby'); + +const ipv6ToIpv4 = require('../../ipv6-to-ipv4'); +const getFromBodyQsParams = require('../../get-from-body-qs-params'); + +const CORE_ENDPOINT = urlJoin(coreUrl, '/product-tree'); + +const router = express.Router(); +module.exports = router; + +const traverse = (data, productType) => { + const products = []; + + if (Array.isArray(data)) { + data.forEach((brandCategory) => { + if (Array.isArray(brandCategory.brands)) { + brandCategory.brands.forEach((brand) => { + if (Array.isArray(brand.product_categories)) { + brand.product_categories.forEach((productCategory) => { + if (Array.isArray(productCategory.products)) { + productCategory.products.forEach((product) => { + products.push({ + product: product.name, + description: product.description, + type: productType, + brandName: brand.name, + productCategory: productCategory.name, + price: product.price, + }); + }); + } + }); + } + }); + } + }); + } + + return products; +}; + +const mainHandler = async (req, res) => { + const { xid } = res.locals; + + const terminalNameWithoutIp = (getFromBodyQsParams(req, 'terminal_name') || '').toString().trim(); + const terminalName = `${terminalNameWithoutIp}@${ipv6ToIpv4(req.ip)}`; + const password = getFromBodyQsParams(req, 'password'); + + try { + const result = await axios.get(CORE_ENDPOINT, { + params: { + terminal_name: terminalName, + password, + }, + }); + + if (!result || !result.data) { + const e = new Error(`${MODULE_NAME} 643A50C5: Invalid result from CORE`); + throw e; + } + + const prepaidProducts = traverse(result.data.prepaid, 'PREPAID'); + const postpaidProducts = traverse(result.data.postpaid, 'POSTPAID'); + + res.json({ + httpgetx_xid: xid, + xid: result.data.xid, + ts: new Date(), + terminal_name: result.data.terminal_name, + products: orderBy( + prepaidProducts.concat(postpaidProducts), + (p) => p.product, + 'asc', + ), + }); + } catch (e) { + logger.warn(`${MODULE_NAME} A5414E86: Exception`, { + xid, + eCode: e.code, + eMessage: e.message || e, + }); + + res.json({ + // httpgetx_xid: xid, + ts: new Date(), + error: e.message || e, + }); + } +}; + +router.get('/', mainHandler); diff --git a/lib/partner-listener/routers/product-tree.js b/lib/partner-listener/routers/product-tree.js index 650e048..f1e7b81 100644 --- a/lib/partner-listener/routers/product-tree.js +++ b/lib/partner-listener/routers/product-tree.js @@ -2,11 +2,12 @@ const MODULE_NAME = 'PARTNER-LISTENER.ROUTERS.PRODUCT-TREE'; const axios = require('axios').default; const express = require('express'); -const urlJoin = require('url-join'); +const urlJoin = require('join-path'); const coreUrl = require('komodo-sdk/core-url'); const logger = require('tektrans-logger'); +const ipv6ToIpv4 = require('../../ipv6-to-ipv4'); const getFromBodyQsParams = require('../../get-from-body-qs-params'); const CORE_ENDPOINT = urlJoin(coreUrl, '/product-tree'); @@ -17,7 +18,8 @@ module.exports = router; const mainHandler = async (req, res) => { const { xid } = res.locals; - const terminalName = getFromBodyQsParams(req, 'terminal_name'); + const terminalNameWithoutIp = (getFromBodyQsParams(req, 'terminal_name') || '').toString().trim(); + const terminalName = `${terminalNameWithoutIp}@${ipv6ToIpv4(req.ip)}`; const password = getFromBodyQsParams(req, 'password'); try { @@ -28,13 +30,13 @@ const mainHandler = async (req, res) => { }, }); - if (!result) { + if (!result || !result.data) { const e = new Error(`${MODULE_NAME} B7555411: Invalid result from CORE`); throw e; } result.httpgetx_xid = xid; - res.json(result); + res.json(result.data); } catch (e) { logger.warn(`${MODULE_NAME} 5AA99A06: Exception`, { xid, @@ -43,7 +45,7 @@ const mainHandler = async (req, res) => { }); res.json({ - xid, + httpgetx_xid: xid, ts: new Date(), error: e.message || e, }); diff --git a/package-lock.json b/package-lock.json index 1402424..236a393 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,13 +11,14 @@ "dependencies": { "axios": "^0.19.2", "express": "^4.17.1", + "join-path": "^1.1.1", "komodo-sdk": "^1.45.6", "mkdirp": "^1.0.4", "moment": "^2.24.0", + "natural-orderby": "^2.0.3", "request": "^2.88.0", "tektrans-logger": "^1.2.3", "uniqid": "^5.3.0", - "url-join": "^5.0.0", "uuid": "^3.3.3" }, "devDependencies": { @@ -244,6 +245,11 @@ "node": ">=0.10.0" } }, + "node_modules/as-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/as-array/-/as-array-2.0.0.tgz", + "integrity": "sha512-1Sd1LrodN0XYxYeZcN1J4xYZvmvTwD5tDWaPUGPIzH1mFsmzsPnVtd2exWhecMjtZk/wYWjNZJiD3b1SLCeJqg==" + }, "node_modules/asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", @@ -1996,6 +2002,21 @@ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, + "node_modules/join-path": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/join-path/-/join-path-1.1.1.tgz", + "integrity": "sha512-jnt9OC34sLXMLJ6YfPQ2ZEKrR9mB5ZbSnQb4LPaOx1c5rTzxpR33L18jjp0r75mGGTJmsil3qwN1B5IBeTnSSA==", + "dependencies": { + "as-array": "^2.0.0", + "url-join": "0.0.1", + "valid-url": "^1" + } + }, + "node_modules/join-path/node_modules/url-join": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-0.0.1.tgz", + "integrity": "sha512-H6dnQ/yPAAVzMQRvEvyz01hhfQL5qRWSEt7BX8t9DqnPw9BjMb64fjIRq76Uvf1hkHp+mTZvEVJ5guXOT0Xqaw==" + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -2710,6 +2731,14 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, + "node_modules/natural-orderby": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/natural-orderby/-/natural-orderby-2.0.3.tgz", + "integrity": "sha512-p7KTHxU0CUrcOXe62Zfrb5Z13nLvPhSWR/so3kFulUQU0sgUll2Z0LwpsLN351eOOD+hRGu/F1g+6xDfPeD++Q==", + "engines": { + "node": "*" + } + }, "node_modules/negotiator": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", @@ -4199,14 +4228,6 @@ "punycode": "^2.1.0" } }, - "node_modules/url-join": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-5.0.0.tgz", - "integrity": "sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA==", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -4235,6 +4256,11 @@ "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", "dev": true }, + "node_modules/valid-url": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz", + "integrity": "sha512-QQDsV8OnSf5Uc30CKSwG9lnhMPe6exHtTXLRYX8uMwKENy640pU+2BgBL0LRbDh/eYRahNCS7aewCx0wf3NYVA==" + }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -4789,6 +4815,11 @@ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" }, + "as-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/as-array/-/as-array-2.0.0.tgz", + "integrity": "sha512-1Sd1LrodN0XYxYeZcN1J4xYZvmvTwD5tDWaPUGPIzH1mFsmzsPnVtd2exWhecMjtZk/wYWjNZJiD3b1SLCeJqg==" + }, "asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", @@ -6208,6 +6239,23 @@ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, + "join-path": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/join-path/-/join-path-1.1.1.tgz", + "integrity": "sha512-jnt9OC34sLXMLJ6YfPQ2ZEKrR9mB5ZbSnQb4LPaOx1c5rTzxpR33L18jjp0r75mGGTJmsil3qwN1B5IBeTnSSA==", + "requires": { + "as-array": "^2.0.0", + "url-join": "0.0.1", + "valid-url": "^1" + }, + "dependencies": { + "url-join": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-0.0.1.tgz", + "integrity": "sha512-H6dnQ/yPAAVzMQRvEvyz01hhfQL5qRWSEt7BX8t9DqnPw9BjMb64fjIRq76Uvf1hkHp+mTZvEVJ5guXOT0Xqaw==" + } + } + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -6778,6 +6826,11 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, + "natural-orderby": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/natural-orderby/-/natural-orderby-2.0.3.tgz", + "integrity": "sha512-p7KTHxU0CUrcOXe62Zfrb5Z13nLvPhSWR/so3kFulUQU0sgUll2Z0LwpsLN351eOOD+hRGu/F1g+6xDfPeD++Q==" + }, "negotiator": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", @@ -7932,11 +7985,6 @@ "punycode": "^2.1.0" } }, - "url-join": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-5.0.0.tgz", - "integrity": "sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA==" - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -7958,6 +8006,11 @@ "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", "dev": true }, + "valid-url": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz", + "integrity": "sha512-QQDsV8OnSf5Uc30CKSwG9lnhMPe6exHtTXLRYX8uMwKENy640pU+2BgBL0LRbDh/eYRahNCS7aewCx0wf3NYVA==" + }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", diff --git a/package.json b/package.json index 35aeb37..392374b 100644 --- a/package.json +++ b/package.json @@ -31,13 +31,14 @@ "dependencies": { "axios": "^0.19.2", "express": "^4.17.1", + "join-path": "^1.1.1", "komodo-sdk": "^1.45.6", "mkdirp": "^1.0.4", "moment": "^2.24.0", + "natural-orderby": "^2.0.3", "request": "^2.88.0", "tektrans-logger": "^1.2.3", "uniqid": "^5.3.0", - "url-join": "^5.0.0", "uuid": "^3.3.3" } }