Commit 636896a548ae5c34ab5fe8e639903d8748b442c8

Authored by Adhidarma Hadiwinoto
1 parent 384d84098c
Exists in master

Hapus debug msisdn

Showing 1 changed file with 0 additions and 1 deletions Inline Diff

lib/partner-mkios.js
1 "use strict"; 1 "use strict";
2 2
3 const fs = require('fs'); 3 const fs = require('fs');
4 const moment = require('moment'); 4 const moment = require('moment');
5 5
6 const Modem = require('./modem'); 6 const Modem = require('./modem');
7 7
8 const pullgw = require('komodo-sdk/gateway/pull'); 8 const pullgw = require('komodo-sdk/gateway/pull');
9 9
10 const config = require('komodo-sdk/config'); 10 const config = require('komodo-sdk/config');
11 const logger = require('komodo-sdk/logger'); 11 const logger = require('komodo-sdk/logger');
12 const matrix = require('komodo-sdk/matrix'); 12 const matrix = require('komodo-sdk/matrix');
13 13
14 const modemDashboard = require('./modem-dashboard'); 14 const modemDashboard = require('./modem-dashboard');
15 15
16 const chipsJsonFile = process.cwd() + '/chips.json'; 16 const chipsJsonFile = process.cwd() + '/chips.json';
17 const chips = fs.existsSync(chipsJsonFile) ? require(chipsJsonFile) : {}; 17 const chips = fs.existsSync(chipsJsonFile) ? require(chipsJsonFile) : {};
18 18
19 if (config && config.debug_modem) { 19 if (config && config.debug_modem) {
20 process.env.KOMODO_DEBUG_MODEM=1; 20 process.env.KOMODO_DEBUG_MODEM=1;
21 } 21 }
22 22
23 if (!config || !config.partner || !config.partner.pin) { 23 if (!config || !config.partner || !config.partner.pin) {
24 logger.warn('Undefined PIN'); 24 logger.warn('Undefined PIN');
25 process.exit(1); 25 process.exit(1);
26 } 26 }
27 27
28 matrix.modem = {}; 28 matrix.modem = {};
29 29
30 matrix.not_ready = true; 30 matrix.not_ready = true;
31 matrix.not_ready_ts = null; 31 matrix.not_ready_ts = null;
32 matrix.not_ready_ts_readable = null; 32 matrix.not_ready_ts_readable = null;
33 matrix.not_ready_max_age_secs = null; 33 matrix.not_ready_max_age_secs = null;
34 34
35 matrix.stock = {}; 35 matrix.stock = {};
36 36
37 const db = require('./local-db').getConnection(); 37 const db = require('./local-db').getConnection();
38 const pendingArchive = require('./pending-archive'); 38 const pendingArchive = require('./pending-archive');
39 const patternMatcher = require('./pattern-rule-matcher'); 39 const patternMatcher = require('./pattern-rule-matcher');
40 const smsHandler = require('./sms-handler'); 40 const smsHandler = require('./sms-handler');
41 41
42 const modem = new Modem(config.partner.modem.dev, {baudRate: 115200}); 42 const modem = new Modem(config.partner.modem.dev, {baudRate: 115200});
43 43
44 const resumeHandlers = {}; 44 const resumeHandlers = {};
45 45
46 let last_trx_id = null; 46 let last_trx_id = null;
47 47
48 modem.on('open', function() { 48 modem.on('open', function() {
49 logger.info('Modem opened'); 49 logger.info('Modem opened');
50 50
51 const ussd_command = '*776*' + config.partner.pin + '#'; 51 const ussd_command = '*776*' + config.partner.pin + '#';
52 db.run("INSERT INTO ussd VALUES (?, ?, 'OUT', ?, ?)", moment().format('YYYY-MM-DD HH:mm:ss'), moment().format('YYYY-MM-DD'), matrix.modem.imsi, 'AT+CUSD=1,"' + ussd_command + '",15', function(err) { 52 db.run("INSERT INTO ussd VALUES (?, ?, 'OUT', ?, ?)", moment().format('YYYY-MM-DD HH:mm:ss'), moment().format('YYYY-MM-DD'), matrix.modem.imsi, 'AT+CUSD=1,"' + ussd_command + '",15', function(err) {
53 if (err) { 53 if (err) {
54 logger.warn('Error inserting ussd command (stock check) to local database', {err: err}); 54 logger.warn('Error inserting ussd command (stock check) to local database', {err: err});
55 } 55 }
56 }); 56 });
57 57
58 modem.sendUSSD(ussd_command, function() {}); 58 modem.sendUSSD(ussd_command, function() {});
59 }) 59 })
60 60
61 modem.on('imsi', function(imsi) { 61 modem.on('imsi', function(imsi) {
62 logger.verbose('IMSI: ' + imsi); 62 logger.verbose('IMSI: ' + imsi);
63 matrix.modem.imsi = imsi; 63 matrix.modem.imsi = imsi;
64 console.log(chips);
65 matrix.modem.msisdn = chips && chips.by_imsi && chips.by_imsi[imsi] && chips.by_imsi[imsi].msisdn ? chips.by_imsi[imsi].msisdn : config.partner.msisdn; 64 matrix.modem.msisdn = chips && chips.by_imsi && chips.by_imsi[imsi] && chips.by_imsi[imsi].msisdn ? chips.by_imsi[imsi].msisdn : config.partner.msisdn;
66 }) 65 })
67 66
68 67
69 function onIncomingSMS(sms) { 68 function onIncomingSMS(sms) {
70 logger.info('Incoming SMS', {sms: sms}); 69 logger.info('Incoming SMS', {sms: sms});
71 db.run("INSERT INTO sms VALUES (?, ?, 'IN', ?, ?, ?)", sms.created, moment(sms.created).format('YYYY-MM-DD'), matrix.modem.imsi, sms.sender, sms.msg, function(err) { 70 db.run("INSERT INTO sms VALUES (?, ?, 'IN', ?, ?, ?)", sms.created, moment(sms.created).format('YYYY-MM-DD'), matrix.modem.imsi, sms.sender, sms.msg, function(err) {
72 if (err) { 71 if (err) {
73 logger.warn('Error inserting sms to local database', {err: err}); 72 logger.warn('Error inserting sms to local database', {err: err});
74 } 73 }
75 }); 74 });
76 75
77 if (!smsHandler.isAllowedSender(sms.sender)) { 76 if (!smsHandler.isAllowedSender(sms.sender)) {
78 logger.verbose('Ignoring SMS from unknown sender', {sender: sms.sender}); 77 logger.verbose('Ignoring SMS from unknown sender', {sender: sms.sender});
79 return; 78 return;
80 } 79 }
81 80
82 const stocks = smsHandler.getMultiStockBalance(sms.msg); 81 const stocks = smsHandler.getMultiStockBalance(sms.msg);
83 if (stocks && Array.isArray(stocks) && stocks.length) { 82 if (stocks && Array.isArray(stocks) && stocks.length) {
84 stocks.forEach(function(stock) { 83 stocks.forEach(function(stock) {
85 const vals = stock.split('='); 84 const vals = stock.split('=');
86 updateStock(vals[0], vals[1]); 85 updateStock(vals[0], vals[1]);
87 }) 86 })
88 } 87 }
89 else { 88 else {
90 const stock = smsHandler.getStockBalance(sms.msg); 89 const stock = smsHandler.getStockBalance(sms.msg);
91 if (stock.name && stock.balance) { 90 if (stock.name && stock.balance) {
92 updateStock(stock.name, stock.balance); 91 updateStock(stock.name, stock.balance);
93 } 92 }
94 } 93 }
95 94
96 const destination = smsHandler.getDestination(sms.msg); 95 const destination = smsHandler.getDestination(sms.msg);
97 if (!destination) { 96 if (!destination) {
98 logger.verbose('Ignoring SMS with unknown trx destination'); 97 logger.verbose('Ignoring SMS with unknown trx destination');
99 return; 98 return;
100 } 99 }
101 100
102 const product = smsHandler.getProduct(sms.msg); 101 const product = smsHandler.getProduct(sms.msg);
103 if (!product) { 102 if (!product) {
104 logger.verbose('Ignoring SMS with unknown trx product'); 103 logger.verbose('Ignoring SMS with unknown trx product');
105 return; 104 return;
106 } 105 }
107 106
108 const trx_date = smsHandler.getTrxDate(sms.msg); 107 const trx_date = smsHandler.getTrxDate(sms.msg);
109 if (!trx_date) { 108 if (!trx_date) {
110 logger.verbose('Ignoring SMS with unknown trx date'); 109 logger.verbose('Ignoring SMS with unknown trx date');
111 return; 110 return;
112 } 111 }
113 112
114 logger.verbose('SMS message parsed and extracted', {destination: destination, product: product, trx_date: trx_date}); 113 logger.verbose('SMS message parsed and extracted', {destination: destination, product: product, trx_date: trx_date});
115 pendingArchive.get(destination, product, trx_date, function(err, trx_id) { 114 pendingArchive.get(destination, product, trx_date, function(err, trx_id) {
116 if (!trx_id) { 115 if (!trx_id) {
117 logger.verbose('No pending trx suits with SMS', {destination: destination, product: product, trx_date: trx_date}); 116 logger.verbose('No pending trx suits with SMS', {destination: destination, product: product, trx_date: trx_date});
118 return; 117 return;
119 } 118 }
120 119
121 deleteResumeHandler(trx_id); 120 deleteResumeHandler(trx_id);
122 pendingArchive.remove(trx_id); 121 pendingArchive.remove(trx_id);
123 122
124 report({ 123 report({
125 trx_id: trx_id, 124 trx_id: trx_id,
126 rc: smsHandler.getRc(sms.msg) || '68', 125 rc: smsHandler.getRc(sms.msg) || '68',
127 sn: smsHandler.getSn(sms.msg), 126 sn: smsHandler.getSn(sms.msg),
128 message: 'SMS: ' + sms.msg 127 message: 'SMS: ' + sms.msg
129 }) 128 })
130 }) 129 })
131 130
132 } 131 }
133 modem.on('incoming sms', onIncomingSMS); 132 modem.on('incoming sms', onIncomingSMS);
134 133
135 modem.on('signal strength', function(signal_strength) { 134 modem.on('signal strength', function(signal_strength) {
136 matrix.modem.signal_strength = signal_strength; 135 matrix.modem.signal_strength = signal_strength;
137 logger.verbose('Signal strength: ' + signal_strength); 136 logger.verbose('Signal strength: ' + signal_strength);
138 }) 137 })
139 138
140 function onUSSDResponse(data) { 139 function onUSSDResponse(data) {
141 logger.verbose('Got USSD response', {response: data}); 140 logger.verbose('Got USSD response', {response: data});
142 141
143 db.run("INSERT INTO ussd VALUES (?, ?, 'IN', ?, ?)", moment().format('YYYY-MM-DD HH:mm:ss'), moment().format('YYYY-MM-DD'), matrix.modem.imsi, data, function(err) { 142 db.run("INSERT INTO ussd VALUES (?, ?, 'IN', ?, ?)", moment().format('YYYY-MM-DD HH:mm:ss'), moment().format('YYYY-MM-DD'), matrix.modem.imsi, data, function(err) {
144 if (err) { 143 if (err) {
145 logger.warn('Error inserting ussd response to local database', {err: err}); 144 logger.warn('Error inserting ussd response to local database', {err: err});
146 } 145 }
147 }); 146 });
148 147
149 148
150 if (!last_trx_id) return; 149 if (!last_trx_id) return;
151 150
152 151
153 const rc = getRcFromMessage(data, config.ussd_parser.rc) || '68'; 152 const rc = getRcFromMessage(data, config.ussd_parser.rc) || '68';
154 if (rc !== '68') { 153 if (rc !== '68') {
155 onTrxFinish(last_trx_id); 154 onTrxFinish(last_trx_id);
156 } 155 }
157 156
158 deleteResumeHandler(last_trx_id);; 157 deleteResumeHandler(last_trx_id);;
159 unsuspendPull(); 158 unsuspendPull();
160 159
161 report({ 160 report({
162 trx_id: last_trx_id, 161 trx_id: last_trx_id,
163 rc: rc, 162 rc: rc,
164 sn: getSnFromMessage(data), 163 sn: getSnFromMessage(data),
165 message: data 164 message: data
166 }); 165 });
167 166
168 const stock_name = getStockProductFromMessage(data); 167 const stock_name = getStockProductFromMessage(data);
169 const stock_balance = getStockBalanceFromMesssage(data); 168 const stock_balance = getStockBalanceFromMesssage(data);
170 169
171 updateStock(stock_name, stock_balance); 170 updateStock(stock_name, stock_balance);
172 last_trx_id = null; 171 last_trx_id = null;
173 } 172 }
174 173
175 modem.on('ussd response', onUSSDResponse); 174 modem.on('ussd response', onUSSDResponse);
176 175
177 176
178 logger.info('Opening MODEM'); 177 logger.info('Opening MODEM');
179 modem.open(function(err) { 178 modem.open(function(err) {
180 if (err) { 179 if (err) {
181 logger.warn('Error opening modem port', {err: err}); 180 logger.warn('Error opening modem port', {err: err});
182 process.exit(1); 181 process.exit(1);
183 } 182 }
184 183
185 logger.info('Modem open successfully, going to ready in 30 secs'); 184 logger.info('Modem open successfully, going to ready in 30 secs');
186 setTimeout( unsuspendPull, 30 * 1000 ) 185 setTimeout( unsuspendPull, 30 * 1000 )
187 186
188 }) 187 })
189 188
190 function updateStock(stock_name, stock_balance) { 189 function updateStock(stock_name, stock_balance) {
191 if (stock_name && (stock_balance !== undefined || stock_balance !== null)) { 190 if (stock_name && (stock_balance !== undefined || stock_balance !== null)) {
192 logger.verbose('Updating stock', {stock_name: stock_name, stock_balance: stock_balance}); 191 logger.verbose('Updating stock', {stock_name: stock_name, stock_balance: stock_balance});
193 192
194 const new_stock_name = config && config.remote_product_alias && config.remote_product_alias[stock_name] ? config.remote_product_alias[stock_name] : stock_name; 193 const new_stock_name = config && config.remote_product_alias && config.remote_product_alias[stock_name] ? config.remote_product_alias[stock_name] : stock_name;
195 194
196 matrix.stock[new_stock_name] = Number(stock_balance); 195 matrix.stock[new_stock_name] = Number(stock_balance);
197 196
198 logger.verbose('Stock balance updated', {stock: matrix.stock}); 197 logger.verbose('Stock balance updated', {stock: matrix.stock});
199 } 198 }
200 } 199 }
201 200
202 function getRcFromMessage(msg, rules) { 201 function getRcFromMessage(msg, rules) {
203 if (!rules || !Array.isArray(rules)) { 202 if (!rules || !Array.isArray(rules)) {
204 return '68'; 203 return '68';
205 } 204 }
206 205
207 for (let rule of rules) { 206 for (let rule of rules) {
208 if (!rule.pattern) return '68'; 207 if (!rule.pattern) return '68';
209 208
210 const re = new RegExp(rule.pattern); 209 const re = new RegExp(rule.pattern);
211 if (msg.search(re) >= 0) { 210 if (msg.search(re) >= 0) {
212 return rule.rc ? rule.rc : '68'; 211 return rule.rc ? rule.rc : '68';
213 } 212 }
214 } 213 }
215 214
216 return '68'; 215 return '68';
217 } 216 }
218 217
219 function getPatternMatchFromMessage(msg, rules) { 218 function getPatternMatchFromMessage(msg, rules) {
220 if (!rules || !Array.isArray(rules)) { 219 if (!rules || !Array.isArray(rules)) {
221 return; 220 return;
222 } 221 }
223 222
224 for (let rule of rules) { 223 for (let rule of rules) {
225 if (!rule.pattern) return; 224 if (!rule.pattern) return;
226 225
227 const re = new RegExp(rule.pattern); 226 const re = new RegExp(rule.pattern);
228 const matches = msg.match(re); 227 const matches = msg.match(re);
229 228
230 if (matches && matches.length >= 2) { 229 if (matches && matches.length >= 2) {
231 return matches[1]; 230 return matches[1];
232 } 231 }
233 } 232 }
234 } 233 }
235 234
236 function getSnFromMessage(msg, rules) { 235 function getSnFromMessage(msg, rules) {
237 return patternMatcher(msg, config.ussd_parser.sn); 236 return patternMatcher(msg, config.ussd_parser.sn);
238 } 237 }
239 238
240 function getStockProductFromMessage(msg, rules) { 239 function getStockProductFromMessage(msg, rules) {
241 return patternMatcher(msg, config.ussd_parser.stock.product); 240 return patternMatcher(msg, config.ussd_parser.stock.product);
242 } 241 }
243 242
244 function getStockBalanceFromMesssage(msg, rules) { 243 function getStockBalanceFromMesssage(msg, rules) {
245 return patternMatcher(msg, config.ussd_parser.stock.balance); 244 return patternMatcher(msg, config.ussd_parser.stock.balance);
246 } 245 }
247 246
248 function suspendPull(trx_id) { 247 function suspendPull(trx_id) {
249 logger.verbose('Set modem to not ready so no other task can be entered and registering delayed resume'); 248 logger.verbose('Set modem to not ready so no other task can be entered and registering delayed resume');
250 matrix.not_ready = true; 249 matrix.not_ready = true;
251 matrix.not_ready_ts = new Date(); 250 matrix.not_ready_ts = new Date();
252 matrix.not_ready_ts_readable = moment(matrix.not_ready_ts).format('YYYY-MM-DD HH:mm:ss'); 251 matrix.not_ready_ts_readable = moment(matrix.not_ready_ts).format('YYYY-MM-DD HH:mm:ss');
253 252
254 resumeHandlers['trx' + trx_id] = setTimeout(function() { 253 resumeHandlers['trx' + trx_id] = setTimeout(function() {
255 logger.verbose('Resuming supsended modem', {trx_id: trx_id}); 254 logger.verbose('Resuming supsended modem', {trx_id: trx_id});
256 unsuspendPull(); 255 unsuspendPull();
257 report({ 256 report({
258 trx_id: trx_id, 257 trx_id: trx_id,
259 rc: '68', 258 rc: '68',
260 message: 'USSD timeout' 259 message: 'USSD timeout'
261 }) 260 })
262 }, Number(config.partner.modem.suspend_time_ms) || 20 * 1000 ); 261 }, Number(config.partner.modem.suspend_time_ms) || 20 * 1000 );
263 } 262 }
264 263
265 function unsuspendPull() { 264 function unsuspendPull() {
266 matrix.not_ready = false; 265 matrix.not_ready = false;
267 266
268 if (matrix.not_ready_ts) { 267 if (matrix.not_ready_ts) {
269 matrix.not_ready_max_age_secs = Math.max( (new Date() - matrix.not_ready_ts) / 1000, matrix.not_ready_max_age_secs ); 268 matrix.not_ready_max_age_secs = Math.max( (new Date() - matrix.not_ready_ts) / 1000, matrix.not_ready_max_age_secs );
270 } 269 }
271 270
272 logger.verbose('Modem is ready'); 271 logger.verbose('Modem is ready');
273 } 272 }
274 273
275 function deleteResumeHandler(trx_id) { 274 function deleteResumeHandler(trx_id) {
276 if (resumeHandlers['trx' + trx_id]) { 275 if (resumeHandlers['trx' + trx_id]) {
277 logger.verbose('Unregistering delayed resume of trx id ' + trx_id); 276 logger.verbose('Unregistering delayed resume of trx id ' + trx_id);
278 clearTimeout(resumeHandlers['trx' + trx_id]); 277 clearTimeout(resumeHandlers['trx' + trx_id]);
279 delete resumeHandlers['trx' + trx_id]; 278 delete resumeHandlers['trx' + trx_id];
280 } 279 }
281 } 280 }
282 281
283 function onTrxFinish(trx_id) { 282 function onTrxFinish(trx_id) {
284 deleteResumeHandler(trx_id); 283 deleteResumeHandler(trx_id);
285 pendingArchive.remove(trx_id); 284 pendingArchive.remove(trx_id);
286 unsuspendPull(); 285 unsuspendPull();
287 } 286 }
288 287
289 function buy(task) { 288 function buy(task) {
290 if (task.product === task.remote_product) { 289 if (task.product === task.remote_product) {
291 report({ 290 report({
292 trx_id: task.trx_id, 291 trx_id: task.trx_id,
293 rc: '40', 292 rc: '40',
294 message: 'INTERNAL: Gagal melakukan transaksi. Kode USSD belum terdefinisi.' 293 message: 'INTERNAL: Gagal melakukan transaksi. Kode USSD belum terdefinisi.'
295 }); 294 });
296 return; 295 return;
297 } 296 }
298 297
299 suspendPull(task.trx_id); 298 suspendPull(task.trx_id);
300 last_trx_id = task.trx_id; 299 last_trx_id = task.trx_id;
301 300
302 pendingArchive.put(task, function(err) { 301 pendingArchive.put(task, function(err) {
303 if (err) { 302 if (err) {
304 logger.verbose('Error inserting task to pending archive', {trx_id: task.trx_id, destination: task.destination, product: task.product, err: err}); 303 logger.verbose('Error inserting task to pending archive', {trx_id: task.trx_id, destination: task.destination, product: task.product, err: err});
305 onTrxFinish(task.trx_id); 304 onTrxFinish(task.trx_id);
306 report({ 305 report({
307 trx_id: task.trx_id, 306 trx_id: task.trx_id,
308 rc: '40', 307 rc: '40',
309 message: 'INTERNAL: Gagal melakukan transaksi. Mungkin ada transaksi dengan nomor dengan produk yang sama yang masih diproses. Silahkan ulangi beberapa saat lagi.' 308 message: 'INTERNAL: Gagal melakukan transaksi. Mungkin ada transaksi dengan nomor dengan produk yang sama yang masih diproses. Silahkan ulangi beberapa saat lagi.'
310 }); 309 });
311 310
312 return; 311 return;
313 } 312 }
314 313
315 const ussd_command = task.remote_product.split(',')[0].replace("<DESTINATION>", task.destination).replace("<PIN>", config.partner.pin); 314 const ussd_command = task.remote_product.split(',')[0].replace("<DESTINATION>", task.destination).replace("<PIN>", config.partner.pin);
316 logger.verbose('Going to execute USSD', {trx_id: task.trx_id, destination: task.destination, product: task.product, ussd: ussd_command}); 315 logger.verbose('Going to execute USSD', {trx_id: task.trx_id, destination: task.destination, product: task.product, ussd: ussd_command});
317 316
318 db.run("INSERT INTO ussd VALUES (?, ?, 'OUT', ?, ?)", moment().format('YYYY-MM-DD HH:mm:ss'), moment().format('YYYY-MM-DD'), matrix.modem.imsi, 'AT+CUSD=1,"' + ussd_command + '",15', function(err) { 317 db.run("INSERT INTO ussd VALUES (?, ?, 'OUT', ?, ?)", moment().format('YYYY-MM-DD HH:mm:ss'), moment().format('YYYY-MM-DD'), matrix.modem.imsi, 'AT+CUSD=1,"' + ussd_command + '",15', function(err) {
319 if (err) { 318 if (err) {
320 logger.warn('Error inserting ussd command to local database', {err: err}); 319 logger.warn('Error inserting ussd command to local database', {err: err});
321 } 320 }
322 }); 321 });
323 modem.sendUSSD(ussd_command, function() {}); 322 modem.sendUSSD(ussd_command, function() {});
324 }) 323 })
325 } 324 }
326 325
327 function report(data) { 326 function report(data) {
328 if (data.message) { 327 if (data.message) {
329 if (matrix.modem.imsi) { 328 if (matrix.modem.imsi) {
330 data.message = 'CHIP-IMSI: ' + matrix.modem.imsi + '; ' + data.message; 329 data.message = 'CHIP-IMSI: ' + matrix.modem.imsi + '; ' + data.message;
331 } 330 }
332 331
333 if (matrix.modem.msisdn) { 332 if (matrix.modem.msisdn) {
334 data.message = 'CHIP-MSISDN: ' + matrix.modem.msisdn + '; ' + data.message; 333 data.message = 'CHIP-MSISDN: ' + matrix.modem.msisdn + '; ' + data.message;
335 } 334 }
336 } 335 }
337 pullgw.report(data); 336 pullgw.report(data);
338 } 337 }
339 338
340 exports.buy = buy; 339 exports.buy = buy;
341 340