Commit 810fa18dae9eb5c2f21cea9bbc42524ccb4e76d4
1 parent
4978f3b374
Exists in
master
and in
1 other branch
Migrate to tektrans-logger
Showing 14 changed files with 14 additions and 14 deletions Inline Diff
- lib/apiserver/index.js
- lib/core-callback/dumper/req.js
- lib/core-callback/dumper/sender.js
- lib/core-callback/index.js
- lib/core-callback/sender.js
- lib/coreapi.js
- lib/middlewares/common.js
- lib/partner-listener/dumper/index.js
- lib/partner-listener/index.js
- lib/partner-listener/routers/inquiry.js
- lib/partner-listener/routers/pay.js
- lib/partner-listener/routers/topup.js
- lib/partner-listener/routers/trx-status.js
- lib/utils/mkdir-if-not-exists.js
lib/apiserver/index.js
1 | const MODULE_NAME = 'APISERVER'; | 1 | const MODULE_NAME = 'APISERVER'; |
2 | 2 | ||
3 | const express = require('express'); | 3 | const express = require('express'); |
4 | const config = require('komodo-sdk/config'); | 4 | const config = require('komodo-sdk/config'); |
5 | const logger = require('komodo-sdk/logger'); | 5 | const logger = require('tektrans-logger'); |
6 | 6 | ||
7 | const validApikey = require('./valid-apikey'); | 7 | const validApikey = require('./valid-apikey'); |
8 | 8 | ||
9 | const middlewareCommon = require('../middlewares/common'); | 9 | const middlewareCommon = require('../middlewares/common'); |
10 | const routerMatrix = require('./routers/matrix'); | 10 | const routerMatrix = require('./routers/matrix'); |
11 | 11 | ||
12 | const app = express(); | 12 | const app = express(); |
13 | 13 | ||
14 | app.use((req, res, next) => { | 14 | app.use((req, res, next) => { |
15 | res.locals.httpgetx_subsystem = MODULE_NAME; | 15 | res.locals.httpgetx_subsystem = MODULE_NAME; |
16 | next(); | 16 | next(); |
17 | }); | 17 | }); |
18 | 18 | ||
19 | const apikeyChecker = (req, res, next) => { | 19 | const apikeyChecker = (req, res, next) => { |
20 | if (validApikey(req.params.apikey)) { | 20 | if (validApikey(req.params.apikey)) { |
21 | next(); | 21 | next(); |
22 | } else { | 22 | } else { |
23 | res.status(403).end('Invalid APIKEY'); | 23 | res.status(403).end('Invalid APIKEY'); |
24 | } | 24 | } |
25 | }; | 25 | }; |
26 | 26 | ||
27 | app.use(middlewareCommon); | 27 | app.use(middlewareCommon); |
28 | 28 | ||
29 | app.use('/apikey/:apikey', apikeyChecker); | 29 | app.use('/apikey/:apikey', apikeyChecker); |
30 | app.use('/apikey/:apikey/matrix', routerMatrix); | 30 | app.use('/apikey/:apikey/matrix', routerMatrix); |
31 | 31 | ||
32 | app.use((req, res) => { | 32 | app.use((req, res) => { |
33 | const { xid } = res.locals; | 33 | const { xid } = res.locals; |
34 | res.status(404).end(`KOMODO-HTTP-GET-X CENTER (APISERVER).\n404: Method not found.\n\nXID: ${xid}.\n`); | 34 | res.status(404).end(`KOMODO-HTTP-GET-X CENTER (APISERVER).\n404: Method not found.\n\nXID: ${xid}.\n`); |
35 | }); | 35 | }); |
36 | 36 | ||
37 | const listenPort = config.listener && config.listener.apiserver && config.listener.apiserver.port; | 37 | const listenPort = config.listener && config.listener.apiserver && config.listener.apiserver.port; |
38 | if ( | 38 | if ( |
39 | listenPort | 39 | listenPort |
40 | && config.listener && config.listener.apiserver && config.listener.apiserver.apikey | 40 | && config.listener && config.listener.apiserver && config.listener.apiserver.apikey |
41 | ) { | 41 | ) { |
42 | app.listen(listenPort, () => { | 42 | app.listen(listenPort, () => { |
43 | logger.info(`${MODULE_NAME} FAEE1E47: Listening`, { port: listenPort }); | 43 | logger.info(`${MODULE_NAME} FAEE1E47: Listening`, { port: listenPort }); |
44 | }); | 44 | }); |
45 | } else { | 45 | } else { |
46 | logger.info(`${MODULE_NAME}: Disabled because of missing configuration`); | 46 | logger.info(`${MODULE_NAME}: Disabled because of missing configuration`); |
47 | } | 47 | } |
48 | 48 |
lib/core-callback/dumper/req.js
1 | const MODULE_NAME = 'CORE-CALLBACK.DUMPER.REQ'; | 1 | const MODULE_NAME = 'CORE-CALLBACK.DUMPER.REQ'; |
2 | 2 | ||
3 | // const fs = require('fs'); | 3 | // const fs = require('fs'); |
4 | const fsPromise = require('fs').promises; | 4 | const fsPromise = require('fs').promises; |
5 | const path = require('path'); | 5 | const path = require('path'); |
6 | const config = require('komodo-sdk/config'); | 6 | const config = require('komodo-sdk/config'); |
7 | const logger = require('komodo-sdk/logger'); | 7 | const logger = require('tektrans-logger'); |
8 | const moment = require('moment'); | 8 | const moment = require('moment'); |
9 | 9 | ||
10 | const mkdirIfNotExists = require('../../utils/mkdir-if-not-exists'); | 10 | const mkdirIfNotExists = require('../../utils/mkdir-if-not-exists'); |
11 | 11 | ||
12 | const baseDumpDir = path.join('dump', 'core-callback'); | 12 | const baseDumpDir = path.join('dump', 'core-callback'); |
13 | const lastDumpFileName = path.join(baseDumpDir, 'last-req'); | 13 | const lastDumpFileName = path.join(baseDumpDir, 'last-req'); |
14 | 14 | ||
15 | module.exports = async (req, res, next) => { | 15 | module.exports = async (req, res, next) => { |
16 | if ( | 16 | if ( |
17 | !config | 17 | !config |
18 | || !config.listener | 18 | || !config.listener |
19 | || !config.listener.core | 19 | || !config.listener.core |
20 | || !config.listener.core.dump | 20 | || !config.listener.core.dump |
21 | ) { | 21 | ) { |
22 | next(); | 22 | next(); |
23 | return; | 23 | return; |
24 | } | 24 | } |
25 | 25 | ||
26 | const { xid } = res.locals; | 26 | const { xid } = res.locals; |
27 | 27 | ||
28 | const data = `-------- | 28 | const data = `-------- |
29 | XID: ${xid} | 29 | XID: ${xid} |
30 | PID: ${process.pid} | 30 | PID: ${process.pid} |
31 | DATE: ${moment().format('YYYY-MM-DD HH:mm:ss.SSS')} | 31 | DATE: ${moment().format('YYYY-MM-DD HH:mm:ss.SSS')} |
32 | 32 | ||
33 | REQ-CONTENT-TYPE: ${req.get('content-type')} | 33 | REQ-CONTENT-TYPE: ${req.get('content-type')} |
34 | 34 | ||
35 | REQ QUERY-STRING: | 35 | REQ QUERY-STRING: |
36 | ${JSON.stringify(req.query, null, 2)} | 36 | ${JSON.stringify(req.query, null, 2)} |
37 | 37 | ||
38 | REQ BODY: | 38 | REQ BODY: |
39 | ${JSON.stringify(req.body, null, 2)} | 39 | ${JSON.stringify(req.body, null, 2)} |
40 | `; | 40 | `; |
41 | 41 | ||
42 | 42 | ||
43 | const dumpFileName = path.join( | 43 | const dumpFileName = path.join( |
44 | baseDumpDir, | 44 | baseDumpDir, |
45 | moment().format('YYYY-MM-DD'), | 45 | moment().format('YYYY-MM-DD'), |
46 | [ | 46 | [ |
47 | 'req', | 47 | 'req', |
48 | moment().format('YYMMDD_HHmmss_SSS'), | 48 | moment().format('YYMMDD_HHmmss_SSS'), |
49 | xid, | 49 | xid, |
50 | ].join('_'), | 50 | ].join('_'), |
51 | ); | 51 | ); |
52 | 52 | ||
53 | try { | 53 | try { |
54 | await mkdirIfNotExists(xid, path.dirname(dumpFileName)); | 54 | await mkdirIfNotExists(xid, path.dirname(dumpFileName)); |
55 | await fsPromise.writeFile(lastDumpFileName, data); | 55 | await fsPromise.writeFile(lastDumpFileName, data); |
56 | await fsPromise.writeFile(dumpFileName, data); | 56 | await fsPromise.writeFile(dumpFileName, data); |
57 | } catch (e) { | 57 | } catch (e) { |
58 | logger.warn(`${MODULE_NAME} E77C2B23: Exception on dumping file`, { | 58 | logger.warn(`${MODULE_NAME} E77C2B23: Exception on dumping file`, { |
59 | xid, | 59 | xid, |
60 | eCode: e.code, | 60 | eCode: e.code, |
61 | eMessage: e.eMessage, | 61 | eMessage: e.eMessage, |
62 | }); | 62 | }); |
63 | } | 63 | } |
64 | 64 | ||
65 | next(); | 65 | next(); |
66 | }; | 66 | }; |
67 | 67 |
lib/core-callback/dumper/sender.js
1 | const MODULE_NAME = 'CORE-CALLBACK.DUMPER.SENDER'; | 1 | const MODULE_NAME = 'CORE-CALLBACK.DUMPER.SENDER'; |
2 | 2 | ||
3 | const fsPromise = require('fs').promises; | 3 | const fsPromise = require('fs').promises; |
4 | const path = require('path'); | 4 | const path = require('path'); |
5 | const config = require('komodo-sdk/config'); | 5 | const config = require('komodo-sdk/config'); |
6 | const logger = require('komodo-sdk/logger'); | 6 | const logger = require('tektrans-logger'); |
7 | const moment = require('moment'); | 7 | const moment = require('moment'); |
8 | 8 | ||
9 | const mkdirIfNotExists = require('../../utils/mkdir-if-not-exists'); | 9 | const mkdirIfNotExists = require('../../utils/mkdir-if-not-exists'); |
10 | 10 | ||
11 | const baseDumpDir = path.join('dump', 'core-callback'); | 11 | const baseDumpDir = path.join('dump', 'core-callback'); |
12 | const lastDumpFileName = path.join(baseDumpDir, 'last-sent'); | 12 | const lastDumpFileName = path.join(baseDumpDir, 'last-sent'); |
13 | 13 | ||
14 | module.exports = async (xid, httpMethod, endpointUrl, params, axiosResponse, axiosError) => { | 14 | module.exports = async (xid, httpMethod, endpointUrl, params, axiosResponse, axiosError) => { |
15 | if ( | 15 | if ( |
16 | !config | 16 | !config |
17 | || !config.listener | 17 | || !config.listener |
18 | || !config.listener.core | 18 | || !config.listener.core |
19 | || !config.listener.core.dump | 19 | || !config.listener.core.dump |
20 | ) { | 20 | ) { |
21 | return; | 21 | return; |
22 | } | 22 | } |
23 | 23 | ||
24 | const data = `-------- | 24 | const data = `-------- |
25 | XID: ${xid} | 25 | XID: ${xid} |
26 | PID: ${process.pid} | 26 | PID: ${process.pid} |
27 | DATE: ${moment().format('YYYY-MM-DD HH:mm:ss.SSS')} | 27 | DATE: ${moment().format('YYYY-MM-DD HH:mm:ss.SSS')} |
28 | 28 | ||
29 | HTTP METHOD: ${httpMethod} | 29 | HTTP METHOD: ${httpMethod} |
30 | ENDPOINT URL: ${endpointUrl} | 30 | ENDPOINT URL: ${endpointUrl} |
31 | 31 | ||
32 | REQ PARAMS: | 32 | REQ PARAMS: |
33 | ${JSON.stringify(params, null, 2)} | 33 | ${JSON.stringify(params, null, 2)} |
34 | 34 | ||
35 | ERROR CODE: ${(axiosError && axiosError.code) || ''} | 35 | ERROR CODE: ${(axiosError && axiosError.code) || ''} |
36 | ERROR MESSAGE: ${(axiosError && axiosError.message) || ''} | 36 | ERROR MESSAGE: ${(axiosError && axiosError.message) || ''} |
37 | 37 | ||
38 | RES HTTP STATUS: ${axiosResponse && axiosResponse.status} | 38 | RES HTTP STATUS: ${axiosResponse && axiosResponse.status} |
39 | RES BODY: | 39 | RES BODY: |
40 | ${ | 40 | ${ |
41 | axiosResponse && axiosResponse.data && ( | 41 | axiosResponse && axiosResponse.data && ( |
42 | ((typeof axiosResponse.data === 'string') && axiosResponse.data) | 42 | ((typeof axiosResponse.data === 'string') && axiosResponse.data) |
43 | || JSON.stringify(axiosResponse.data, null, 2) | 43 | || JSON.stringify(axiosResponse.data, null, 2) |
44 | ) | 44 | ) |
45 | } | 45 | } |
46 | `; | 46 | `; |
47 | 47 | ||
48 | const dumpFileName = path.join( | 48 | const dumpFileName = path.join( |
49 | baseDumpDir, | 49 | baseDumpDir, |
50 | moment().format('YYYY-MM-DD'), | 50 | moment().format('YYYY-MM-DD'), |
51 | [ | 51 | [ |
52 | 'sent', | 52 | 'sent', |
53 | moment().format('YYMMDD_HHmmss_SSS'), | 53 | moment().format('YYMMDD_HHmmss_SSS'), |
54 | xid, | 54 | xid, |
55 | ].join('_'), | 55 | ].join('_'), |
56 | ); | 56 | ); |
57 | 57 | ||
58 | try { | 58 | try { |
59 | await mkdirIfNotExists(xid, path.dirname(dumpFileName)); | 59 | await mkdirIfNotExists(xid, path.dirname(dumpFileName)); |
60 | await fsPromise.writeFile(lastDumpFileName, data); | 60 | await fsPromise.writeFile(lastDumpFileName, data); |
61 | await fsPromise.writeFile(dumpFileName, data); | 61 | await fsPromise.writeFile(dumpFileName, data); |
62 | } catch (e) { | 62 | } catch (e) { |
63 | logger.warn(`${MODULE_NAME} 9BA99454: Exception on dumping file`, { | 63 | logger.warn(`${MODULE_NAME} 9BA99454: Exception on dumping file`, { |
64 | xid, | 64 | xid, |
65 | eCode: e.code, | 65 | eCode: e.code, |
66 | eMessage: e.eMessage, | 66 | eMessage: e.eMessage, |
67 | }); | 67 | }); |
68 | } | 68 | } |
69 | }; | 69 | }; |
70 | 70 |
lib/core-callback/index.js
1 | const MODULE_NAME = 'CORE-CALLBACK'; | 1 | const MODULE_NAME = 'CORE-CALLBACK'; |
2 | 2 | ||
3 | const DEFAULT_LISTENER_FROM_CORE = 25613; | 3 | const DEFAULT_LISTENER_FROM_CORE = 25613; |
4 | 4 | ||
5 | const express = require('express'); | 5 | const express = require('express'); |
6 | const config = require('komodo-sdk/config'); | 6 | const config = require('komodo-sdk/config'); |
7 | const logger = require('komodo-sdk/logger'); | 7 | const logger = require('tektrans-logger'); |
8 | const middlewareCommon = require('../middlewares/common'); | 8 | const middlewareCommon = require('../middlewares/common'); |
9 | const sender = require('./sender'); | 9 | const sender = require('./sender'); |
10 | const dumperReq = require('./dumper/req'); | 10 | const dumperReq = require('./dumper/req'); |
11 | const matrix = require('../matrix'); | 11 | const matrix = require('../matrix'); |
12 | 12 | ||
13 | const app = express(); | 13 | const app = express(); |
14 | 14 | ||
15 | app.use(express.json({ extended: true })); | 15 | app.use(express.json({ extended: true })); |
16 | app.use(express.urlencoded({ extended: true })); | 16 | app.use(express.urlencoded({ extended: true })); |
17 | 17 | ||
18 | app.use((req, res, next) => { | 18 | app.use((req, res, next) => { |
19 | res.locals.httpgetx_subsystem = MODULE_NAME; | 19 | res.locals.httpgetx_subsystem = MODULE_NAME; |
20 | next(); | 20 | next(); |
21 | }); | 21 | }); |
22 | 22 | ||
23 | app.use(middlewareCommon); | 23 | app.use(middlewareCommon); |
24 | app.use(dumperReq); | 24 | app.use(dumperReq); |
25 | 25 | ||
26 | app.use((req, res) => { | 26 | app.use((req, res) => { |
27 | matrix.core.received += 1; | 27 | matrix.core.received += 1; |
28 | res.end('OK'); | 28 | res.end('OK'); |
29 | 29 | ||
30 | const data = req.method === 'GET' ? req.query : req.body; | 30 | const data = req.method === 'GET' ? req.query : req.body; |
31 | sender(data, res.locals.xid); | 31 | sender(data, res.locals.xid); |
32 | }); | 32 | }); |
33 | 33 | ||
34 | const port = (config.listener && config.listener.core && config.listener.core.port) | 34 | const port = (config.listener && config.listener.core && config.listener.core.port) |
35 | || DEFAULT_LISTENER_FROM_CORE; | 35 | || DEFAULT_LISTENER_FROM_CORE; |
36 | 36 | ||
37 | app.listen(port, () => { | 37 | app.listen(port, () => { |
38 | logger.info(`${MODULE_NAME} 0375DC4E: Listen from CORE callback on port ${port}`); | 38 | logger.info(`${MODULE_NAME} 0375DC4E: Listen from CORE callback on port ${port}`); |
39 | }).on('error', (e) => { | 39 | }).on('error', (e) => { |
40 | logger.error(`${MODULE_NAME} A90E42D5: Can not listen CORE callback on port ${port}. ${e.toString()}`); | 40 | logger.error(`${MODULE_NAME} A90E42D5: Can not listen CORE callback on port ${port}. ${e.toString()}`); |
41 | process.exit(1); | 41 | process.exit(1); |
42 | }); | 42 | }); |
43 | 43 |
lib/core-callback/sender.js
1 | const MODULE_NAME = 'CORE-CALLBACK.SENDER'; | 1 | const MODULE_NAME = 'CORE-CALLBACK.SENDER'; |
2 | 2 | ||
3 | const axios = require('axios').default; | 3 | const axios = require('axios').default; |
4 | const config = require('komodo-sdk/config'); | 4 | const config = require('komodo-sdk/config'); |
5 | const logger = require('komodo-sdk/logger'); | 5 | const logger = require('tektrans-logger'); |
6 | 6 | ||
7 | const dumper = require('./dumper/sender'); | 7 | const dumper = require('./dumper/sender'); |
8 | const matrix = require('../matrix'); | 8 | const matrix = require('../matrix'); |
9 | 9 | ||
10 | const HTTP_TIMEOUT = Number( | 10 | const HTTP_TIMEOUT = Number( |
11 | config.callback_sender && config.callback_sender.http_timeout_ms, | 11 | config.callback_sender && config.callback_sender.http_timeout_ms, |
12 | ) || 30 * 1000; | 12 | ) || 30 * 1000; |
13 | 13 | ||
14 | const SLEEP_BEFORE_RETRY_MS = Number( | 14 | const SLEEP_BEFORE_RETRY_MS = Number( |
15 | config.callback_sender && config.callback_sender.sleep_before_retry_ms, | 15 | config.callback_sender && config.callback_sender.sleep_before_retry_ms, |
16 | ) || 10 * 1000; | 16 | ) || 10 * 1000; |
17 | 17 | ||
18 | const MAX_RETRY = Number( | 18 | const MAX_RETRY = Number( |
19 | config.callback_sender && config.callback_sender.max_retry, | 19 | config.callback_sender && config.callback_sender.max_retry, |
20 | ) || 10; | 20 | ) || 10; |
21 | 21 | ||
22 | logger.verbose(`${MODULE_NAME} 848B9104: Initialized`, { | 22 | logger.verbose(`${MODULE_NAME} 848B9104: Initialized`, { |
23 | HTTP_TIMEOUT, | 23 | HTTP_TIMEOUT, |
24 | SLEEP_BEFORE_RETRY_MS, | 24 | SLEEP_BEFORE_RETRY_MS, |
25 | MAX_RETRY, | 25 | MAX_RETRY, |
26 | }); | 26 | }); |
27 | 27 | ||
28 | const axiosHeaders = { | 28 | const axiosHeaders = { |
29 | 'Content-Type': 'application/json', | 29 | 'Content-Type': 'application/json', |
30 | 'User-Agent': 'KOMODO-HTTPGETX callback sender', | 30 | 'User-Agent': 'KOMODO-HTTPGETX callback sender', |
31 | }; | 31 | }; |
32 | 32 | ||
33 | const sleep = require('../sleep'); | 33 | const sleep = require('../sleep'); |
34 | const urlConcatQs = require('../url-concat-qs'); | 34 | const urlConcatQs = require('../url-concat-qs'); |
35 | 35 | ||
36 | const sender = async (data, xid, retry) => { | 36 | const sender = async (data, xid, retry) => { |
37 | if (!data.reverse_url) { | 37 | if (!data.reverse_url) { |
38 | logger.verbose(`${MODULE_NAME} C4FF18FB: Ignoring missing reverse url`, { | 38 | logger.verbose(`${MODULE_NAME} C4FF18FB: Ignoring missing reverse url`, { |
39 | xid, | 39 | xid, |
40 | dataFromCore: data, | 40 | dataFromCore: data, |
41 | }); | 41 | }); |
42 | 42 | ||
43 | return; | 43 | return; |
44 | } | 44 | } |
45 | 45 | ||
46 | const params = { | 46 | const params = { |
47 | httpgetx_xid: xid, | 47 | httpgetx_xid: xid, |
48 | command: data.command, | 48 | command: data.command, |
49 | 49 | ||
50 | request_id: data.request_id && data.request_id.toString(), | 50 | request_id: data.request_id && data.request_id.toString(), |
51 | transaction_id: data.transaction_id && data.transaction_id.toString(), | 51 | transaction_id: data.transaction_id && data.transaction_id.toString(), |
52 | transaction_date: data.transaction_date, | 52 | transaction_date: data.transaction_date, |
53 | 53 | ||
54 | store_name: data.store_name, | 54 | store_name: data.store_name, |
55 | terminal_name: data.terminal_name, | 55 | terminal_name: data.terminal_name, |
56 | 56 | ||
57 | product_name: data.product_name, | 57 | product_name: data.product_name, |
58 | destination: data.destination, | 58 | destination: data.destination, |
59 | 59 | ||
60 | rc: data.rc, | 60 | rc: data.rc, |
61 | sn: data.sn || undefined, | 61 | sn: data.sn || undefined, |
62 | amount: Number(data.amount) || undefined, | 62 | amount: Number(data.amount) || undefined, |
63 | ending_balance: Number(data.ending_balance) || undefined, | 63 | ending_balance: Number(data.ending_balance) || undefined, |
64 | 64 | ||
65 | message: data.message, | 65 | message: data.message, |
66 | 66 | ||
67 | bill_count: Number(data.bill_count) || undefined, | 67 | bill_count: Number(data.bill_count) || undefined, |
68 | bill_amount: Number(data.bill_amount) || undefined, | 68 | bill_amount: Number(data.bill_amount) || undefined, |
69 | fee_per_bill: Number(data.fee) || undefined, | 69 | fee_per_bill: Number(data.fee) || undefined, |
70 | fee_total: Number(data.fee_total) || undefined, | 70 | fee_total: Number(data.fee_total) || undefined, |
71 | 71 | ||
72 | bill_detail: data.bill_detail || undefined, | 72 | bill_detail: data.bill_detail || undefined, |
73 | struk: data.struk || undefined, | 73 | struk: data.struk || undefined, |
74 | }; | 74 | }; |
75 | 75 | ||
76 | if (data.command === 'INQUIRY' && data.amount_to_charge) { | 76 | if (data.command === 'INQUIRY' && data.amount_to_charge) { |
77 | params.amount_to_charge = data.amount_to_charge; | 77 | params.amount_to_charge = data.amount_to_charge; |
78 | } | 78 | } |
79 | 79 | ||
80 | const isPostpaid = ['INQUIRY', 'PAY'].indexOf(data.command) >= 0; | 80 | const isPostpaid = ['INQUIRY', 'PAY'].indexOf(data.command) >= 0; |
81 | const isHttpPost = isPostpaid; | 81 | const isHttpPost = isPostpaid; |
82 | 82 | ||
83 | const endpointUrl = isHttpPost ? data.reverse_url : urlConcatQs(data.reverse_url, params); | 83 | const endpointUrl = isHttpPost ? data.reverse_url : urlConcatQs(data.reverse_url, params); |
84 | 84 | ||
85 | logger.info(`${MODULE_NAME} 8B6A4CEC: Sending to PARTNER`, { | 85 | logger.info(`${MODULE_NAME} 8B6A4CEC: Sending to PARTNER`, { |
86 | xid, | 86 | xid, |
87 | retry, | 87 | retry, |
88 | isPostpaid, | 88 | isPostpaid, |
89 | isHttpPost, | 89 | isHttpPost, |
90 | endpointUrl, | 90 | endpointUrl, |
91 | }); | 91 | }); |
92 | 92 | ||
93 | let responseToDump; | 93 | let responseToDump; |
94 | let errorResponseToDump; | 94 | let errorResponseToDump; |
95 | 95 | ||
96 | try { | 96 | try { |
97 | const response = isHttpPost | 97 | const response = isHttpPost |
98 | ? await axios.post(data.reverse_url, params, { | 98 | ? await axios.post(data.reverse_url, params, { |
99 | timeout: HTTP_TIMEOUT, | 99 | timeout: HTTP_TIMEOUT, |
100 | headers: axiosHeaders, | 100 | headers: axiosHeaders, |
101 | }) | 101 | }) |
102 | : await axios.get(data.reverse_url, { | 102 | : await axios.get(data.reverse_url, { |
103 | params, | 103 | params, |
104 | timeout: HTTP_TIMEOUT, | 104 | timeout: HTTP_TIMEOUT, |
105 | headers: axiosHeaders, | 105 | headers: axiosHeaders, |
106 | }); | 106 | }); |
107 | 107 | ||
108 | responseToDump = response; | 108 | responseToDump = response; |
109 | 109 | ||
110 | matrix.callback_sender.sent += 1; | 110 | matrix.callback_sender.sent += 1; |
111 | matrix.callback_sender.active_count += 1; | 111 | matrix.callback_sender.active_count += 1; |
112 | matrix.callback_sender.active_sending[xid] = { | 112 | matrix.callback_sender.active_sending[xid] = { |
113 | ts: new Date(), | 113 | ts: new Date(), |
114 | trxId: data.trx_id, | 114 | trxId: data.trx_id, |
115 | reverseUrl: data.reverse_url, | 115 | reverseUrl: data.reverse_url, |
116 | }; | 116 | }; |
117 | 117 | ||
118 | if (isPostpaid) { | 118 | if (isPostpaid) { |
119 | matrix.callback_sender.sent_using_post += 1; | 119 | matrix.callback_sender.sent_using_post += 1; |
120 | } else { | 120 | } else { |
121 | matrix.callback_sender.sent_using_get += 1; | 121 | matrix.callback_sender.sent_using_get += 1; |
122 | } | 122 | } |
123 | 123 | ||
124 | logger.info(`${MODULE_NAME} 3641FBD7: Has been sent to PARTNER successfully`, { | 124 | logger.info(`${MODULE_NAME} 3641FBD7: Has been sent to PARTNER successfully`, { |
125 | xid, | 125 | xid, |
126 | retry, | 126 | retry, |
127 | httpStatus: response.status, | 127 | httpStatus: response.status, |
128 | responseBody: response && response.data, | 128 | responseBody: response && response.data, |
129 | }); | 129 | }); |
130 | } catch (e) { | 130 | } catch (e) { |
131 | matrix.callback_sender.sent_failed += 1; | 131 | matrix.callback_sender.sent_failed += 1; |
132 | matrix.callback_sender.last_error = { | 132 | matrix.callback_sender.last_error = { |
133 | xid, | 133 | xid, |
134 | ts: new Date(), | 134 | ts: new Date(), |
135 | eCode: e.code, | 135 | eCode: e.code, |
136 | eMessage: e.message, | 136 | eMessage: e.message, |
137 | trxId: data.trx_id, | 137 | trxId: data.trx_id, |
138 | reverseUrl: data.reverse_url, | 138 | reverseUrl: data.reverse_url, |
139 | httpStatus: e.response && e.response.status, | 139 | httpStatus: e.response && e.response.status, |
140 | responseBody: e.response && e.response.data, | 140 | responseBody: e.response && e.response.data, |
141 | }; | 141 | }; |
142 | 142 | ||
143 | responseToDump = e.response && e.response.data; | 143 | responseToDump = e.response && e.response.data; |
144 | errorResponseToDump = e; | 144 | errorResponseToDump = e; |
145 | 145 | ||
146 | logger.warn(`${MODULE_NAME} A1EC9E70: Failed on sending to PARTNER`, { | 146 | logger.warn(`${MODULE_NAME} A1EC9E70: Failed on sending to PARTNER`, { |
147 | xid, | 147 | xid, |
148 | retry, | 148 | retry, |
149 | maxRetry: MAX_RETRY, | 149 | maxRetry: MAX_RETRY, |
150 | errCode: e.code, | 150 | errCode: e.code, |
151 | errMessage: e.message, | 151 | errMessage: e.message, |
152 | reverseUrl: data.reverse_url, | 152 | reverseUrl: data.reverse_url, |
153 | endpointUrl, | 153 | endpointUrl, |
154 | httpStatus: e.response && e.response.status, | 154 | httpStatus: e.response && e.response.status, |
155 | responseBody: e.response && e.response.data, | 155 | responseBody: e.response && e.response.data, |
156 | }); | 156 | }); |
157 | 157 | ||
158 | if ((retry || 0) < MAX_RETRY) { | 158 | if ((retry || 0) < MAX_RETRY) { |
159 | await sleep(SLEEP_BEFORE_RETRY_MS); | 159 | await sleep(SLEEP_BEFORE_RETRY_MS); |
160 | logger.verbose(`${MODULE_NAME} D8958695: Going to retry sending CORE-CALLBACK TO PARTNER`, { | 160 | logger.verbose(`${MODULE_NAME} D8958695: Going to retry sending CORE-CALLBACK TO PARTNER`, { |
161 | xid, sleepTime: SLEEP_BEFORE_RETRY_MS, | 161 | xid, sleepTime: SLEEP_BEFORE_RETRY_MS, |
162 | }); | 162 | }); |
163 | sender(data, xid, (retry || 0) + 1); | 163 | sender(data, xid, (retry || 0) + 1); |
164 | } | 164 | } |
165 | } finally { | 165 | } finally { |
166 | matrix.callback_sender.active_count -= 1; | 166 | matrix.callback_sender.active_count -= 1; |
167 | if (matrix.callback_sender.active_sending[xid]) { | 167 | if (matrix.callback_sender.active_sending[xid]) { |
168 | delete matrix.callback_sender.active_sending[xid]; | 168 | delete matrix.callback_sender.active_sending[xid]; |
169 | } | 169 | } |
170 | 170 | ||
171 | dumper( | 171 | dumper( |
172 | xid, | 172 | xid, |
173 | isHttpPost ? 'POST' : 'GET', | 173 | isHttpPost ? 'POST' : 'GET', |
174 | endpointUrl, | 174 | endpointUrl, |
175 | params, | 175 | params, |
176 | responseToDump, | 176 | responseToDump, |
177 | errorResponseToDump, | 177 | errorResponseToDump, |
178 | ); | 178 | ); |
179 | } | 179 | } |
180 | }; | 180 | }; |
181 | 181 | ||
182 | module.exports = sender; | 182 | module.exports = sender; |
183 | 183 |
lib/coreapi.js
1 | const request = require('request'); | 1 | const request = require('request'); |
2 | 2 | ||
3 | const logger = require('komodo-sdk/logger'); | 3 | const logger = require('tektrans-logger'); |
4 | const coreUrl = require('komodo-sdk/core-url'); | 4 | const coreUrl = require('komodo-sdk/core-url'); |
5 | 5 | ||
6 | logger.verbose(`CORE URL: ${coreUrl}`); | 6 | logger.verbose(`CORE URL: ${coreUrl}`); |
7 | 7 | ||
8 | function doRequest(params, cb) { | 8 | function doRequest(params, cb) { |
9 | return new Promise((resolve) => { | 9 | return new Promise((resolve) => { |
10 | const options = { | 10 | const options = { |
11 | url: `${coreUrl}/${params.path.replace(/^\/+/, '')}`, | 11 | url: `${coreUrl}/${params.path.replace(/^\/+/, '')}`, |
12 | method: params.method || 'GET', | 12 | method: params.method || 'GET', |
13 | qs: params.qs || null, | 13 | qs: params.qs || null, |
14 | }; | 14 | }; |
15 | 15 | ||
16 | logger.verbose('Requesting to CORE', { | 16 | logger.verbose('Requesting to CORE', { |
17 | xid: params.xid, method: options.method, fullpath: options.url, qs: options.qs, | 17 | xid: params.xid, method: options.method, fullpath: options.url, qs: options.qs, |
18 | }); | 18 | }); |
19 | 19 | ||
20 | request(options, (err, res, body) => { | 20 | request(options, (err, res, body) => { |
21 | if (err) { | 21 | if (err) { |
22 | logger.warn(`COREAPI: Error doing HTTP ${options.method} to CORE. ${err.toString()}`, { xid: params.xid }); | 22 | logger.warn(`COREAPI: Error doing HTTP ${options.method} to CORE. ${err.toString()}`, { xid: params.xid }); |
23 | resolve(null); | 23 | resolve(null); |
24 | if (typeof cb === 'function') cb(err); | 24 | if (typeof cb === 'function') cb(err); |
25 | return; | 25 | return; |
26 | } | 26 | } |
27 | 27 | ||
28 | if (res.statusCode !== 200) { | 28 | if (res.statusCode !== 200) { |
29 | logger.warn(`COREAPI: CORE returning HTTP STATUS CODE ${res.statusCode}, not 200`, { xid: params.xid, body }); | 29 | logger.warn(`COREAPI: CORE returning HTTP STATUS CODE ${res.statusCode}, not 200`, { xid: params.xid, body }); |
30 | resolve(null); | 30 | resolve(null); |
31 | if (typeof cb === 'function') cb('NON_HTTP_STATUS_200'); | 31 | if (typeof cb === 'function') cb('NON_HTTP_STATUS_200'); |
32 | return; | 32 | return; |
33 | } | 33 | } |
34 | 34 | ||
35 | let bodyObject; | 35 | let bodyObject; |
36 | try { | 36 | try { |
37 | bodyObject = JSON.parse(body); | 37 | bodyObject = JSON.parse(body); |
38 | } catch (e) { | 38 | } catch (e) { |
39 | logger.verbose('COREAPI: CORE respond is not a JSON string'); | 39 | logger.verbose('COREAPI: CORE respond is not a JSON string'); |
40 | resolve(body); | 40 | resolve(body); |
41 | if (typeof cb === 'function') cb(e, body); | 41 | if (typeof cb === 'function') cb(e, body); |
42 | return; | 42 | return; |
43 | } | 43 | } |
44 | 44 | ||
45 | resolve(bodyObject); | 45 | resolve(bodyObject); |
46 | if (typeof cb === 'function') cb(null, bodyObject); | 46 | if (typeof cb === 'function') cb(null, bodyObject); |
47 | }); | 47 | }); |
48 | }); | 48 | }); |
49 | } | 49 | } |
50 | 50 | ||
51 | module.exports = doRequest; | 51 | module.exports = doRequest; |
52 | 52 |
lib/middlewares/common.js
1 | const MODULE_NAME = 'MIDDLEWARES'; | 1 | const MODULE_NAME = 'MIDDLEWARES'; |
2 | 2 | ||
3 | const uuidv1 = require('uuid/v1'); | 3 | const uuidv1 = require('uuid/v1'); |
4 | const uniqid = require('uniqid'); | 4 | const uniqid = require('uniqid'); |
5 | 5 | ||
6 | const config = require('komodo-sdk/config'); | 6 | const config = require('komodo-sdk/config'); |
7 | const logger = require('komodo-sdk/logger'); | 7 | const logger = require('tektrans-logger'); |
8 | 8 | ||
9 | module.exports = function common(req, res, next) { | 9 | module.exports = function common(req, res, next) { |
10 | if (req.url.search('/favicon.ico') === 0) { | 10 | if (req.url.search('/favicon.ico') === 0) { |
11 | res.sendStatus(404); | 11 | res.sendStatus(404); |
12 | return; | 12 | return; |
13 | } | 13 | } |
14 | 14 | ||
15 | res.locals.xid = config.xid_from_uuid ? uuidv1() | 15 | res.locals.xid = config.xid_from_uuid ? uuidv1() |
16 | : uniqid(); | 16 | : uniqid(); |
17 | 17 | ||
18 | res.locals.x_http_request_ts = new Date(); | 18 | res.locals.x_http_request_ts = new Date(); |
19 | 19 | ||
20 | logger.info(`${MODULE_NAME}.COMMON B6257542: Got a request`, { | 20 | logger.info(`${MODULE_NAME}.COMMON B6257542: Got a request`, { |
21 | xid: res.locals.xid, | 21 | xid: res.locals.xid, |
22 | pid: process.pid, | 22 | pid: process.pid, |
23 | subsystem: res.locals.httpgetx_subsystem, | 23 | subsystem: res.locals.httpgetx_subsystem, |
24 | requester_ip: req.ip, | 24 | requester_ip: req.ip, |
25 | method: req.method, | 25 | method: req.method, |
26 | path: req.path, | 26 | path: req.path, |
27 | url: req.url, | 27 | url: req.url, |
28 | qs: req.query, | 28 | qs: req.query, |
29 | body: req.body, | 29 | body: req.body, |
30 | }); | 30 | }); |
31 | next(); | 31 | next(); |
32 | }; | 32 | }; |
33 | 33 |
lib/partner-listener/dumper/index.js
1 | const MODULE_NAME = 'PARTNER-LISTENER.DUMPER'; | 1 | const MODULE_NAME = 'PARTNER-LISTENER.DUMPER'; |
2 | 2 | ||
3 | const fsPromise = require('fs').promises; | 3 | const fsPromise = require('fs').promises; |
4 | const path = require('path'); | 4 | const path = require('path'); |
5 | const moment = require('moment'); | 5 | const moment = require('moment'); |
6 | const config = require('komodo-sdk/config'); | 6 | const config = require('komodo-sdk/config'); |
7 | const logger = require('komodo-sdk/logger'); | 7 | const logger = require('tektrans-logger'); |
8 | 8 | ||
9 | const mkdirIfNotExists = require('../../utils/mkdir-if-not-exists'); | 9 | const mkdirIfNotExists = require('../../utils/mkdir-if-not-exists'); |
10 | 10 | ||
11 | const baseDumpDir = path.join('dump', 'partner-listener'); | 11 | const baseDumpDir = path.join('dump', 'partner-listener'); |
12 | const lastDumpFileName = path.join(baseDumpDir, 'last'); | 12 | const lastDumpFileName = path.join(baseDumpDir, 'last'); |
13 | 13 | ||
14 | module.exports = async (xid, req, responseBody) => { | 14 | module.exports = async (xid, req, responseBody) => { |
15 | if ( | 15 | if ( |
16 | !config | 16 | !config |
17 | || !config.listener | 17 | || !config.listener |
18 | || !config.listener.partner | 18 | || !config.listener.partner |
19 | || !config.listener.partner.dump | 19 | || !config.listener.partner.dump |
20 | ) return; | 20 | ) return; |
21 | 21 | ||
22 | const data = `-------- | 22 | const data = `-------- |
23 | XID: ${xid} | 23 | XID: ${xid} |
24 | TS: ${moment().format('YYYY-MM-DD HH:mm:ss')} | 24 | TS: ${moment().format('YYYY-MM-DD HH:mm:ss')} |
25 | 25 | ||
26 | REQ FROM: ${req.ip} | 26 | REQ FROM: ${req.ip} |
27 | REQ CONTENT-TYPE: ${req.get('content-type')} | 27 | REQ CONTENT-TYPE: ${req.get('content-type')} |
28 | REQ METHOD: ${req.method} | 28 | REQ METHOD: ${req.method} |
29 | REQ URL: ${req.url} | 29 | REQ URL: ${req.url} |
30 | 30 | ||
31 | REQ QUERY-STRING: | 31 | REQ QUERY-STRING: |
32 | ${JSON.stringify(req.query, null, 2)} | 32 | ${JSON.stringify(req.query, null, 2)} |
33 | 33 | ||
34 | REQ BODY: | 34 | REQ BODY: |
35 | ${typeof req.body === 'string' ? req.body : JSON.stringify(req.body, null, 2)} | 35 | ${typeof req.body === 'string' ? req.body : JSON.stringify(req.body, null, 2)} |
36 | 36 | ||
37 | RES BODY: | 37 | RES BODY: |
38 | ${typeof responseBody === 'string' ? responseBody : JSON.stringify(responseBody, null, 2)} | 38 | ${typeof responseBody === 'string' ? responseBody : JSON.stringify(responseBody, null, 2)} |
39 | `; | 39 | `; |
40 | 40 | ||
41 | const dumpFileName = path.join( | 41 | const dumpFileName = path.join( |
42 | baseDumpDir, | 42 | baseDumpDir, |
43 | moment().format('YYYY-MM-DD'), | 43 | moment().format('YYYY-MM-DD'), |
44 | [ | 44 | [ |
45 | moment().format('YYMMDD_HHmmss_SSS'), | 45 | moment().format('YYMMDD_HHmmss_SSS'), |
46 | xid, | 46 | xid, |
47 | ].join('_'), | 47 | ].join('_'), |
48 | ); | 48 | ); |
49 | 49 | ||
50 | try { | 50 | try { |
51 | await mkdirIfNotExists(xid, path.dirname(dumpFileName), MODULE_NAME); | 51 | await mkdirIfNotExists(xid, path.dirname(dumpFileName), MODULE_NAME); |
52 | await fsPromise.writeFile(lastDumpFileName, data); | 52 | await fsPromise.writeFile(lastDumpFileName, data); |
53 | await fsPromise.writeFile(dumpFileName, data); | 53 | await fsPromise.writeFile(dumpFileName, data); |
54 | } catch (e) { | 54 | } catch (e) { |
55 | logger.warn(`${MODULE_NAME} FBC46420: Exception on dumping file`, { | 55 | logger.warn(`${MODULE_NAME} FBC46420: Exception on dumping file`, { |
56 | xid, | 56 | xid, |
57 | eCode: e.code, | 57 | eCode: e.code, |
58 | eMessage: e.eMessage, | 58 | eMessage: e.eMessage, |
59 | }); | 59 | }); |
60 | } | 60 | } |
61 | }; | 61 | }; |
62 | 62 |
lib/partner-listener/index.js
1 | const MODULE_NAME = 'PARTNER-LISTENER'; | 1 | const MODULE_NAME = 'PARTNER-LISTENER'; |
2 | 2 | ||
3 | const DEFAULT_LISTENER_FROM_PARTNER_PORT = 25614; | 3 | const DEFAULT_LISTENER_FROM_PARTNER_PORT = 25614; |
4 | 4 | ||
5 | const express = require('express'); | 5 | const express = require('express'); |
6 | 6 | ||
7 | const config = require('komodo-sdk/config'); | 7 | const config = require('komodo-sdk/config'); |
8 | const logger = require('komodo-sdk/logger'); | 8 | const logger = require('tektrans-logger'); |
9 | 9 | ||
10 | const middlewareCommon = require('../middlewares/common'); | 10 | const middlewareCommon = require('../middlewares/common'); |
11 | 11 | ||
12 | const routerInquiry = require('./routers/inquiry'); | 12 | const routerInquiry = require('./routers/inquiry'); |
13 | const routerPay = require('./routers/pay'); | 13 | const routerPay = require('./routers/pay'); |
14 | const routerTopup = require('./routers/topup'); | 14 | const routerTopup = require('./routers/topup'); |
15 | const routerTrxStatus = require('./routers/trx-status'); | 15 | const routerTrxStatus = require('./routers/trx-status'); |
16 | 16 | ||
17 | const app = express(); | 17 | const app = express(); |
18 | 18 | ||
19 | if (config.partner && config.partner.trust_proxy) { | 19 | if (config.partner && config.partner.trust_proxy) { |
20 | app.set('trust proxy', config.partner.trust_proxy); | 20 | app.set('trust proxy', config.partner.trust_proxy); |
21 | } | 21 | } |
22 | 22 | ||
23 | app.use((req, res, next) => { | 23 | app.use((req, res, next) => { |
24 | res.locals.httpgetx_subsystem = MODULE_NAME; | 24 | res.locals.httpgetx_subsystem = MODULE_NAME; |
25 | next(); | 25 | next(); |
26 | }); | 26 | }); |
27 | 27 | ||
28 | app.use(express.json({ extended: true })); | 28 | app.use(express.json({ extended: true })); |
29 | app.use(express.urlencoded({ extended: true })); | 29 | app.use(express.urlencoded({ extended: true })); |
30 | app.use(middlewareCommon); | 30 | app.use(middlewareCommon); |
31 | 31 | ||
32 | app.use('/ping', (req, res) => { | 32 | app.use('/ping', (req, res) => { |
33 | res.json({ | 33 | res.json({ |
34 | error: false, | 34 | error: false, |
35 | xid: res.locals.xid, | 35 | xid: res.locals.xid, |
36 | from_ip: req.ip, | 36 | from_ip: req.ip, |
37 | ts: new Date(), | 37 | ts: new Date(), |
38 | request: { | 38 | request: { |
39 | method: req.method, | 39 | method: req.method, |
40 | userAgent: req.get('user-agent'), | 40 | userAgent: req.get('user-agent'), |
41 | contentType: req.get('content-type'), | 41 | contentType: req.get('content-type'), |
42 | qs: req.query, | 42 | qs: req.query, |
43 | body: req.body, | 43 | body: req.body, |
44 | }, | 44 | }, |
45 | }); | 45 | }); |
46 | }); | 46 | }); |
47 | app.use('/inquiry', routerInquiry); | 47 | app.use('/inquiry', routerInquiry); |
48 | app.use('/pay', routerPay); | 48 | app.use('/pay', routerPay); |
49 | app.use('/topup', routerTopup); | 49 | app.use('/topup', routerTopup); |
50 | app.use('/trx-status', routerTrxStatus); | 50 | app.use('/trx-status', routerTrxStatus); |
51 | app.use('/', routerTopup); | 51 | app.use('/', routerTopup); |
52 | 52 | ||
53 | app.use((req, res) => { | 53 | app.use((req, res) => { |
54 | const { xid } = res.locals; | 54 | const { xid } = res.locals; |
55 | res.status(404).end(`KOMODO-HTTP-GET-X CENTER.\n404: Method not found.\n\nXID: ${xid}.\n`); | 55 | res.status(404).end(`KOMODO-HTTP-GET-X CENTER.\n404: Method not found.\n\nXID: ${xid}.\n`); |
56 | }); | 56 | }); |
57 | 57 | ||
58 | app.listen(config.listener.partner.port || DEFAULT_LISTENER_FROM_PARTNER_PORT, () => { | 58 | app.listen(config.listener.partner.port || DEFAULT_LISTENER_FROM_PARTNER_PORT, () => { |
59 | logger.info(`Listen from partner request on port ${config.listener.partner.port}`); | 59 | logger.info(`Listen from partner request on port ${config.listener.partner.port}`); |
60 | }).on('error', (e) => { | 60 | }).on('error', (e) => { |
61 | logger.error(`Can not listen request from partner on port ${config.listener.partner.port || DEFAULT_LISTENER_FROM_PARTNER_PORT}. ${e.toString()}`); | 61 | logger.error(`Can not listen request from partner on port ${config.listener.partner.port || DEFAULT_LISTENER_FROM_PARTNER_PORT}. ${e.toString()}`); |
62 | process.exit(1); | 62 | process.exit(1); |
63 | }); | 63 | }); |
64 | 64 |
lib/partner-listener/routers/inquiry.js
1 | const axios = require('axios').default; | 1 | const axios = require('axios').default; |
2 | const express = require('express'); | 2 | const express = require('express'); |
3 | const coreUrl = require('komodo-sdk/core-url'); | 3 | const coreUrl = require('komodo-sdk/core-url'); |
4 | 4 | ||
5 | const config = require('komodo-sdk/config'); | 5 | const config = require('komodo-sdk/config'); |
6 | const logger = require('komodo-sdk/logger'); | 6 | const logger = require('tektrans-logger'); |
7 | 7 | ||
8 | const getFromBodyQsParams = require('../../get-from-body-qs-params'); | 8 | const getFromBodyQsParams = require('../../get-from-body-qs-params'); |
9 | const ipv6ToIpv4 = require('../../ipv6-to-ipv4'); | 9 | const ipv6ToIpv4 = require('../../ipv6-to-ipv4'); |
10 | const dumper = require('../dumper'); | 10 | const dumper = require('../dumper'); |
11 | 11 | ||
12 | const router = express.Router(); | 12 | const router = express.Router(); |
13 | module.exports = router; | 13 | module.exports = router; |
14 | 14 | ||
15 | const CORE_ENDPOINT = `${coreUrl}/postpaid2/inquiry`; | 15 | const CORE_ENDPOINT = `${coreUrl}/postpaid2/inquiry`; |
16 | 16 | ||
17 | const mainHandler = async (req, res) => { | 17 | const mainHandler = async (req, res) => { |
18 | const { xid } = res.locals; | 18 | const { xid } = res.locals; |
19 | 19 | ||
20 | const requestId = (getFromBodyQsParams(req, 'request_id') || '').toString().trim(); | 20 | const requestId = (getFromBodyQsParams(req, 'request_id') || '').toString().trim(); |
21 | const terminalNameWithoutIp = (getFromBodyQsParams(req, 'terminal_name') || '').toString().trim(); | 21 | const terminalNameWithoutIp = (getFromBodyQsParams(req, 'terminal_name') || '').toString().trim(); |
22 | const terminalName = `${terminalNameWithoutIp}@${ipv6ToIpv4(req.ip)}`; | 22 | const terminalName = `${terminalNameWithoutIp}@${ipv6ToIpv4(req.ip)}`; |
23 | const productName = (getFromBodyQsParams(req, 'product_name') || '').trim().toUpperCase(); | 23 | const productName = (getFromBodyQsParams(req, 'product_name') || '').trim().toUpperCase(); |
24 | const destination = (getFromBodyQsParams(req, 'destination') || '').toString().trim(); | 24 | const destination = (getFromBodyQsParams(req, 'destination') || '').toString().trim(); |
25 | const password = getFromBodyQsParams(req, 'password'); | 25 | const password = getFromBodyQsParams(req, 'password'); |
26 | const reverseUrl = getFromBodyQsParams(req, 'reverse_url'); | 26 | const reverseUrl = getFromBodyQsParams(req, 'reverse_url'); |
27 | 27 | ||
28 | if (!requestId || !terminalNameWithoutIp || !productName || !destination) { | 28 | if (!requestId || !terminalNameWithoutIp || !productName || !destination) { |
29 | const msg = 'INVALID REQUEST. Missing request_id or terminal_name or product_name or destination.'; | 29 | const msg = 'INVALID REQUEST. Missing request_id or terminal_name or product_name or destination.'; |
30 | res.end(msg); | 30 | res.end(msg); |
31 | 31 | ||
32 | dumper(xid, req, msg); | 32 | dumper(xid, req, msg); |
33 | return; | 33 | return; |
34 | } | 34 | } |
35 | 35 | ||
36 | const params = { | 36 | const params = { |
37 | origin: config.name, | 37 | origin: config.name, |
38 | report_ip: config.listener.core.from_ip, | 38 | report_ip: config.listener.core.from_ip, |
39 | report_port: config.listener.core.port || 25614, | 39 | report_port: config.listener.core.port || 25614, |
40 | request_id: requestId, | 40 | request_id: requestId, |
41 | terminal_name: terminalName, | 41 | terminal_name: terminalName, |
42 | product_name: productName, | 42 | product_name: productName, |
43 | destination, | 43 | destination, |
44 | terminal_password: password, | 44 | terminal_password: password, |
45 | reverse_url: reverseUrl, | 45 | reverse_url: reverseUrl, |
46 | }; | 46 | }; |
47 | 47 | ||
48 | logger.info('Forwarding INQUIRY request to CORE', { xid, params }); | 48 | logger.info('Forwarding INQUIRY request to CORE', { xid, params }); |
49 | try { | 49 | try { |
50 | const result = await axios.get(CORE_ENDPOINT, { | 50 | const result = await axios.get(CORE_ENDPOINT, { |
51 | params, | 51 | params, |
52 | timeout: 10000, | 52 | timeout: 10000, |
53 | }); | 53 | }); |
54 | 54 | ||
55 | if (!result || !result.data) { | 55 | if (!result || !result.data) { |
56 | const newError = new Error('8002EB0D: Empty CORE INQUIRY direct-response'); | 56 | const newError = new Error('8002EB0D: Empty CORE INQUIRY direct-response'); |
57 | logger.warn(newError.message, { xid }); | 57 | logger.warn(newError.message, { xid }); |
58 | throw newError; | 58 | throw newError; |
59 | } | 59 | } |
60 | 60 | ||
61 | logger.verbose('Got INQUIRY direct-response from CORE', { | 61 | logger.verbose('Got INQUIRY direct-response from CORE', { |
62 | xid, | 62 | xid, |
63 | coreResponse: result.data, | 63 | coreResponse: result.data, |
64 | }); | 64 | }); |
65 | 65 | ||
66 | const resultForPartner = { | 66 | const resultForPartner = { |
67 | httpgetx_xid: xid, | 67 | httpgetx_xid: xid, |
68 | command: result.data.command, | 68 | command: result.data.command, |
69 | request_id: result.data.request_id && result.data.request_id.toString(), | 69 | request_id: result.data.request_id && result.data.request_id.toString(), |
70 | transaction_id: result.data.transaction_id && result.data.transaction_id.toString(), | 70 | transaction_id: result.data.transaction_id && result.data.transaction_id.toString(), |
71 | transaction_date: result.data.transaction_date, | 71 | transaction_date: result.data.transaction_date, |
72 | store_name: result.data.store_name, | 72 | store_name: result.data.store_name, |
73 | terminal_name: result.data.terminal_name, | 73 | terminal_name: result.data.terminal_name, |
74 | product_name: result.data.product_name, | 74 | product_name: result.data.product_name, |
75 | destination: result.data.destination, | 75 | destination: result.data.destination, |
76 | rc: result.data.rc, | 76 | rc: result.data.rc, |
77 | sn: result.data.sn, | 77 | sn: result.data.sn, |
78 | message: result.data.message, | 78 | message: result.data.message, |
79 | amount: result.data.amount, | 79 | amount: result.data.amount, |
80 | ending_balance: result.data.ending_balance, | 80 | ending_balance: result.data.ending_balance, |
81 | amount_to_charge: result.data.amount_to_charge, | 81 | amount_to_charge: result.data.amount_to_charge, |
82 | }; | 82 | }; |
83 | 83 | ||
84 | logger.verbose('Forwarding CORE direct-response to partner', { | 84 | logger.verbose('Forwarding CORE direct-response to partner', { |
85 | xid, | 85 | xid, |
86 | resultForPartner, | 86 | resultForPartner, |
87 | }); | 87 | }); |
88 | 88 | ||
89 | res.json(resultForPartner); | 89 | res.json(resultForPartner); |
90 | 90 | ||
91 | dumper(xid, req, resultForPartner); | 91 | dumper(xid, req, resultForPartner); |
92 | } catch (e) { | 92 | } catch (e) { |
93 | logger.warn('EXCEPTION on forwarding INQUIRY request to CORE', { | 93 | logger.warn('EXCEPTION on forwarding INQUIRY request to CORE', { |
94 | xid, | 94 | xid, |
95 | errCode: e.code, | 95 | errCode: e.code, |
96 | errMessage: e.message, | 96 | errMessage: e.message, |
97 | }); | 97 | }); |
98 | 98 | ||
99 | const resultForPartner = { | 99 | const resultForPartner = { |
100 | httpgetx_xid: xid, | 100 | httpgetx_xid: xid, |
101 | command: 'INQUIRY', | 101 | command: 'INQUIRY', |
102 | request_id: requestId, | 102 | request_id: requestId, |
103 | terminal_name: terminalName, | 103 | terminal_name: terminalName, |
104 | product_name: productName, | 104 | product_name: productName, |
105 | destination, | 105 | destination, |
106 | rc: '68', | 106 | rc: '68', |
107 | message: 'CORE tidak merespon dengan benar, tidak dapat mengetahui status request anda', | 107 | message: 'CORE tidak merespon dengan benar, tidak dapat mengetahui status request anda', |
108 | }; | 108 | }; |
109 | 109 | ||
110 | res.json(resultForPartner); | 110 | res.json(resultForPartner); |
111 | dumper(xid, req, resultForPartner); | 111 | dumper(xid, req, resultForPartner); |
112 | } | 112 | } |
113 | }; | 113 | }; |
114 | 114 | ||
115 | router.all('/', mainHandler); | 115 | router.all('/', mainHandler); |
116 | 116 |
lib/partner-listener/routers/pay.js
1 | const axios = require('axios').default; | 1 | const axios = require('axios').default; |
2 | const express = require('express'); | 2 | const express = require('express'); |
3 | const coreUrl = require('komodo-sdk/core-url'); | 3 | const coreUrl = require('komodo-sdk/core-url'); |
4 | 4 | ||
5 | const config = require('komodo-sdk/config'); | 5 | const config = require('komodo-sdk/config'); |
6 | const logger = require('komodo-sdk/logger'); | 6 | const logger = require('tektrans-logger'); |
7 | 7 | ||
8 | const getFromBodyQsParams = require('../../get-from-body-qs-params'); | 8 | const getFromBodyQsParams = require('../../get-from-body-qs-params'); |
9 | const ipv6ToIpv4 = require('../../ipv6-to-ipv4'); | 9 | const ipv6ToIpv4 = require('../../ipv6-to-ipv4'); |
10 | const dumper = require('../dumper'); | 10 | const dumper = require('../dumper'); |
11 | 11 | ||
12 | const router = express.Router(); | 12 | const router = express.Router(); |
13 | module.exports = router; | 13 | module.exports = router; |
14 | 14 | ||
15 | const CORE_ENDPOINT = `${coreUrl}/postpaid2/pay`; | 15 | const CORE_ENDPOINT = `${coreUrl}/postpaid2/pay`; |
16 | 16 | ||
17 | const mainHandler = async (req, res) => { | 17 | const mainHandler = async (req, res) => { |
18 | const { xid } = res.locals; | 18 | const { xid } = res.locals; |
19 | 19 | ||
20 | const requestId = (getFromBodyQsParams(req, 'request_id') || '').toString().trim(); | 20 | const requestId = (getFromBodyQsParams(req, 'request_id') || '').toString().trim(); |
21 | const terminalNameWithoutIp = (getFromBodyQsParams(req, 'terminal_name') || '').toString().trim(); | 21 | const terminalNameWithoutIp = (getFromBodyQsParams(req, 'terminal_name') || '').toString().trim(); |
22 | const terminalName = `${terminalNameWithoutIp}@${ipv6ToIpv4(req.ip)}`; | 22 | const terminalName = `${terminalNameWithoutIp}@${ipv6ToIpv4(req.ip)}`; |
23 | const productName = (getFromBodyQsParams(req, 'product_name') || '').trim().toUpperCase(); | 23 | const productName = (getFromBodyQsParams(req, 'product_name') || '').trim().toUpperCase(); |
24 | const destination = (getFromBodyQsParams(req, 'destination') || '').toString().trim(); | 24 | const destination = (getFromBodyQsParams(req, 'destination') || '').toString().trim(); |
25 | const password = getFromBodyQsParams(req, 'password'); | 25 | const password = getFromBodyQsParams(req, 'password'); |
26 | const reverseUrl = getFromBodyQsParams(req, 'reverse_url'); | 26 | const reverseUrl = getFromBodyQsParams(req, 'reverse_url'); |
27 | 27 | ||
28 | if (!requestId || !terminalNameWithoutIp || !productName || !destination) { | 28 | if (!requestId || !terminalNameWithoutIp || !productName || !destination) { |
29 | const msg = 'INVALID REQUEST. Missing request_id or terminal_name or product_name or destination.'; | 29 | const msg = 'INVALID REQUEST. Missing request_id or terminal_name or product_name or destination.'; |
30 | res.end(msg); | 30 | res.end(msg); |
31 | dumper(xid, req, msg); | 31 | dumper(xid, req, msg); |
32 | return; | 32 | return; |
33 | } | 33 | } |
34 | 34 | ||
35 | const params = { | 35 | const params = { |
36 | origin: config.name, | 36 | origin: config.name, |
37 | report_ip: config.listener.core.from_ip, | 37 | report_ip: config.listener.core.from_ip, |
38 | report_port: config.listener.core.port || 25614, | 38 | report_port: config.listener.core.port || 25614, |
39 | request_id: requestId, | 39 | request_id: requestId, |
40 | terminal_name: terminalName, | 40 | terminal_name: terminalName, |
41 | product_name: productName, | 41 | product_name: productName, |
42 | destination, | 42 | destination, |
43 | terminal_password: password, | 43 | terminal_password: password, |
44 | reverse_url: reverseUrl, | 44 | reverse_url: reverseUrl, |
45 | }; | 45 | }; |
46 | 46 | ||
47 | logger.info('Forwarding PAY request to CORE', { xid, params }); | 47 | logger.info('Forwarding PAY request to CORE', { xid, params }); |
48 | try { | 48 | try { |
49 | const result = await axios.get(CORE_ENDPOINT, { | 49 | const result = await axios.get(CORE_ENDPOINT, { |
50 | params, | 50 | params, |
51 | timeout: 10000, | 51 | timeout: 10000, |
52 | }); | 52 | }); |
53 | 53 | ||
54 | if (!result || !result.data) { | 54 | if (!result || !result.data) { |
55 | const newError = new Error('0D428E4C: Empty CORE PAY direct-response'); | 55 | const newError = new Error('0D428E4C: Empty CORE PAY direct-response'); |
56 | logger.warn(newError.message, { xid }); | 56 | logger.warn(newError.message, { xid }); |
57 | throw newError; | 57 | throw newError; |
58 | } | 58 | } |
59 | 59 | ||
60 | logger.verbose('Got PAY direct-response from CORE', { | 60 | logger.verbose('Got PAY direct-response from CORE', { |
61 | xid, | 61 | xid, |
62 | coreResponse: result.data, | 62 | coreResponse: result.data, |
63 | }); | 63 | }); |
64 | 64 | ||
65 | const resultForPartner = { | 65 | const resultForPartner = { |
66 | httpgetx_xid: xid, | 66 | httpgetx_xid: xid, |
67 | command: result.data.command, | 67 | command: result.data.command, |
68 | request_id: result.data.request_id && result.data.request_id.toString(), | 68 | request_id: result.data.request_id && result.data.request_id.toString(), |
69 | transaction_id: result.data.transaction_id && result.data.transaction_id.toString(), | 69 | transaction_id: result.data.transaction_id && result.data.transaction_id.toString(), |
70 | transaction_date: result.data.transaction_date, | 70 | transaction_date: result.data.transaction_date, |
71 | store_name: result.data.store_name, | 71 | store_name: result.data.store_name, |
72 | terminal_name: result.data.terminal_name, | 72 | terminal_name: result.data.terminal_name, |
73 | product_name: result.data.product_name, | 73 | product_name: result.data.product_name, |
74 | destination: result.data.destination, | 74 | destination: result.data.destination, |
75 | rc: result.data.rc, | 75 | rc: result.data.rc, |
76 | sn: result.data.sn, | 76 | sn: result.data.sn, |
77 | message: result.data.message, | 77 | message: result.data.message, |
78 | amount: result.data.amount, | 78 | amount: result.data.amount, |
79 | ending_balance: result.data.ending_balance, | 79 | ending_balance: result.data.ending_balance, |
80 | }; | 80 | }; |
81 | 81 | ||
82 | logger.verbose('Forwarding CORE PAY direct-response to partner', { | 82 | logger.verbose('Forwarding CORE PAY direct-response to partner', { |
83 | xid, | 83 | xid, |
84 | resultForPartner, | 84 | resultForPartner, |
85 | }); | 85 | }); |
86 | 86 | ||
87 | res.json(resultForPartner); | 87 | res.json(resultForPartner); |
88 | dumper(xid, req, resultForPartner); | 88 | dumper(xid, req, resultForPartner); |
89 | } catch (e) { | 89 | } catch (e) { |
90 | logger.warn('EXCEPTION on forwarding PAY request to CORE', { | 90 | logger.warn('EXCEPTION on forwarding PAY request to CORE', { |
91 | xid, | 91 | xid, |
92 | errCode: e.code, | 92 | errCode: e.code, |
93 | errMessage: e.message, | 93 | errMessage: e.message, |
94 | }); | 94 | }); |
95 | 95 | ||
96 | const resultForPartner = { | 96 | const resultForPartner = { |
97 | httpgetx_xid: xid, | 97 | httpgetx_xid: xid, |
98 | command: 'PAY', | 98 | command: 'PAY', |
99 | request_id: requestId, | 99 | request_id: requestId, |
100 | terminal_name: terminalName, | 100 | terminal_name: terminalName, |
101 | product_name: productName, | 101 | product_name: productName, |
102 | destination, | 102 | destination, |
103 | rc: '68', | 103 | rc: '68', |
104 | message: 'CORE tidak merespon dengan benar, tidak dapat mengetahui status request anda', | 104 | message: 'CORE tidak merespon dengan benar, tidak dapat mengetahui status request anda', |
105 | }; | 105 | }; |
106 | 106 | ||
107 | dumper(xid, req, resultForPartner); | 107 | dumper(xid, req, resultForPartner); |
108 | } | 108 | } |
109 | }; | 109 | }; |
110 | 110 | ||
111 | router.all('/', mainHandler); | 111 | router.all('/', mainHandler); |
112 | 112 |
lib/partner-listener/routers/topup.js
1 | const MODULE_NAME = 'PARTNER-LISTENER.ROUTER.TOPUP'; | 1 | const MODULE_NAME = 'PARTNER-LISTENER.ROUTER.TOPUP'; |
2 | 2 | ||
3 | const express = require('express'); | 3 | const express = require('express'); |
4 | 4 | ||
5 | const config = require('komodo-sdk/config'); | 5 | const config = require('komodo-sdk/config'); |
6 | const logger = require('komodo-sdk/logger'); | 6 | const logger = require('tektrans-logger'); |
7 | const coreapi = require('komodo-sdk/coreapi'); | 7 | const coreapi = require('komodo-sdk/coreapi'); |
8 | // const coreapi = require('../../coreapi'); | 8 | // const coreapi = require('../../coreapi'); |
9 | const matrix = require('../../matrix'); | 9 | const matrix = require('../../matrix'); |
10 | const dumper = require('../dumper'); | 10 | const dumper = require('../dumper'); |
11 | 11 | ||
12 | const router = express.Router(); | 12 | const router = express.Router(); |
13 | module.exports = router; | 13 | module.exports = router; |
14 | 14 | ||
15 | function onInvalidParameter(missingParameter, req, res) { | 15 | function onInvalidParameter(missingParameter, req, res) { |
16 | logger.verbose(`${MODULE_NAME} 1536D577: Undefined ${missingParameter} parameter`, { | 16 | logger.verbose(`${MODULE_NAME} 1536D577: Undefined ${missingParameter} parameter`, { |
17 | xid: res.locals.xid, | 17 | xid: res.locals.xid, |
18 | ip: req.ip, | 18 | ip: req.ip, |
19 | terminal_name: req.body.terminal_name || req.query.terminal_name, | 19 | terminal_name: req.body.terminal_name || req.query.terminal_name, |
20 | request_id: req.body.request_id || req.query.request_id, | 20 | request_id: req.body.request_id || req.query.request_id, |
21 | product_name: req.body.product_name || req.query.product_name, | 21 | product_name: req.body.product_name || req.query.product_name, |
22 | destination: req.body.destination || req.query.destination, | 22 | destination: req.body.destination || req.query.destination, |
23 | }); | 23 | }); |
24 | res.end('INVALID REQUEST'); | 24 | res.end('INVALID REQUEST'); |
25 | } | 25 | } |
26 | 26 | ||
27 | function pagePrerequisite(req, res, next) { | 27 | function pagePrerequisite(req, res, next) { |
28 | if (!req.body) req.body = {}; | 28 | if (!req.body) req.body = {}; |
29 | 29 | ||
30 | if (!req.body.terminal_name && !req.query.terminal_name) { | 30 | if (!req.body.terminal_name && !req.query.terminal_name) { |
31 | onInvalidParameter('terminal_name', req, res); | 31 | onInvalidParameter('terminal_name', req, res); |
32 | return; | 32 | return; |
33 | } | 33 | } |
34 | 34 | ||
35 | if (!req.body.password && !req.query.password) { | 35 | if (!req.body.password && !req.query.password) { |
36 | onInvalidParameter('password', req, res); | 36 | onInvalidParameter('password', req, res); |
37 | return; | 37 | return; |
38 | } | 38 | } |
39 | 39 | ||
40 | if (!req.body.request_id && !req.query.request_id) { | 40 | if (!req.body.request_id && !req.query.request_id) { |
41 | onInvalidParameter('request_id', req, res); | 41 | onInvalidParameter('request_id', req, res); |
42 | return; | 42 | return; |
43 | } | 43 | } |
44 | 44 | ||
45 | if (!req.body.product_name && !req.query.product_name) { | 45 | if (!req.body.product_name && !req.query.product_name) { |
46 | onInvalidParameter('product_name', req, res); | 46 | onInvalidParameter('product_name', req, res); |
47 | return; | 47 | return; |
48 | } | 48 | } |
49 | 49 | ||
50 | if (!req.body.destination && !req.query.destination) { | 50 | if (!req.body.destination && !req.query.destination) { |
51 | onInvalidParameter('destination', req, res); | 51 | onInvalidParameter('destination', req, res); |
52 | return; | 52 | return; |
53 | } | 53 | } |
54 | 54 | ||
55 | next(); | 55 | next(); |
56 | } | 56 | } |
57 | 57 | ||
58 | async function pageIndex(req, res) { | 58 | async function pageIndex(req, res) { |
59 | const { xid } = res.locals; | 59 | const { xid } = res.locals; |
60 | 60 | ||
61 | const terminalName = `${req.body.terminal_name || req.query.terminal_name}@${req.ip.replace(/^::ffff:/, '')}`; | 61 | const terminalName = `${req.body.terminal_name || req.query.terminal_name}@${req.ip.replace(/^::ffff:/, '')}`; |
62 | 62 | ||
63 | matrix.core.sent += 1; | 63 | matrix.core.sent += 1; |
64 | 64 | ||
65 | const [err, coreResponse] = await coreapi({ | 65 | const [err, coreResponse] = await coreapi({ |
66 | xid, | 66 | xid, |
67 | path: '/prepaid/buy', | 67 | path: '/prepaid/buy', |
68 | qs: { | 68 | qs: { |
69 | terminal_name: terminalName, | 69 | terminal_name: terminalName, |
70 | password: req.body.password || req.query.password, | 70 | password: req.body.password || req.query.password, |
71 | request_id: req.body.request_id || req.query.request_id, | 71 | request_id: req.body.request_id || req.query.request_id, |
72 | product_name: req.body.product_name || req.query.product_name, | 72 | product_name: req.body.product_name || req.query.product_name, |
73 | destination: req.body.destination || req.query.destination, | 73 | destination: req.body.destination || req.query.destination, |
74 | origin: config.name || 'HTTPGETX', | 74 | origin: config.name || 'HTTPGETX', |
75 | report_ip: config.listener.core.ip || null, | 75 | report_ip: config.listener.core.ip || null, |
76 | report_port: config.listener.core.port, | 76 | report_port: config.listener.core.port, |
77 | reverse_url: req.body.reverse_url || req.query.reverse_url || null, | 77 | reverse_url: req.body.reverse_url || req.query.reverse_url || null, |
78 | }, | 78 | }, |
79 | }); | 79 | }); |
80 | 80 | ||
81 | if (err || !coreResponse) { | 81 | if (err || !coreResponse) { |
82 | matrix.core.sent_failed += 1; | 82 | matrix.core.sent_failed += 1; |
83 | matrix.core.last_error = { | 83 | matrix.core.last_error = { |
84 | xid, | 84 | xid, |
85 | ts: new Date(), | 85 | ts: new Date(), |
86 | e: err, | 86 | e: err, |
87 | eCode: err.code, | 87 | eCode: err.code, |
88 | eMessage: err.message, | 88 | eMessage: err.message, |
89 | }; | 89 | }; |
90 | 90 | ||
91 | logger.warn(`${MODULE_NAME} 8DEBE15F: ERROR on /prepaid/buy response`, { | 91 | logger.warn(`${MODULE_NAME} 8DEBE15F: ERROR on /prepaid/buy response`, { |
92 | xid, | 92 | xid, |
93 | err, | 93 | err, |
94 | coreResponseTypeof: typeof coreResponse, | 94 | coreResponseTypeof: typeof coreResponse, |
95 | coreResponse, | 95 | coreResponse, |
96 | }); | 96 | }); |
97 | res.end('INVALID CORE RESPONSE'); | 97 | res.end('INVALID CORE RESPONSE'); |
98 | 98 | ||
99 | dumper(xid, req, 'INVALID CORE RESPONSE'); | 99 | dumper(xid, req, 'INVALID CORE RESPONSE'); |
100 | return; | 100 | return; |
101 | } | 101 | } |
102 | 102 | ||
103 | logger.verbose(`${MODULE_NAME} 2528A9B4: Got CORE response`, { | 103 | logger.verbose(`${MODULE_NAME} 2528A9B4: Got CORE response`, { |
104 | xid, | 104 | xid, |
105 | coreResponse, | 105 | coreResponse, |
106 | }); | 106 | }); |
107 | 107 | ||
108 | const responseToPartner = { | 108 | const responseToPartner = { |
109 | httpgetx_xid: xid, | 109 | httpgetx_xid: xid, |
110 | request_id: coreResponse.request_id, | 110 | request_id: coreResponse.request_id, |
111 | transaction_id: coreResponse.transaction_id, | 111 | transaction_id: coreResponse.transaction_id, |
112 | transaction_date: coreResponse.transaction_date, | 112 | transaction_date: coreResponse.transaction_date, |
113 | store_name: coreResponse.store_name, | 113 | store_name: coreResponse.store_name, |
114 | terminal_name: coreResponse.terminal_name, | 114 | terminal_name: coreResponse.terminal_name, |
115 | product_name: coreResponse.product_name, | 115 | product_name: coreResponse.product_name, |
116 | destination: coreResponse.destination, | 116 | destination: coreResponse.destination, |
117 | rc: coreResponse.rc, | 117 | rc: coreResponse.rc, |
118 | sn: coreResponse.sn || undefined, | 118 | sn: coreResponse.sn || undefined, |
119 | amount: Number(coreResponse.amount) || undefined, | 119 | amount: Number(coreResponse.amount) || undefined, |
120 | ending_balance: Number(coreResponse.ending_balance) || undefined, | 120 | ending_balance: Number(coreResponse.ending_balance) || undefined, |
121 | message: coreResponse.message, | 121 | message: coreResponse.message, |
122 | }; | 122 | }; |
123 | 123 | ||
124 | res.json(responseToPartner); | 124 | res.json(responseToPartner); |
125 | dumper(xid, req, responseToPartner); | 125 | dumper(xid, req, responseToPartner); |
126 | } | 126 | } |
127 | 127 | ||
128 | // router.all('/', (req, res) => { res.status(404).end('404: Not implemented yet'); }); | 128 | // router.all('/', (req, res) => { res.status(404).end('404: Not implemented yet'); }); |
129 | router.get('/', pagePrerequisite, pageIndex); | 129 | router.get('/', pagePrerequisite, pageIndex); |
130 | 130 |
lib/partner-listener/routers/trx-status.js
1 | const MODULE_NAME = 'PARTNER-LISTENER.ROUTERS.TRX-STATUS'; | 1 | const MODULE_NAME = 'PARTNER-LISTENER.ROUTERS.TRX-STATUS'; |
2 | 2 | ||
3 | const express = require('express'); | 3 | const express = require('express'); |
4 | const moment = require('moment'); | 4 | const moment = require('moment'); |
5 | 5 | ||
6 | const logger = require('komodo-sdk/logger'); | 6 | const logger = require('tektrans-logger'); |
7 | 7 | ||
8 | const coreapi = require('../../coreapi'); | 8 | const coreapi = require('../../coreapi'); |
9 | const dumper = require('../dumper'); | 9 | const dumper = require('../dumper'); |
10 | 10 | ||
11 | const router = express.Router(); | 11 | const router = express.Router(); |
12 | module.exports = router; | 12 | module.exports = router; |
13 | 13 | ||
14 | async function pageIndex(req, res) { | 14 | async function pageIndex(req, res) { |
15 | const { xid } = res.locals; | 15 | const { xid } = res.locals; |
16 | if (!req.body) req.body = {}; | 16 | if (!req.body) req.body = {}; |
17 | 17 | ||
18 | if (!req.body.terminal_name && !req.query.terminal_name) { | 18 | if (!req.body.terminal_name && !req.query.terminal_name) { |
19 | const msg = 'Parameter terminal_name tidak terdefinisi'; | 19 | const msg = 'Parameter terminal_name tidak terdefinisi'; |
20 | res.json({ | 20 | res.json({ |
21 | httpgetx_xid: xid, | 21 | httpgetx_xid: xid, |
22 | error: true, | 22 | error: true, |
23 | message: msg, | 23 | message: msg, |
24 | }); | 24 | }); |
25 | 25 | ||
26 | dumper(xid, req, msg); | 26 | dumper(xid, req, msg); |
27 | return; | 27 | return; |
28 | } | 28 | } |
29 | 29 | ||
30 | if (!req.body.password && !req.query.password) { | 30 | if (!req.body.password && !req.query.password) { |
31 | const msg = 'Parameter password tidak terdefinisi'; | 31 | const msg = 'Parameter password tidak terdefinisi'; |
32 | res.json({ | 32 | res.json({ |
33 | httpgetx_xid: xid, | 33 | httpgetx_xid: xid, |
34 | error: true, | 34 | error: true, |
35 | message: msg, | 35 | message: msg, |
36 | }); | 36 | }); |
37 | 37 | ||
38 | dumper(xid, req, msg); | 38 | dumper(xid, req, msg); |
39 | return; | 39 | return; |
40 | } | 40 | } |
41 | 41 | ||
42 | if (!req.body.request_id && !req.query.request_id) { | 42 | if (!req.body.request_id && !req.query.request_id) { |
43 | const msg = 'Parameter request_id tidak terdefinisi'; | 43 | const msg = 'Parameter request_id tidak terdefinisi'; |
44 | res.json({ | 44 | res.json({ |
45 | httpgetx_xid: xid, | 45 | httpgetx_xid: xid, |
46 | error: true, | 46 | error: true, |
47 | message: msg, | 47 | message: msg, |
48 | }); | 48 | }); |
49 | 49 | ||
50 | dumper(xid, req, msg); | 50 | dumper(xid, req, msg); |
51 | return; | 51 | return; |
52 | } | 52 | } |
53 | 53 | ||
54 | const remoteIp = req.ip.replace(/^::ffff:/, ''); | 54 | const remoteIp = req.ip.replace(/^::ffff:/, ''); |
55 | const askerTerminalName = `${req.body.terminal_name || req.query.terminal_name}@${remoteIp}`; | 55 | const askerTerminalName = `${req.body.terminal_name || req.query.terminal_name}@${remoteIp}`; |
56 | 56 | ||
57 | const coreResponse = await coreapi({ | 57 | const coreResponse = await coreapi({ |
58 | xid, | 58 | xid, |
59 | path: '/trx-status/view', | 59 | path: '/trx-status/view', |
60 | qs: { | 60 | qs: { |
61 | asker_terminal_name: askerTerminalName, | 61 | asker_terminal_name: askerTerminalName, |
62 | asker_terminal_password: req.body.password || req.query.password, | 62 | asker_terminal_password: req.body.password || req.query.password, |
63 | request_id: req.body.request_id || req.query.request_id, | 63 | request_id: req.body.request_id || req.query.request_id, |
64 | }, | 64 | }, |
65 | }); | 65 | }); |
66 | 66 | ||
67 | if (!coreResponse || !coreResponse.status) { | 67 | if (!coreResponse || !coreResponse.status) { |
68 | const msg = 'Status transaksi tidak dapat diketahui karena suatu kesalahan pada sistem'; | 68 | const msg = 'Status transaksi tidak dapat diketahui karena suatu kesalahan pada sistem'; |
69 | 69 | ||
70 | logger.warn(`${MODULE_NAME} 9983DB34: ${msg}`, { | 70 | logger.warn(`${MODULE_NAME} 9983DB34: ${msg}`, { |
71 | xid, | 71 | xid, |
72 | ip: req.ip, | 72 | ip: req.ip, |
73 | terminal_name: req.body.terminal_name || req.query.terminal_name, | 73 | terminal_name: req.body.terminal_name || req.query.terminal_name, |
74 | request_id: req.body.request_id || req.query.request_id, | 74 | request_id: req.body.request_id || req.query.request_id, |
75 | }); | 75 | }); |
76 | 76 | ||
77 | const responseBody = { | 77 | const responseBody = { |
78 | httpgetx_xid: xid, | 78 | httpgetx_xid: xid, |
79 | error: true, | 79 | error: true, |
80 | from_ip: remoteIp, | 80 | from_ip: remoteIp, |
81 | terminal_name: req.body.terminal_name || req.query.terminal_name, | 81 | terminal_name: req.body.terminal_name || req.query.terminal_name, |
82 | full_terminal_name: askerTerminalName, | 82 | full_terminal_name: askerTerminalName, |
83 | password: req.body.password || req.query.password, | 83 | password: req.body.password || req.query.password, |
84 | message: msg, | 84 | message: msg, |
85 | }; | 85 | }; |
86 | 86 | ||
87 | res.json(responseBody); | 87 | res.json(responseBody); |
88 | dumper(xid, req, responseBody); | 88 | dumper(xid, req, responseBody); |
89 | 89 | ||
90 | return; | 90 | return; |
91 | } | 91 | } |
92 | 92 | ||
93 | const trx = coreResponse && coreResponse.result ? { | 93 | const trx = coreResponse && coreResponse.result ? { |
94 | id: coreResponse.result.id, | 94 | id: coreResponse.result.id, |
95 | request_id: coreResponse.result.request_id, | 95 | request_id: coreResponse.result.request_id, |
96 | store_id: coreResponse.result.store_id, | 96 | store_id: coreResponse.result.store_id, |
97 | store_name: coreResponse.result.store_name, | 97 | store_name: coreResponse.result.store_name, |
98 | terminal_id: coreResponse.result.terminal_id, | 98 | terminal_id: coreResponse.result.terminal_id, |
99 | terminal_name: coreResponse.result.terminal_name, | 99 | terminal_name: coreResponse.result.terminal_name, |
100 | 100 | ||
101 | created: moment(coreResponse.result.created).format('YYYY-MM-DD HH:mm:ss'), | 101 | created: moment(coreResponse.result.created).format('YYYY-MM-DD HH:mm:ss'), |
102 | modified: moment(coreResponse.result.modified).format('YYYY-MM-DD HH:mm:ss'), | 102 | modified: moment(coreResponse.result.modified).format('YYYY-MM-DD HH:mm:ss'), |
103 | 103 | ||
104 | product_name: coreResponse.result.product_name, | 104 | product_name: coreResponse.result.product_name, |
105 | destination: coreResponse.result.destination, | 105 | destination: coreResponse.result.destination, |
106 | amount: coreResponse.result.amount, | 106 | amount: coreResponse.result.amount, |
107 | ending_balance: coreResponse.result.ending_balance, | 107 | ending_balance: coreResponse.result.ending_balance, |
108 | rc: coreResponse.result.rc, | 108 | rc: coreResponse.result.rc, |
109 | message: coreResponse.result.reply_message, | 109 | message: coreResponse.result.reply_message, |
110 | sn: coreResponse.result.sn, | 110 | sn: coreResponse.result.sn, |
111 | } | 111 | } |
112 | : null; | 112 | : null; |
113 | 113 | ||
114 | const result = { | 114 | const result = { |
115 | httpgetx_xid: xid, | 115 | httpgetx_xid: xid, |
116 | error: coreResponse.status !== 'OK', | 116 | error: coreResponse.status !== 'OK', |
117 | from_ip: remoteIp, | 117 | from_ip: remoteIp, |
118 | terminal_name: req.body.terminal_name || req.query.terminal_name, | 118 | terminal_name: req.body.terminal_name || req.query.terminal_name, |
119 | full_terminal_name: askerTerminalName, | 119 | full_terminal_name: askerTerminalName, |
120 | message: coreResponse.message, | 120 | message: coreResponse.message, |
121 | trx_found: !!trx, | 121 | trx_found: !!trx, |
122 | trx, | 122 | trx, |
123 | // original_trx: coreResponse.result, | 123 | // original_trx: coreResponse.result, |
124 | }; | 124 | }; |
125 | 125 | ||
126 | res.json(result); | 126 | res.json(result); |
127 | 127 | ||
128 | logger.info(`${MODULE_NAME} 480C4BB0: Partner request responded`, { | 128 | logger.info(`${MODULE_NAME} 480C4BB0: Partner request responded`, { |
129 | xid, | 129 | xid, |
130 | processing_time_in_ms: new Date() - res.locals.x_http_request_ts, | 130 | processing_time_in_ms: new Date() - res.locals.x_http_request_ts, |
131 | result, | 131 | result, |
132 | }); | 132 | }); |
133 | 133 | ||
134 | dumper(xid, req, result); | 134 | dumper(xid, req, result); |
135 | } | 135 | } |
136 | 136 | ||
137 | router.get('/', pageIndex); | 137 | router.get('/', pageIndex); |
138 | 138 |
lib/utils/mkdir-if-not-exists.js
1 | const MODULE_NAME = 'MKDIR-IF-NOT-EXISTS'; | 1 | const MODULE_NAME = 'MKDIR-IF-NOT-EXISTS'; |
2 | 2 | ||
3 | const fsPromise = require('fs').promises; | 3 | const fsPromise = require('fs').promises; |
4 | const logger = require('komodo-sdk/logger'); | 4 | const logger = require('tektrans-logger'); |
5 | 5 | ||
6 | const mkdir = async (xid, dirname, callerName) => { | 6 | const mkdir = async (xid, dirname, callerName) => { |
7 | try { | 7 | try { |
8 | logger.verbose(`${MODULE_NAME} 6B08D52D: Creating directory`, { | 8 | logger.verbose(`${MODULE_NAME} 6B08D52D: Creating directory`, { |
9 | xid, dirname, callerName, | 9 | xid, dirname, callerName, |
10 | }); | 10 | }); |
11 | 11 | ||
12 | await fsPromise.mkdir(dirname, { recursive: true }); | 12 | await fsPromise.mkdir(dirname, { recursive: true }); |
13 | } catch (e) { | 13 | } catch (e) { |
14 | logger.warn(`${MODULE_NAME} 857718E9: Exception on creating directory`, { | 14 | logger.warn(`${MODULE_NAME} 857718E9: Exception on creating directory`, { |
15 | xid, | 15 | xid, |
16 | dirname, | 16 | dirname, |
17 | callerName, | 17 | callerName, |
18 | eCode: e.code, | 18 | eCode: e.code, |
19 | eMessage: e.message, | 19 | eMessage: e.message, |
20 | }); | 20 | }); |
21 | } | 21 | } |
22 | }; | 22 | }; |
23 | 23 | ||
24 | module.exports = async (xid, dirname, callerName) => { | 24 | module.exports = async (xid, dirname, callerName) => { |
25 | try { | 25 | try { |
26 | await fsPromise.stat(dirname); | 26 | await fsPromise.stat(dirname); |
27 | } catch (e) { | 27 | } catch (e) { |
28 | await mkdir(xid, dirname, callerName); | 28 | await mkdir(xid, dirname, callerName); |
29 | } | 29 | } |
30 | }; | 30 | }; |
31 | 31 |