diff --git a/lib/message-extractor.js b/lib/message-extractor.js new file mode 100644 index 0000000..3325ff6 --- /dev/null +++ b/lib/message-extractor.js @@ -0,0 +1,50 @@ +/* eslint-disable no-console */ +const MODULE_NAME = 'MESSAGE-PARSER.FINDER'; + +/** + * Mencari nilai berdasarkan array of pattern + * @date 2021-07-05 + * @param {Array} rules + * @param {string} originalMessage + * @param {any} isDebug + * @returns {string} string yang sesuai pattern, null jika tidak ditemukan + */ +module.exports = (rules, originalMessage, isDebug) => { + if (!Array.isArray(rules)) return null; + if (typeof originalMessage !== 'string') return null; + + const msg = originalMessage.trim(); + + if (!rules || !msg) return null; + + const ruleCount = rules.length; + for (let i = 0; i < ruleCount; i += 1) { + const rule = rules[i]; + + // eslint-disable-next-line no-continue + if (rule.disable || rule.disabled) continue; + + const re = new RegExp(rule.pattern, rule.flags || ''); + + const matches = msg.match(re); + let result = matches && matches[rule.idx]; + + if (result && rule.postprocessing && typeof rule.postprocessing === 'function') { + result = rule.postprocessing(result); + } + + if (result) { + if (isDebug) { + console.log(`${MODULE_NAME} 9FAF9286: Found matches`, { isDebug, result, rule }); + } + + return result; + } + } + + if (isDebug) { + console.log(`${MODULE_NAME} 0240860D: Matches not found`, { isDebug }); + } + + return null; +}; diff --git a/lib/parse-result.js b/lib/parse-result.js index d8a3f96..87923a7 100644 --- a/lib/parse-result.js +++ b/lib/parse-result.js @@ -8,6 +8,8 @@ const parseXml = require('./parse-xml'); const report = require('./report'); const translateRc = require('./translate-rc'); +const messageExtractor = require('./message-extractor'); +const patternRules = require('./pattern-rules'); module.exports = (xid, trxIdFromCaller, xml, isCallback) => { logger.verbose(`${MODULE_NAME} 58547863: Processing XML message`, { xid, isCallback }); @@ -72,9 +74,8 @@ module.exports = (xid, trxIdFromCaller, xml, isCallback) => { const responseCodeField = (config.partner.xmlrpc_field && config.partner.xmlrpc_field.responseCode) || 'RESPONSECODE'; const responseCodeFromResponse = params[responseCodeField]; - // eslint-disable-next-line max-len - // const messageField = (config.partner.xmlrpc_field && config.partner.xmlrpc_field.message) || 'MESSAGE'; - // const messageFromResponse = params[messageField]; + const messageField = (config.partner.xmlrpc_field && config.partner.xmlrpc_field.message) || 'MESSAGE'; + const messageFromResponse = params[messageField]; const snField = (config.partner.xmlrpc_field && config.partner.xmlrpc_field.sn) || 'SN'; const snFromResponse = params[snField]; @@ -87,12 +88,22 @@ module.exports = (xid, trxIdFromCaller, xml, isCallback) => { const rc = translateRc(xid, responseCodeFromResponse) || '68'; - const sn = (rc === '00' && snFromResponse) || null; + const sn = ( + rc === '00' && ( + snFromResponse + || messageExtractor(patternRules.sn, messageFromResponse) + ) + ) || null; + + const amount = Number(messageExtractor(patternRules.price, messageFromResponse) || '') || null; + const balance = Number(messageExtractor(patternRules.balance, messageFromResponse) || '') || null; report(xid, { trx_id: trxId.toString(), rc, sn, + amount, + balance, message: { xid, responseType: isCallback ? 'CALLBACK' : 'DIRECT-RESPONSE', diff --git a/lib/pattern-rules.js b/lib/pattern-rules.js new file mode 100644 index 0000000..8e14a5c --- /dev/null +++ b/lib/pattern-rules.js @@ -0,0 +1,28 @@ +/** + * Rule pattern to be used by message extractor + */ +module.exports = { + sn: [ + { + pattern: '(?:^|,|\\.|;|\\s)SN\\s*[=: ]\\s*(.+?)(?:;|$)', + idx: 1, + disable: false, + }, + ], + price: [ + { + pattern: '(?:,|\\.|;|\\s)(?:HRG|HARGA)\\s*[=: ]\\s*(?:RP)*\\s*(([0-9]|\\.||,)+)', + idx: 1, + disable: false, + postprocessing: (val) => (val || '').replace(/[,.]/g, ''), + }, + ], + balance: [ + { + pattern: '(?:,|\\.|;|\\s)SAL(?:DO)*\\s*[=: ]\\s*(?:RP)*\\s*(([0-9]|\\.||,)+)', + idx: 1, + disable: false, + postprocessing: (val) => (val || '').replace(/[,.]/g, ''), + }, + ], +}; diff --git a/test/message-extractor.js b/test/message-extractor.js new file mode 100644 index 0000000..2f7cf8f --- /dev/null +++ b/test/message-extractor.js @@ -0,0 +1,57 @@ +/* global describe it */ + +// eslint-disable-next-line no-unused-vars +const should = require('should'); +const finder = require('../lib/message-extractor'); +const organicRules = require('../lib/pattern-rules'); + +describe('#message-extractor', () => { + it('should handle garbage input', () => { + should.not.exists(finder(null, null, '39A9909D')); + should.not.exists(finder(null, '', '8C046E19')); + should.not.exists(finder(null, 'ada', '4154D1DC')); + should.not.exists(finder([], 'ada'), '5511A78C'); + }); + + it('should return correct sn', () => { + finder( + organicRules.sn, + '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', + false, + ).should.equal('3438-2805-5518-4885-2577/A HANIS SACHRA/R1 /1300 VA/31,5', 'ST24 metro-reload 5B164B64'); + + finder( + organicRules.sn, + 'ISI TS10 KE 082324881979 , SUKSES. SAL=489700,HRG=10300,ID=1625459089388,SN=0061003777417733', + false, + ).should.equal('0061003777417733', 'PLINK 00FC0A03'); + }); + + it('should return correct price', () => { + finder( + organicRules.price, + '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', + false, + ).should.equal('50020', 'ST24 metro-reload 572DAAE1'); + + finder( + organicRules.price, + 'ISI TS10 KE 082324881979 , SUKSES. SAL=489700,HRG=10300,ID=1625459089388,SN=0061003777417733', + false, + ).should.equal('10300', 'PLINK DB7F7B1C'); + }); + + it('should return correct ending balance', () => { + finder( + organicRules.balance, + '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', + false, + ).should.equal('75856585', 'ST24 metro-reload 5E6CA14F'); + + finder( + organicRules.balance, + 'ISI TS10 KE 082324881979 , SUKSES. SAL=489700,HRG=10300,ID=1625459089388,SN=0061003777417733', + false, + ).should.equal('489700', 'PLINK 29C24CEA'); + }); +});