Commit 00208dea14cae319fd0851c773b947d4f86e8ae4

Authored by Adhidarma Hadiwinoto
1 parent 4c826b27e1
Exists in master

messageExtractor buat extract price dan endingBalance

Showing 4 changed files with 150 additions and 4 deletions Inline Diff

lib/message-extractor.js
File was created 1 /* eslint-disable no-console */
2 const MODULE_NAME = 'MESSAGE-PARSER.FINDER';
3
4 /**
5 * Mencari nilai berdasarkan array of pattern
6 * @date 2021-07-05
7 * @param {Array} rules
8 * @param {string} originalMessage
9 * @param {any} isDebug
10 * @returns {string} string yang sesuai pattern, null jika tidak ditemukan
11 */
12 module.exports = (rules, originalMessage, isDebug) => {
13 if (!Array.isArray(rules)) return null;
14 if (typeof originalMessage !== 'string') return null;
15
16 const msg = originalMessage.trim();
17
18 if (!rules || !msg) return null;
19
20 const ruleCount = rules.length;
21 for (let i = 0; i < ruleCount; i += 1) {
22 const rule = rules[i];
23
24 // eslint-disable-next-line no-continue
25 if (rule.disable || rule.disabled) continue;
26
27 const re = new RegExp(rule.pattern, rule.flags || '');
28
29 const matches = msg.match(re);
30 let result = matches && matches[rule.idx];
31
32 if (result && rule.postprocessing && typeof rule.postprocessing === 'function') {
33 result = rule.postprocessing(result);
34 }
35
36 if (result) {
37 if (isDebug) {
38 console.log(`${MODULE_NAME} 9FAF9286: Found matches`, { isDebug, result, rule });
39 }
40
41 return result;
42 }
43 }
44
45 if (isDebug) {
46 console.log(`${MODULE_NAME} 0240860D: Matches not found`, { isDebug });
47 }
48
49 return null;
50 };
51
1 const MODULE_NAME = 'PARSE-RESULT'; 1 const MODULE_NAME = 'PARSE-RESULT';
2 2
3 const config = require('komodo-sdk/config'); 3 const config = require('komodo-sdk/config');
4 const logger = require('komodo-sdk/logger'); 4 const logger = require('komodo-sdk/logger');
5 5
6 const getParamsMemberObj = require('./generic-xmlrpc/get-params-members-obj'); 6 const getParamsMemberObj = require('./generic-xmlrpc/get-params-members-obj');
7 const parseXml = require('./parse-xml'); 7 const parseXml = require('./parse-xml');
8 8
9 const report = require('./report'); 9 const report = require('./report');
10 const translateRc = require('./translate-rc'); 10 const translateRc = require('./translate-rc');
11 const messageExtractor = require('./message-extractor');
12 const patternRules = require('./pattern-rules');
11 13
12 module.exports = (xid, trxIdFromCaller, xml, isCallback) => { 14 module.exports = (xid, trxIdFromCaller, xml, isCallback) => {
13 logger.verbose(`${MODULE_NAME} 58547863: Processing XML message`, { xid, isCallback }); 15 logger.verbose(`${MODULE_NAME} 58547863: Processing XML message`, { xid, isCallback });
14 16
15 const responseType = isCallback ? 'CALLBACK' : 'DIRECT-RESPONSE'; 17 const responseType = isCallback ? 'CALLBACK' : 'DIRECT-RESPONSE';
16 18
17 if (!trxIdFromCaller && !isCallback) { 19 if (!trxIdFromCaller && !isCallback) {
18 if (logger) logger.warn(`${MODULE_NAME} 8CAAD7C9: No trx id on non callback`, { xid }); 20 if (logger) logger.warn(`${MODULE_NAME} 8CAAD7C9: No trx id on non callback`, { xid });
19 return; 21 return;
20 } 22 }
21 23
22 const obj = parseXml(xid, xml); 24 const obj = parseXml(xid, xml);
23 if (!obj) { 25 if (!obj) {
24 const e = new Error(`${MODULE_NAME} B46CAAD1: Invalid XML`); 26 const e = new Error(`${MODULE_NAME} B46CAAD1: Invalid XML`);
25 logger.warn(e.message, { xid }); 27 logger.warn(e.message, { xid });
26 28
27 if (trxIdFromCaller) { 29 if (trxIdFromCaller) {
28 report(xid, { 30 report(xid, {
29 trx_id: trxIdFromCaller.toString(), 31 trx_id: trxIdFromCaller.toString(),
30 rc: '68', 32 rc: '68',
31 message: { 33 message: {
32 xid, 34 xid,
33 responseType, 35 responseType,
34 'GW-ERROR': { 36 'GW-ERROR': {
35 message: e.message, 37 message: e.message,
36 responseFromPartner: xml, 38 responseFromPartner: xml,
37 }, 39 },
38 }, 40 },
39 }); 41 });
40 } 42 }
41 43
42 return; 44 return;
43 } 45 }
44 46
45 const params = getParamsMemberObj(obj, false); 47 const params = getParamsMemberObj(obj, false);
46 48
47 if (!params) { 49 if (!params) {
48 const e = new Error(`${MODULE_NAME} A7B7EB30: Can not get params from message`); 50 const e = new Error(`${MODULE_NAME} A7B7EB30: Can not get params from message`);
49 logger.warn(e.message, { xid }); 51 logger.warn(e.message, { xid });
50 52
51 if (trxIdFromCaller) { 53 if (trxIdFromCaller) {
52 report(xid, { 54 report(xid, {
53 trx_id: trxIdFromCaller.toString(), 55 trx_id: trxIdFromCaller.toString(),
54 rc: '68', 56 rc: '68',
55 message: { 57 message: {
56 xid, 58 xid,
57 responseType, 59 responseType,
58 'GW-ERROR': { 60 'GW-ERROR': {
59 message: e.message, 61 message: e.message,
60 responseFromPartner: obj, 62 responseFromPartner: obj,
61 }, 63 },
62 }, 64 },
63 }); 65 });
64 } 66 }
65 } 67 }
66 68
67 logger.verbose(`${MODULE_NAME} 3D5400C1: Params extracted from response`, { xid, params }); 69 logger.verbose(`${MODULE_NAME} 3D5400C1: Params extracted from response`, { xid, params });
68 70
69 const requestIdField = (config.partner.xmlrpc_field && config.partner.xmlrpc_field.requestId) || 'REQUESTID'; 71 const requestIdField = (config.partner.xmlrpc_field && config.partner.xmlrpc_field.requestId) || 'REQUESTID';
70 const requestIdFromResponse = params[requestIdField]; 72 const requestIdFromResponse = params[requestIdField];
71 73
72 const responseCodeField = (config.partner.xmlrpc_field && config.partner.xmlrpc_field.responseCode) || 'RESPONSECODE'; 74 const responseCodeField = (config.partner.xmlrpc_field && config.partner.xmlrpc_field.responseCode) || 'RESPONSECODE';
73 const responseCodeFromResponse = params[responseCodeField]; 75 const responseCodeFromResponse = params[responseCodeField];
74 76
75 // eslint-disable-next-line max-len 77 const messageField = (config.partner.xmlrpc_field && config.partner.xmlrpc_field.message) || 'MESSAGE';
76 // const messageField = (config.partner.xmlrpc_field && config.partner.xmlrpc_field.message) || 'MESSAGE'; 78 const messageFromResponse = params[messageField];
77 // const messageFromResponse = params[messageField];
78 79
79 const snField = (config.partner.xmlrpc_field && config.partner.xmlrpc_field.sn) || 'SN'; 80 const snField = (config.partner.xmlrpc_field && config.partner.xmlrpc_field.sn) || 'SN';
80 const snFromResponse = params[snField]; 81 const snFromResponse = params[snField];
81 82
82 const trxId = trxIdFromCaller || requestIdFromResponse; 83 const trxId = trxIdFromCaller || requestIdFromResponse;
83 if (!trxId) { 84 if (!trxId) {
84 logger.warn(`${MODULE_NAME} 534E684A: Unknown trxId`, { xid }); 85 logger.warn(`${MODULE_NAME} 534E684A: Unknown trxId`, { xid });
85 return; 86 return;
86 } 87 }
87 88
88 const rc = translateRc(xid, responseCodeFromResponse) || '68'; 89 const rc = translateRc(xid, responseCodeFromResponse) || '68';
89 90
90 const sn = (rc === '00' && snFromResponse) || null; 91 const sn = (
92 rc === '00' && (
93 snFromResponse
94 || messageExtractor(patternRules.sn, messageFromResponse)
95 )
96 ) || null;
97
98 const amount = Number(messageExtractor(patternRules.price, messageFromResponse) || '') || null;
99 const balance = Number(messageExtractor(patternRules.balance, messageFromResponse) || '') || null;
91 100
92 report(xid, { 101 report(xid, {
93 trx_id: trxId.toString(), 102 trx_id: trxId.toString(),
94 rc, 103 rc,
95 sn, 104 sn,
105 amount,
106 balance,
96 message: { 107 message: {
97 xid, 108 xid,
98 responseType: isCallback ? 'CALLBACK' : 'DIRECT-RESPONSE', 109 responseType: isCallback ? 'CALLBACK' : 'DIRECT-RESPONSE',
99 message: params, 110 message: params,
100 }, 111 },
101 }); 112 });
102 }; 113 };
lib/pattern-rules.js
File was created 1 /**
2 * Rule pattern to be used by message extractor
3 */
4 module.exports = {
5 sn: [
6 {
7 pattern: '(?:^|,|\\.|;|\\s)SN\\s*[=: ]\\s*(.+?)(?:;|$)',
8 idx: 1,
9 disable: false,
10 },
11 ],
12 price: [
13 {
14 pattern: '(?:,|\\.|;|\\s)(?:HRG|HARGA)\\s*[=: ]\\s*(?:RP)*\\s*(([0-9]|\\.||,)+)',
15 idx: 1,
16 disable: false,
17 postprocessing: (val) => (val || '').replace(/[,.]/g, ''),
18 },
19 ],
20 balance: [
21 {
22 pattern: '(?:,|\\.|;|\\s)SAL(?:DO)*\\s*[=: ]\\s*(?:RP)*\\s*(([0-9]|\\.||,)+)',
23 idx: 1,
24 disable: false,
25 postprocessing: (val) => (val || '').replace(/[,.]/g, ''),
26 },
27 ],
28 };
29
test/message-extractor.js
File was created 1 /* global describe it */
2
3 // eslint-disable-next-line no-unused-vars
4 const should = require('should');
5 const finder = require('../lib/message-extractor');
6 const organicRules = require('../lib/pattern-rules');
7
8 describe('#message-extractor', () => {
9 it('should handle garbage input', () => {
10 should.not.exists(finder(null, null, '39A9909D'));
11 should.not.exists(finder(null, '', '8C046E19'));
12 should.not.exists(finder(null, 'ada', '4154D1DC'));
13 should.not.exists(finder([], 'ada'), '5511A78C');
14 });
15
16 it('should return correct sn', () => {
17 finder(
18 organicRules.sn,
19 'SN=3438-2805-5518-4885-2577/A HANIS SACHRA/R1 /1300 VA/31,5;05/07/21 19:05 TRANSAKSI PLNB50 KE 14336230686, (ISO00) BERHASIL. SAL=RP 75.856.585 ,HRG=RP 50.020 ,ID=91280176,SN=3438-2805-5518-4885-2577/A HANIS SACHRA/R1 /1300 VA/31,5@,REQID=2794362 *Channel Telegram : https://t.me/metroreloadinfoh2h',
20 false,
21 ).should.equal('3438-2805-5518-4885-2577/A HANIS SACHRA/R1 /1300 VA/31,5', 'ST24 metro-reload 5B164B64');
22
23 finder(
24 organicRules.sn,
25 'ISI TS10 KE 082324881979 , SUKSES. SAL=489700,HRG=10300,ID=1625459089388,SN=0061003777417733',
26 false,
27 ).should.equal('0061003777417733', 'PLINK 00FC0A03');
28 });
29
30 it('should return correct price', () => {
31 finder(
32 organicRules.price,
33 'SN=3438-2805-5518-4885-2577/A HANIS SACHRA/R1 /1300 VA/31,5;05/07/21 19:05 TRANSAKSI PLNB50 KE 14336230686, (ISO00) BERHASIL. SAL=RP 75.856.585 ,HRG=RP 50.020 ,ID=91280176,SN=3438-2805-5518-4885-2577/A HANIS SACHRA/R1 /1300 VA/31,5@,REQID=2794362 *Channel Telegram : https://t.me/metroreloadinfoh2h',
34 false,
35 ).should.equal('50020', 'ST24 metro-reload 572DAAE1');
36
37 finder(
38 organicRules.price,
39 'ISI TS10 KE 082324881979 , SUKSES. SAL=489700,HRG=10300,ID=1625459089388,SN=0061003777417733',
40 false,
41 ).should.equal('10300', 'PLINK DB7F7B1C');
42 });
43
44 it('should return correct ending balance', () => {
45 finder(
46 organicRules.balance,
47 'SN=3438-2805-5518-4885-2577/A HANIS SACHRA/R1 /1300 VA/31,5;05/07/21 19:05 TRANSAKSI PLNB50 KE 14336230686, (ISO00) BERHASIL. SAL=RP 75.856.585 ,HRG=RP 50.020 ,ID=91280176,SN=3438-2805-5518-4885-2577/A HANIS SACHRA/R1 /1300 VA/31,5@,REQID=2794362 *Channel Telegram : https://t.me/metroreloadinfoh2h',
48 false,
49 ).should.equal('75856585', 'ST24 metro-reload 5E6CA14F');
50
51 finder(
52 organicRules.balance,
53 'ISI TS10 KE 082324881979 , SUKSES. SAL=489700,HRG=10300,ID=1625459089388,SN=0061003777417733',
54 false,
55 ).should.equal('489700', 'PLINK 29C24CEA');
56 });
57 });
58