Commit 9ced2cfdf03e19f6c35901c59076ab1322236d6b

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

PAY finished

Showing 3 changed files with 111 additions and 1 deletions Inline Diff

lib/core-callback/sender.js
1 const MODULE_NAME = 'CORE-CALLBACK-SENDER'; 1 const MODULE_NAME = 'CORE-CALLBACK-SENDER';
2 const MAX_RETRY = 10; 2 const MAX_RETRY = 10;
3 const SLEEP_BEFORE_RETRY_MS = 60 * 1000; 3 const SLEEP_BEFORE_RETRY_MS = 60 * 1000;
4 4
5 const axios = require('axios').default; 5 const axios = require('axios').default;
6 const logger = require('komodo-sdk/logger'); 6 const logger = require('komodo-sdk/logger');
7 7
8 const sleep = require('../sleep'); 8 const sleep = require('../sleep');
9 const urlConcatQs = require('../url-concat-qs'); 9 const urlConcatQs = require('../url-concat-qs');
10 10
11 const sender = async (data, xid, retry) => { 11 const sender = async (data, xid, retry) => {
12 if (!data.reverse_url) return; 12 if (!data.reverse_url) return;
13 13
14 const params = { 14 const params = {
15 httpgetx_xid: xid, 15 httpgetx_xid: xid,
16 command: data.command, 16 command: data.command,
17 request_id: data.request_id && data.request_id.toString(), 17 request_id: data.request_id && data.request_id.toString(),
18 transaction_id: data.transaction_id && data.transaction_id.toString(), 18 transaction_id: data.transaction_id && data.transaction_id.toString(),
19 transaction_date: data.transaction_date, 19 transaction_date: data.transaction_date,
20 store_name: data.store_name, 20 store_name: data.store_name,
21 terminal_name: data.terminal_name, 21 terminal_name: data.terminal_name,
22 product_name: data.product_name, 22 product_name: data.product_name,
23 destination: data.destination, 23 destination: data.destination,
24 rc: data.rc, 24 rc: data.rc,
25 sn: data.sn, 25 sn: data.sn,
26 message: data.message, 26 message: data.message,
27 amount: data.amount, 27 amount: data.amount,
28 ending_balance: data.ending_balance, 28 ending_balance: data.ending_balance,
29 amount_to_charge: data.amount_to_charge,
30 }; 29 };
31 30
31 if (data.command === 'INQUIRY' && data.amount_to_charge) {
32 params.amount_to_charge = data.amount_to_charge;
33 }
34
32 const fullUrl = urlConcatQs(data.reverse_url, params); 35 const fullUrl = urlConcatQs(data.reverse_url, params);
33 logger.info(`${MODULE_NAME} 8B6A4CEC: Sending CORE-CALLBACK to PARTNER`, { 36 logger.info(`${MODULE_NAME} 8B6A4CEC: Sending CORE-CALLBACK to PARTNER`, {
34 xid, retry, params, fullUrl, 37 xid, retry, params, fullUrl,
35 }); 38 });
36 39
37 try { 40 try {
38 const result = await axios.get(data.reverse_url, { 41 const result = await axios.get(data.reverse_url, {
39 params, 42 params,
40 timeout: 60 * 1000, 43 timeout: 60 * 1000,
41 }); 44 });
42 45
43 logger.info(`${MODULE_NAME} 3641FBD7: CORE-CALLBACK has been sent to PARTNER successfully`, { 46 logger.info(`${MODULE_NAME} 3641FBD7: CORE-CALLBACK has been sent to PARTNER successfully`, {
44 xid, retry, fullUrl, body: result && result.data, 47 xid, retry, fullUrl, body: result && result.data,
45 }); 48 });
46 } catch (e) { 49 } catch (e) {
47 logger.warn(`${MODULE_NAME} A1EC9E70: Failed on sending CORE-CALLBACK to PARTNER`, { 50 logger.warn(`${MODULE_NAME} A1EC9E70: Failed on sending CORE-CALLBACK to PARTNER`, {
48 xid, 51 xid,
49 retry, 52 retry,
50 maxRetry: MAX_RETRY, 53 maxRetry: MAX_RETRY,
51 errCode: e.code, 54 errCode: e.code,
52 errMessage: e.message, 55 errMessage: e.message,
53 reverseUrl: data.reverse_url, 56 reverseUrl: data.reverse_url,
54 fullUrl, 57 fullUrl,
55 httpStatus: e.response && e.response.status, 58 httpStatus: e.response && e.response.status,
56 body: e.response && e.response.data, 59 body: e.response && e.response.data,
57 }); 60 });
58 61
59 if ((retry || 0) < MAX_RETRY) { 62 if ((retry || 0) < MAX_RETRY) {
60 await sleep(SLEEP_BEFORE_RETRY_MS); 63 await sleep(SLEEP_BEFORE_RETRY_MS);
61 logger.verbose(`${MODULE_NAME} D8958695: Going to retry sending CORE-CALLBACK TO PARTNER`, { 64 logger.verbose(`${MODULE_NAME} D8958695: Going to retry sending CORE-CALLBACK TO PARTNER`, {
62 xid, sleepTime: SLEEP_BEFORE_RETRY_MS, 65 xid, sleepTime: SLEEP_BEFORE_RETRY_MS,
63 }); 66 });
64 sender(data, xid, (retry || 0) + 1); 67 sender(data, xid, (retry || 0) + 1);
65 } 68 }
66 } 69 }
67 }; 70 };
68 71
69 module.exports = sender; 72 module.exports = sender;
lib/listener-partner/index.js
1 'use strict'; 1 'use strict';
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('komodo-sdk/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 routerTopup = require('./routers/topup'); 14 const routerTopup = require('./routers/topup');
14 const routerTrxStatus = require('./routers/trx-status'); 15 const routerTrxStatus = require('./routers/trx-status');
15 16
16 const app = express(); 17 const app = express();
17 18
18 app.use(express.json({ extended: true })); 19 app.use(express.json({ extended: true }));
19 app.use(express.urlencoded({ extended: true })); 20 app.use(express.urlencoded({ extended: true }));
20 app.use(middlewareCommon); 21 app.use(middlewareCommon);
21 22
22 app.use('/inquiry', routerInquiry); 23 app.use('/inquiry', routerInquiry);
24 app.use('/pay', routerPay);
23 app.use('/topup', routerTopup); 25 app.use('/topup', routerTopup);
24 app.use('/trx-status', routerTrxStatus); 26 app.use('/trx-status', routerTrxStatus);
25 27
26 app.use((req, res) => { 28 app.use((req, res) => {
27 const { xid } = res.locals; 29 const { xid } = res.locals;
28 res.status(404).end(`KOMODO-HTTP-GET-X CENTER.\n404: Method not found.\n\nXID: ${xid}.\n`); 30 res.status(404).end(`KOMODO-HTTP-GET-X CENTER.\n404: Method not found.\n\nXID: ${xid}.\n`);
29 }); 31 });
30 32
31 app.listen(config.listener.partner.port || DEFAULT_LISTENER_FROM_PARTNER_PORT, () => { 33 app.listen(config.listener.partner.port || DEFAULT_LISTENER_FROM_PARTNER_PORT, () => {
32 logger.info(`Listen from partner request on port ${config.listener.partner.port}`); 34 logger.info(`Listen from partner request on port ${config.listener.partner.port}`);
33 }).on('error', (e) => { 35 }).on('error', (e) => {
34 logger.error(`Can not listen request from partner on port ${config.listener.partner.port || DEFAULT_LISTENER_FROM_PARTNER_PORT}. ${e.toString()}`); 36 logger.error(`Can not listen request from partner on port ${config.listener.partner.port || DEFAULT_LISTENER_FROM_PARTNER_PORT}. ${e.toString()}`);
35 process.exit(1); 37 process.exit(1);
36 }); 38 });
37 39
lib/listener-partner/routers/pay.js
File was created 1 const axios = require('axios').default;
2 const express = require('express');
3 const coreUrl = require('komodo-sdk/core-url');
4
5 const config = require('komodo-sdk/config');
6 const logger = require('komodo-sdk/logger');
7
8 const getFromBodyQsParams = require('../../get-from-body-qs-params');
9 const ipv6ToIpv4 = require('../../ipv6-to-ipv4');
10
11 const router = express.Router();
12 module.exports = router;
13
14 const CORE_ENDPOINT = `${coreUrl}/postpaid2/pay`;
15
16 const mainHandler = async (req, res) => {
17 const { xid } = res.locals;
18
19 const requestId = (getFromBodyQsParams(req, 'request_id') || '').toString().trim();
20 const terminalNameWithoutIp = (getFromBodyQsParams(req, 'terminal_name') || '').toString().trim();
21 const terminalName = `${terminalNameWithoutIp}@${ipv6ToIpv4(req.ip)}`;
22 const productName = (getFromBodyQsParams(req, 'product_name') || '').trim().toUpperCase();
23 const destination = (getFromBodyQsParams(req, 'destination') || '').toString().trim();
24 const password = getFromBodyQsParams(req, 'password');
25 const reverseUrl = getFromBodyQsParams(req, 'reverse_url');
26
27 if (!requestId || !terminalNameWithoutIp || !productName || !destination) {
28 res.end('INVALID REQUEST. Missing request_id or terminal_name or product_name or destination.');
29 return;
30 }
31
32 const params = {
33 origin: config.name,
34 report_ip: config.listener.core.from_ip,
35 report_port: config.listener.core.port || 25614,
36 request_id: requestId,
37 terminal_name: terminalName,
38 product_name: productName,
39 destination,
40 terminal_password: password,
41 reverse_url: reverseUrl,
42 };
43
44 logger.info('Forwarding PAY request to CORE', { xid, params });
45 try {
46 const result = await axios.get(CORE_ENDPOINT, {
47 params,
48 timeout: 10000,
49 });
50
51 if (!result || !result.data) {
52 const newError = new Error('0D428E4C: Empty CORE PAY direct-response');
53 logger.warn(newError.message, { xid });
54 throw newError;
55 }
56
57 logger.verbose('Got PAY direct-response from CORE', {
58 xid,
59 coreResponse: result.data,
60 });
61
62 const resultForPartner = {
63 httpgetx_xid: xid,
64 command: result.data.command,
65 request_id: result.data.request_id && result.data.request_id.toString(),
66 transaction_id: result.data.transaction_id && result.data.transaction_id.toString(),
67 transaction_date: result.data.transaction_date,
68 store_name: result.data.store_name,
69 terminal_name: result.data.terminal_name,
70 product_name: result.data.product_name,
71 destination: result.data.destination,
72 rc: result.data.rc,
73 sn: result.data.sn,
74 message: result.data.message,
75 amount: result.data.amount,
76 ending_balance: result.data.ending_balance,
77 };
78
79 logger.verbose('Forwarding CORE PAY direct-response to partner', {
80 xid,
81 resultForPartner,
82 });
83
84 res.json(resultForPartner);
85 } catch (e) {
86 logger.warn('EXCEPTION on forwarding PAY request to CORE', {
87 xid,
88 errCode: e.code,
89 errMessage: e.message,
90 });
91
92 res.json({
93 httpgetx_xid: xid,
94 command: 'PAY',
95 request_id: requestId,
96 terminal_name: terminalName,
97 product_name: productName,
98 destination,
99 rc: '68',
100 message: 'CORE tidak merespon dengan benar, tidak dapat mengetahui status request anda',
101 });
102 }
103 };
104
105 router.all('/', mainHandler);
106