Commit b403448adb43d790a3a6c6f7fa2e35d351bd1505

Authored by Adhidarma Hadiwinoto
1 parent dc2d0f90ec
Exists in master and in 1 other branch dev

Refactor some matrix

Showing 4 changed files with 25 additions and 12 deletions Inline Diff

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('komodo-sdk/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 matrix = require('../matrix'); 10 const matrix = require('../matrix');
11 11
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 24
25 app.use((req, res) => { 25 app.use((req, res) => {
26 matrix.messages_from_core += 1; 26 matrix.core.received += 1;
27 res.end('OK'); 27 res.end('OK');
28 sender(req.query, res.locals.xid); 28 sender(req.query, res.locals.xid);
29 }); 29 });
30 30
31 const port = (config.listener && config.listener.core && config.listener.core.port) 31 const port = (config.listener && config.listener.core && config.listener.core.port)
32 || DEFAULT_LISTENER_FROM_CORE; 32 || DEFAULT_LISTENER_FROM_CORE;
33 33
34 app.listen(port, () => { 34 app.listen(port, () => {
35 logger.info(`${MODULE_NAME} 0375DC4E: Listen from CORE callback on port ${port}`); 35 logger.info(`${MODULE_NAME} 0375DC4E: Listen from CORE callback on port ${port}`);
36 }).on('error', (e) => { 36 }).on('error', (e) => {
37 logger.error(`${MODULE_NAME} A90E42D5: Can not listen CORE callback on port ${port}. ${e.toString()}`); 37 logger.error(`${MODULE_NAME} A90E42D5: Can not listen CORE callback on port ${port}. ${e.toString()}`);
38 process.exit(1); 38 process.exit(1);
39 }); 39 });
40 40
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('komodo-sdk/logger');
6 6
7 const matrix = require('../matrix'); 7 const matrix = require('../matrix');
8 8
9 const HTTP_TIMEOUT = Number( 9 const HTTP_TIMEOUT = Number(
10 config.callback_sender && config.callback_sender.http_timeout_ms, 10 config.callback_sender && config.callback_sender.http_timeout_ms,
11 ) || 30 * 1000; 11 ) || 30 * 1000;
12 12
13 const SLEEP_BEFORE_RETRY_MS = Number( 13 const SLEEP_BEFORE_RETRY_MS = Number(
14 config.callback_sender && config.callback_sender.sleep_before_retry_ms, 14 config.callback_sender && config.callback_sender.sleep_before_retry_ms,
15 ) || 10 * 1000; 15 ) || 10 * 1000;
16 16
17 const MAX_RETRY = Number( 17 const MAX_RETRY = Number(
18 config.callback_sender && config.callback_sender.max_retry, 18 config.callback_sender && config.callback_sender.max_retry,
19 ) || 10; 19 ) || 10;
20 20
21 logger.verbose(`${MODULE_NAME} 848B9104: Initialized`, { 21 logger.verbose(`${MODULE_NAME} 848B9104: Initialized`, {
22 HTTP_TIMEOUT, 22 HTTP_TIMEOUT,
23 SLEEP_BEFORE_RETRY_MS, 23 SLEEP_BEFORE_RETRY_MS,
24 MAX_RETRY, 24 MAX_RETRY,
25 }); 25 });
26 26
27 const axiosHeaders = { 27 const axiosHeaders = {
28 'Content-Type': 'application/json', 28 'Content-Type': 'application/json',
29 'User-Agent': 'KOMODO-HTTPGETX callback sender', 29 'User-Agent': 'KOMODO-HTTPGETX callback sender',
30 }; 30 };
31 31
32 const sleep = require('../sleep'); 32 const sleep = require('../sleep');
33 const urlConcatQs = require('../url-concat-qs'); 33 const urlConcatQs = require('../url-concat-qs');
34 34
35 const sender = async (data, xid, retry) => { 35 const sender = async (data, xid, retry) => {
36 if (!data.reverse_url) { 36 if (!data.reverse_url) {
37 logger.verbose(`${MODULE_NAME} C4FF18FB: Ignoring missing reverse url`, { 37 logger.verbose(`${MODULE_NAME} C4FF18FB: Ignoring missing reverse url`, {
38 xid, 38 xid,
39 dataFromCore: data, 39 dataFromCore: data,
40 }); 40 });
41 41
42 return; 42 return;
43 } 43 }
44 44
45 const params = { 45 const params = {
46 httpgetx_xid: xid, 46 httpgetx_xid: xid,
47 command: data.command, 47 command: data.command,
48 48
49 request_id: data.request_id && data.request_id.toString(), 49 request_id: data.request_id && data.request_id.toString(),
50 transaction_id: data.transaction_id && data.transaction_id.toString(), 50 transaction_id: data.transaction_id && data.transaction_id.toString(),
51 transaction_date: data.transaction_date, 51 transaction_date: data.transaction_date,
52 52
53 store_name: data.store_name, 53 store_name: data.store_name,
54 terminal_name: data.terminal_name, 54 terminal_name: data.terminal_name,
55 55
56 product_name: data.product_name, 56 product_name: data.product_name,
57 destination: data.destination, 57 destination: data.destination,
58 58
59 rc: data.rc, 59 rc: data.rc,
60 sn: data.sn || undefined, 60 sn: data.sn || undefined,
61 amount: Number(data.amount) || undefined, 61 amount: Number(data.amount) || undefined,
62 ending_balance: Number(data.ending_balance) || undefined, 62 ending_balance: Number(data.ending_balance) || undefined,
63 63
64 message: data.message, 64 message: data.message,
65 65
66 bill_count: Number(data.bill_count) || undefined, 66 bill_count: Number(data.bill_count) || undefined,
67 bill_amount: Number(data.bill_amount) || undefined, 67 bill_amount: Number(data.bill_amount) || undefined,
68 fee_per_bill: Number(data.fee) || undefined, 68 fee_per_bill: Number(data.fee) || undefined,
69 fee_total: Number(data.fee_total) || undefined, 69 fee_total: Number(data.fee_total) || undefined,
70 70
71 bill_detail: data.bill_detail || undefined, 71 bill_detail: data.bill_detail || undefined,
72 }; 72 };
73 73
74 if (data.command === 'INQUIRY' && data.amount_to_charge) { 74 if (data.command === 'INQUIRY' && data.amount_to_charge) {
75 params.amount_to_charge = data.amount_to_charge; 75 params.amount_to_charge = data.amount_to_charge;
76 } 76 }
77 77
78 const isPostpaid = ['INQUIRY', 'PAY'].indexOf(data.command) >= 0; 78 const isPostpaid = ['INQUIRY', 'PAY'].indexOf(data.command) >= 0;
79 const isHttpPost = isPostpaid; 79 const isHttpPost = isPostpaid;
80 80
81 const endpointUrl = isHttpPost ? data.reverse_url : urlConcatQs(data.reverse_url, params); 81 const endpointUrl = isHttpPost ? data.reverse_url : urlConcatQs(data.reverse_url, params);
82 82
83 logger.info(`${MODULE_NAME} 8B6A4CEC: Sending to PARTNER`, { 83 logger.info(`${MODULE_NAME} 8B6A4CEC: Sending to PARTNER`, {
84 xid, 84 xid,
85 retry, 85 retry,
86 isPostpaid, 86 isPostpaid,
87 isHttpPost, 87 isHttpPost,
88 endpointUrl, 88 endpointUrl,
89 }); 89 });
90 90
91 try { 91 try {
92 const response = isHttpPost 92 const response = isHttpPost
93 ? await axios.post(data.reverse_url, params, { 93 ? await axios.post(data.reverse_url, params, {
94 timeout: HTTP_TIMEOUT, 94 timeout: HTTP_TIMEOUT,
95 headers: axiosHeaders, 95 headers: axiosHeaders,
96 }) 96 })
97 : await axios.get(data.reverse_url, { 97 : await axios.get(data.reverse_url, {
98 params, 98 params,
99 timeout: HTTP_TIMEOUT, 99 timeout: HTTP_TIMEOUT,
100 headers: axiosHeaders, 100 headers: axiosHeaders,
101 }); 101 });
102 102
103 matrix.callback_sender.message_sent += 1; 103 matrix.callback_sender.sent += 1;
104 104
105 if (isPostpaid) { 105 if (isPostpaid) {
106 matrix.callback_sender.message_sent_using_post_method += 1; 106 matrix.callback_sender.sent_using_post += 1;
107 } else { 107 } else {
108 matrix.callback_sender.message_sent_using_get_method += 1; 108 matrix.callback_sender.sent_using_get += 1;
109 } 109 }
110 110
111 logger.info(`${MODULE_NAME} 3641FBD7: Has been sent to PARTNER successfully`, { 111 logger.info(`${MODULE_NAME} 3641FBD7: Has been sent to PARTNER successfully`, {
112 xid, 112 xid,
113 retry, 113 retry,
114 httpStatus: response.status, 114 httpStatus: response.status,
115 responseBody: response && response.data, 115 responseBody: response && response.data,
116 }); 116 });
117 } catch (e) { 117 } catch (e) {
118 matrix.callback_sender.message_sent_failed += 1; 118 matrix.callback_sender.sent_failed += 1;
119 matrix.callback_sender.last_error = { 119 matrix.callback_sender.last_error = {
120 xid, 120 xid,
121 ts: new Date(), 121 ts: new Date(),
122 eCode: e.code, 122 eCode: e.code,
123 eMessage: e.message, 123 eMessage: e.message,
124 reverseUrl: data.reverse_url, 124 reverseUrl: data.reverse_url,
125 httpStatus: e.response && e.response.status, 125 httpStatus: e.response && e.response.status,
126 responseBody: e.response && e.response.data, 126 responseBody: e.response && e.response.data,
127 }; 127 };
128 128
129 logger.warn(`${MODULE_NAME} A1EC9E70: Failed on sending to PARTNER`, { 129 logger.warn(`${MODULE_NAME} A1EC9E70: Failed on sending to PARTNER`, {
130 xid, 130 xid,
131 retry, 131 retry,
132 maxRetry: MAX_RETRY, 132 maxRetry: MAX_RETRY,
133 errCode: e.code, 133 errCode: e.code,
134 errMessage: e.message, 134 errMessage: e.message,
135 reverseUrl: data.reverse_url, 135 reverseUrl: data.reverse_url,
136 endpointUrl, 136 endpointUrl,
137 httpStatus: e.response && e.response.status, 137 httpStatus: e.response && e.response.status,
138 responseBody: e.response && e.response.data, 138 responseBody: e.response && e.response.data,
139 }); 139 });
140 140
141 if ((retry || 0) < MAX_RETRY) { 141 if ((retry || 0) < MAX_RETRY) {
142 await sleep(SLEEP_BEFORE_RETRY_MS); 142 await sleep(SLEEP_BEFORE_RETRY_MS);
143 logger.verbose(`${MODULE_NAME} D8958695: Going to retry sending CORE-CALLBACK TO PARTNER`, { 143 logger.verbose(`${MODULE_NAME} D8958695: Going to retry sending CORE-CALLBACK TO PARTNER`, {
144 xid, sleepTime: SLEEP_BEFORE_RETRY_MS, 144 xid, sleepTime: SLEEP_BEFORE_RETRY_MS,
145 }); 145 });
146 sender(data, xid, (retry || 0) + 1); 146 sender(data, xid, (retry || 0) + 1);
147 } 147 }
148 } 148 }
149 }; 149 };
150 150
151 module.exports = sender; 151 module.exports = sender;
152 152
1 const os = require('os'); 1 const os = require('os');
2 // const config = require('komodo-sdk/config'); 2 // const config = require('komodo-sdk/config');
3 3
4 module.exports = { 4 module.exports = {
5 pid: process.pid, 5 pid: process.pid,
6 ts: new Date(), 6 ts: new Date(),
7 start_time: new Date(), 7 start_time: new Date(),
8 start_time_from_now: null, 8 start_time_from_now: null,
9 uptime_secs: process.uptime(), 9 uptime_secs: process.uptime(),
10 hostname: os.hostname(), 10 hostname: os.hostname(),
11 loadavg: os.loadavg(), 11 loadavg: os.loadavg(),
12 workdir: process.cwd(), 12 workdir: process.cwd(),
13 memory_usage: process.memoryUsage(), 13 memory_usage: process.memoryUsage(),
14 nodejs_versions: process.versions, 14 nodejs_versions: process.versions,
15 messages_from_core: 0, 15 core: {
16 messages_to_core: 0, 16 received: 0,
17 sent: 0,
18 sent_failed: 0,
19 last_error: null,
20 },
17 callback_sender: { 21 callback_sender: {
18 message_sent: 0, 22 sent: 0,
19 message_sent_failed: 0, 23 sent_failed: 0,
20 message_sent_using_get_method: 0, 24 sent_using_get: 0,
21 message_sent_using_post_method: 0, 25 sent_using_post: 0,
22 last_error: null, 26 last_error: null,
23 }, 27 },
24 }; 28 };
25 29
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('komodo-sdk/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 10
11 const router = express.Router(); 11 const router = express.Router();
12 module.exports = router; 12 module.exports = router;
13 13
14 function onInvalidParameter(missingParameter, req, res) { 14 function onInvalidParameter(missingParameter, req, res) {
15 logger.verbose(`${MODULE_NAME} 1536D577: Undefined ${missingParameter} parameter`, { 15 logger.verbose(`${MODULE_NAME} 1536D577: Undefined ${missingParameter} parameter`, {
16 xid: res.locals.xid, 16 xid: res.locals.xid,
17 ip: req.ip, 17 ip: req.ip,
18 terminal_name: req.body.terminal_name || req.query.terminal_name, 18 terminal_name: req.body.terminal_name || req.query.terminal_name,
19 request_id: req.body.request_id || req.query.request_id, 19 request_id: req.body.request_id || req.query.request_id,
20 product_name: req.body.product_name || req.query.product_name, 20 product_name: req.body.product_name || req.query.product_name,
21 destination: req.body.destination || req.query.destination, 21 destination: req.body.destination || req.query.destination,
22 }); 22 });
23 res.end('INVALID REQUEST'); 23 res.end('INVALID REQUEST');
24 } 24 }
25 25
26 function pagePrerequisite(req, res, next) { 26 function pagePrerequisite(req, res, next) {
27 if (!req.body) req.body = {}; 27 if (!req.body) req.body = {};
28 28
29 if (!req.body.terminal_name && !req.query.terminal_name) { 29 if (!req.body.terminal_name && !req.query.terminal_name) {
30 onInvalidParameter('terminal_name', req, res); 30 onInvalidParameter('terminal_name', req, res);
31 return; 31 return;
32 } 32 }
33 33
34 if (!req.body.password && !req.query.password) { 34 if (!req.body.password && !req.query.password) {
35 onInvalidParameter('password', req, res); 35 onInvalidParameter('password', req, res);
36 return; 36 return;
37 } 37 }
38 38
39 if (!req.body.request_id && !req.query.request_id) { 39 if (!req.body.request_id && !req.query.request_id) {
40 onInvalidParameter('request_id', req, res); 40 onInvalidParameter('request_id', req, res);
41 return; 41 return;
42 } 42 }
43 43
44 if (!req.body.product_name && !req.query.product_name) { 44 if (!req.body.product_name && !req.query.product_name) {
45 onInvalidParameter('product_name', req, res); 45 onInvalidParameter('product_name', req, res);
46 return; 46 return;
47 } 47 }
48 48
49 if (!req.body.destination && !req.query.destination) { 49 if (!req.body.destination && !req.query.destination) {
50 onInvalidParameter('destination', req, res); 50 onInvalidParameter('destination', req, res);
51 return; 51 return;
52 } 52 }
53 53
54 next(); 54 next();
55 } 55 }
56 56
57 async function pageIndex(req, res) { 57 async function pageIndex(req, res) {
58 const { xid } = res.locals; 58 const { xid } = res.locals;
59 59
60 const terminalName = `${req.body.terminal_name || req.query.terminal_name}@${req.ip.replace(/^::ffff:/, '')}`; 60 const terminalName = `${req.body.terminal_name || req.query.terminal_name}@${req.ip.replace(/^::ffff:/, '')}`;
61 61
62 matrix.messages_to_core += 1; 62 matrix.core.sent += 1;
63 63
64 const [err, coreResponse] = await coreapi({ 64 const [err, coreResponse] = await coreapi({
65 xid, 65 xid,
66 path: '/prepaid/buy', 66 path: '/prepaid/buy',
67 qs: { 67 qs: {
68 terminal_name: terminalName, 68 terminal_name: terminalName,
69 password: req.body.password || req.query.password, 69 password: req.body.password || req.query.password,
70 request_id: req.body.request_id || req.query.request_id, 70 request_id: req.body.request_id || req.query.request_id,
71 product_name: req.body.product_name || req.query.product_name, 71 product_name: req.body.product_name || req.query.product_name,
72 destination: req.body.destination || req.query.destination, 72 destination: req.body.destination || req.query.destination,
73 origin: config.name || 'HTTPGETX', 73 origin: config.name || 'HTTPGETX',
74 report_ip: config.listener.core.ip || null, 74 report_ip: config.listener.core.ip || null,
75 report_port: config.listener.core.port, 75 report_port: config.listener.core.port,
76 reverse_url: req.body.reverse_url || req.query.reverse_url || null, 76 reverse_url: req.body.reverse_url || req.query.reverse_url || null,
77 }, 77 },
78 }); 78 });
79 79
80 if (err || !coreResponse) { 80 if (err || !coreResponse) {
81 matrix.core.sent_failed += 1;
82 matrix.core.last_error = {
83 xid,
84 ts: new Date(),
85 e: err,
86 eCode: err.code,
87 eMessage: err.message,
88 };
89
81 logger.warn(`${MODULE_NAME} 8DEBE15F: ERROR on /prepaid/buy response`, { 90 logger.warn(`${MODULE_NAME} 8DEBE15F: ERROR on /prepaid/buy response`, {
82 xid, 91 xid,
83 err, 92 err,
84 coreResponseTypeof: typeof coreResponse, 93 coreResponseTypeof: typeof coreResponse,
85 coreResponse, 94 coreResponse,
86 }); 95 });
87 res.end('INVALID CORE RESPONSE'); 96 res.end('INVALID CORE RESPONSE');
88 return; 97 return;
89 } 98 }
90 99
91 logger.verbose(`${MODULE_NAME} 2528A9B4: Got CORE response`, { 100 logger.verbose(`${MODULE_NAME} 2528A9B4: Got CORE response`, {
92 xid, 101 xid,
93 coreResponse, 102 coreResponse,
94 }); 103 });
95 104
96 const responseToPartner = { 105 const responseToPartner = {
97 httpgetx_xid: xid, 106 httpgetx_xid: xid,
98 request_id: coreResponse.request_id, 107 request_id: coreResponse.request_id,
99 transaction_id: coreResponse.transaction_id, 108 transaction_id: coreResponse.transaction_id,
100 transaction_date: coreResponse.transaction_date, 109 transaction_date: coreResponse.transaction_date,
101 store_name: coreResponse.store_name, 110 store_name: coreResponse.store_name,
102 terminal_name: coreResponse.terminal_name, 111 terminal_name: coreResponse.terminal_name,
103 product_name: coreResponse.product_name, 112 product_name: coreResponse.product_name,
104 destination: coreResponse.destination, 113 destination: coreResponse.destination,
105 rc: coreResponse.rc, 114 rc: coreResponse.rc,
106 sn: coreResponse.sn || undefined, 115 sn: coreResponse.sn || undefined,
107 amount: Number(coreResponse.amount) || undefined, 116 amount: Number(coreResponse.amount) || undefined,
108 ending_balance: Number(coreResponse.ending_balance) || undefined, 117 ending_balance: Number(coreResponse.ending_balance) || undefined,
109 message: coreResponse.message, 118 message: coreResponse.message,
110 }; 119 };
111 120
112 res.json(responseToPartner); 121 res.json(responseToPartner);
113 } 122 }
114 123
115 // router.all('/', (req, res) => { res.status(404).end('404: Not implemented yet'); }); 124 // router.all('/', (req, res) => { res.status(404).end('404: Not implemented yet'); });
116 router.get('/', pagePrerequisite, pageIndex); 125 router.get('/', pagePrerequisite, pageIndex);
117 126