Commit a3472a346deae2225ea34276c99d1e677e114e24
1 parent
d46698ccca
Exists in
master
modem msisdn on matrix
Showing 1 changed file with 3 additions and 3 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 | 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 | }) | 65 | }) |
65 | 66 | ||
66 | 67 | ||
67 | function onIncomingSMS(sms) { | 68 | function onIncomingSMS(sms) { |
68 | logger.info('Incoming SMS', {sms: sms}); | 69 | logger.info('Incoming SMS', {sms: sms}); |
69 | 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) { |
70 | if (err) { | 71 | if (err) { |
71 | logger.warn('Error inserting sms to local database', {err: err}); | 72 | logger.warn('Error inserting sms to local database', {err: err}); |
72 | } | 73 | } |
73 | }); | 74 | }); |
74 | 75 | ||
75 | if (!smsHandler.isAllowedSender(sms.sender)) { | 76 | if (!smsHandler.isAllowedSender(sms.sender)) { |
76 | logger.verbose('Ignoring SMS from unknown sender', {sender: sms.sender}); | 77 | logger.verbose('Ignoring SMS from unknown sender', {sender: sms.sender}); |
77 | return; | 78 | return; |
78 | } | 79 | } |
79 | 80 | ||
80 | const stocks = smsHandler.getMultiStockBalance(sms.msg); | 81 | const stocks = smsHandler.getMultiStockBalance(sms.msg); |
81 | if (stocks && Array.isArray(stocks) && stocks.length) { | 82 | if (stocks && Array.isArray(stocks) && stocks.length) { |
82 | stocks.forEach(function(stock) { | 83 | stocks.forEach(function(stock) { |
83 | const vals = stock.split('='); | 84 | const vals = stock.split('='); |
84 | updateStock(vals[0], vals[1]); | 85 | updateStock(vals[0], vals[1]); |
85 | }) | 86 | }) |
86 | } | 87 | } |
87 | else { | 88 | else { |
88 | const stock = smsHandler.getStockBalance(sms.msg); | 89 | const stock = smsHandler.getStockBalance(sms.msg); |
89 | if (stock.name && stock.balance) { | 90 | if (stock.name && stock.balance) { |
90 | updateStock(stock.name, stock.balance); | 91 | updateStock(stock.name, stock.balance); |
91 | } | 92 | } |
92 | } | 93 | } |
93 | 94 | ||
94 | const destination = smsHandler.getDestination(sms.msg); | 95 | const destination = smsHandler.getDestination(sms.msg); |
95 | if (!destination) { | 96 | if (!destination) { |
96 | logger.verbose('Ignoring SMS with unknown trx destination'); | 97 | logger.verbose('Ignoring SMS with unknown trx destination'); |
97 | return; | 98 | return; |
98 | } | 99 | } |
99 | 100 | ||
100 | const product = smsHandler.getProduct(sms.msg); | 101 | const product = smsHandler.getProduct(sms.msg); |
101 | if (!product) { | 102 | if (!product) { |
102 | logger.verbose('Ignoring SMS with unknown trx product'); | 103 | logger.verbose('Ignoring SMS with unknown trx product'); |
103 | return; | 104 | return; |
104 | } | 105 | } |
105 | 106 | ||
106 | const trx_date = smsHandler.getTrxDate(sms.msg); | 107 | const trx_date = smsHandler.getTrxDate(sms.msg); |
107 | if (!trx_date) { | 108 | if (!trx_date) { |
108 | logger.verbose('Ignoring SMS with unknown trx date'); | 109 | logger.verbose('Ignoring SMS with unknown trx date'); |
109 | return; | 110 | return; |
110 | } | 111 | } |
111 | 112 | ||
112 | 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}); |
113 | pendingArchive.get(destination, product, trx_date, function(err, trx_id) { | 114 | pendingArchive.get(destination, product, trx_date, function(err, trx_id) { |
114 | if (!trx_id) { | 115 | if (!trx_id) { |
115 | 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}); |
116 | return; | 117 | return; |
117 | } | 118 | } |
118 | 119 | ||
119 | deleteResumeHandler(trx_id); | 120 | deleteResumeHandler(trx_id); |
120 | pendingArchive.remove(trx_id); | 121 | pendingArchive.remove(trx_id); |
121 | 122 | ||
122 | report({ | 123 | report({ |
123 | trx_id: trx_id, | 124 | trx_id: trx_id, |
124 | rc: smsHandler.getRc(sms.msg) || '68', | 125 | rc: smsHandler.getRc(sms.msg) || '68', |
125 | sn: smsHandler.getSn(sms.msg), | 126 | sn: smsHandler.getSn(sms.msg), |
126 | message: 'SMS: ' + sms.msg | 127 | message: 'SMS: ' + sms.msg |
127 | }) | 128 | }) |
128 | }) | 129 | }) |
129 | 130 | ||
130 | } | 131 | } |
131 | modem.on('incoming sms', onIncomingSMS); | 132 | modem.on('incoming sms', onIncomingSMS); |
132 | 133 | ||
133 | modem.on('signal strength', function(signal_strength) { | 134 | modem.on('signal strength', function(signal_strength) { |
134 | matrix.modem.signal_strength = signal_strength; | 135 | matrix.modem.signal_strength = signal_strength; |
135 | logger.verbose('Signal strength: ' + signal_strength); | 136 | logger.verbose('Signal strength: ' + signal_strength); |
136 | }) | 137 | }) |
137 | 138 | ||
138 | function onUSSDResponse(data) { | 139 | function onUSSDResponse(data) { |
139 | logger.verbose('Got USSD response', {response: data}); | 140 | logger.verbose('Got USSD response', {response: data}); |
140 | 141 | ||
141 | 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) { |
142 | if (err) { | 143 | if (err) { |
143 | logger.warn('Error inserting ussd response to local database', {err: err}); | 144 | logger.warn('Error inserting ussd response to local database', {err: err}); |
144 | } | 145 | } |
145 | }); | 146 | }); |
146 | 147 | ||
147 | 148 | ||
148 | if (!last_trx_id) return; | 149 | if (!last_trx_id) return; |
149 | 150 | ||
150 | 151 | ||
151 | const rc = getRcFromMessage(data, config.ussd_parser.rc) || '68'; | 152 | const rc = getRcFromMessage(data, config.ussd_parser.rc) || '68'; |
152 | if (rc !== '68') { | 153 | if (rc !== '68') { |
153 | onTrxFinish(last_trx_id); | 154 | onTrxFinish(last_trx_id); |
154 | } | 155 | } |
155 | 156 | ||
156 | deleteResumeHandler(last_trx_id);; | 157 | deleteResumeHandler(last_trx_id);; |
157 | unsuspendPull(); | 158 | unsuspendPull(); |
158 | 159 | ||
159 | report({ | 160 | report({ |
160 | trx_id: last_trx_id, | 161 | trx_id: last_trx_id, |
161 | rc: rc, | 162 | rc: rc, |
162 | sn: getSnFromMessage(data), | 163 | sn: getSnFromMessage(data), |
163 | message: data | 164 | message: data |
164 | }); | 165 | }); |
165 | 166 | ||
166 | const stock_name = getStockProductFromMessage(data); | 167 | const stock_name = getStockProductFromMessage(data); |
167 | const stock_balance = getStockBalanceFromMesssage(data); | 168 | const stock_balance = getStockBalanceFromMesssage(data); |
168 | 169 | ||
169 | updateStock(stock_name, stock_balance); | 170 | updateStock(stock_name, stock_balance); |
170 | last_trx_id = null; | 171 | last_trx_id = null; |
171 | } | 172 | } |
172 | 173 | ||
173 | modem.on('ussd response', onUSSDResponse); | 174 | modem.on('ussd response', onUSSDResponse); |
174 | 175 | ||
175 | 176 | ||
176 | logger.info('Opening MODEM'); | 177 | logger.info('Opening MODEM'); |
177 | modem.open(function(err) { | 178 | modem.open(function(err) { |
178 | if (err) { | 179 | if (err) { |
179 | logger.warn('Error opening modem port', {err: err}); | 180 | logger.warn('Error opening modem port', {err: err}); |
180 | process.exit(1); | 181 | process.exit(1); |
181 | } | 182 | } |
182 | 183 | ||
183 | logger.info('Modem open successfully, going to ready in 30 secs'); | 184 | logger.info('Modem open successfully, going to ready in 30 secs'); |
184 | setTimeout( unsuspendPull, 30 * 1000 ) | 185 | setTimeout( unsuspendPull, 30 * 1000 ) |
185 | 186 | ||
186 | }) | 187 | }) |
187 | 188 | ||
188 | function updateStock(stock_name, stock_balance) { | 189 | function updateStock(stock_name, stock_balance) { |
189 | if (stock_name && (stock_balance !== undefined || stock_balance !== null)) { | 190 | if (stock_name && (stock_balance !== undefined || stock_balance !== null)) { |
190 | 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}); |
191 | 192 | ||
192 | 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; |
193 | 194 | ||
194 | matrix.stock[new_stock_name] = Number(stock_balance); | 195 | matrix.stock[new_stock_name] = Number(stock_balance); |
195 | 196 | ||
196 | logger.verbose('Stock balance updated', {stock: matrix.stock}); | 197 | logger.verbose('Stock balance updated', {stock: matrix.stock}); |
197 | } | 198 | } |
198 | } | 199 | } |
199 | 200 | ||
200 | function getRcFromMessage(msg, rules) { | 201 | function getRcFromMessage(msg, rules) { |
201 | if (!rules || !Array.isArray(rules)) { | 202 | if (!rules || !Array.isArray(rules)) { |
202 | return '68'; | 203 | return '68'; |
203 | } | 204 | } |
204 | 205 | ||
205 | for (let rule of rules) { | 206 | for (let rule of rules) { |
206 | if (!rule.pattern) return '68'; | 207 | if (!rule.pattern) return '68'; |
207 | 208 | ||
208 | const re = new RegExp(rule.pattern); | 209 | const re = new RegExp(rule.pattern); |
209 | if (msg.search(re) >= 0) { | 210 | if (msg.search(re) >= 0) { |
210 | return rule.rc ? rule.rc : '68'; | 211 | return rule.rc ? rule.rc : '68'; |
211 | } | 212 | } |
212 | } | 213 | } |
213 | 214 | ||
214 | return '68'; | 215 | return '68'; |
215 | } | 216 | } |
216 | 217 | ||
217 | function getPatternMatchFromMessage(msg, rules) { | 218 | function getPatternMatchFromMessage(msg, rules) { |
218 | if (!rules || !Array.isArray(rules)) { | 219 | if (!rules || !Array.isArray(rules)) { |
219 | return; | 220 | return; |
220 | } | 221 | } |
221 | 222 | ||
222 | for (let rule of rules) { | 223 | for (let rule of rules) { |
223 | if (!rule.pattern) return; | 224 | if (!rule.pattern) return; |
224 | 225 | ||
225 | const re = new RegExp(rule.pattern); | 226 | const re = new RegExp(rule.pattern); |
226 | const matches = msg.match(re); | 227 | const matches = msg.match(re); |
227 | 228 | ||
228 | if (matches && matches.length >= 2) { | 229 | if (matches && matches.length >= 2) { |
229 | return matches[1]; | 230 | return matches[1]; |
230 | } | 231 | } |
231 | } | 232 | } |
232 | } | 233 | } |
233 | 234 | ||
234 | function getSnFromMessage(msg, rules) { | 235 | function getSnFromMessage(msg, rules) { |
235 | return patternMatcher(msg, config.ussd_parser.sn); | 236 | return patternMatcher(msg, config.ussd_parser.sn); |
236 | } | 237 | } |
237 | 238 | ||
238 | function getStockProductFromMessage(msg, rules) { | 239 | function getStockProductFromMessage(msg, rules) { |
239 | return patternMatcher(msg, config.ussd_parser.stock.product); | 240 | return patternMatcher(msg, config.ussd_parser.stock.product); |
240 | } | 241 | } |
241 | 242 | ||
242 | function getStockBalanceFromMesssage(msg, rules) { | 243 | function getStockBalanceFromMesssage(msg, rules) { |
243 | return patternMatcher(msg, config.ussd_parser.stock.balance); | 244 | return patternMatcher(msg, config.ussd_parser.stock.balance); |
244 | } | 245 | } |
245 | 246 | ||
246 | function suspendPull(trx_id) { | 247 | function suspendPull(trx_id) { |
247 | 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'); |
248 | matrix.not_ready = true; | 249 | matrix.not_ready = true; |
249 | matrix.not_ready_ts = new Date(); | 250 | matrix.not_ready_ts = new Date(); |
250 | 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'); |
251 | 252 | ||
252 | resumeHandlers['trx' + trx_id] = setTimeout(function() { | 253 | resumeHandlers['trx' + trx_id] = setTimeout(function() { |
253 | logger.verbose('Resuming supsended modem', {trx_id: trx_id}); | 254 | logger.verbose('Resuming supsended modem', {trx_id: trx_id}); |
254 | unsuspendPull(); | 255 | unsuspendPull(); |
255 | report({ | 256 | report({ |
256 | trx_id: trx_id, | 257 | trx_id: trx_id, |
257 | rc: '68', | 258 | rc: '68', |
258 | message: 'USSD timeout' | 259 | message: 'USSD timeout' |
259 | }) | 260 | }) |
260 | }, Number(config.partner.modem.suspend_time_ms) || 20 * 1000 ); | 261 | }, Number(config.partner.modem.suspend_time_ms) || 20 * 1000 ); |
261 | } | 262 | } |
262 | 263 | ||
263 | function unsuspendPull() { | 264 | function unsuspendPull() { |
264 | matrix.not_ready = false; | 265 | matrix.not_ready = false; |
265 | 266 | ||
266 | if (matrix.not_ready_ts) { | 267 | if (matrix.not_ready_ts) { |
267 | 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 ); |
268 | } | 269 | } |
269 | 270 | ||
270 | logger.verbose('Modem is ready'); | 271 | logger.verbose('Modem is ready'); |
271 | } | 272 | } |
272 | 273 | ||
273 | function deleteResumeHandler(trx_id) { | 274 | function deleteResumeHandler(trx_id) { |
274 | if (resumeHandlers['trx' + trx_id]) { | 275 | if (resumeHandlers['trx' + trx_id]) { |
275 | logger.verbose('Unregistering delayed resume of trx id ' + trx_id); | 276 | logger.verbose('Unregistering delayed resume of trx id ' + trx_id); |
276 | clearTimeout(resumeHandlers['trx' + trx_id]); | 277 | clearTimeout(resumeHandlers['trx' + trx_id]); |
277 | delete resumeHandlers['trx' + trx_id]; | 278 | delete resumeHandlers['trx' + trx_id]; |
278 | } | 279 | } |
279 | } | 280 | } |
280 | 281 | ||
281 | function onTrxFinish(trx_id) { | 282 | function onTrxFinish(trx_id) { |
282 | deleteResumeHandler(trx_id); | 283 | deleteResumeHandler(trx_id); |
283 | pendingArchive.remove(trx_id); | 284 | pendingArchive.remove(trx_id); |
284 | unsuspendPull(); | 285 | unsuspendPull(); |
285 | } | 286 | } |
286 | 287 | ||
287 | function buy(task) { | 288 | function buy(task) { |
288 | if (task.product === task.remote_product) { | 289 | if (task.product === task.remote_product) { |
289 | report({ | 290 | report({ |
290 | trx_id: task.trx_id, | 291 | trx_id: task.trx_id, |
291 | rc: '40', | 292 | rc: '40', |
292 | message: 'INTERNAL: Gagal melakukan transaksi. Kode USSD belum terdefinisi.' | 293 | message: 'INTERNAL: Gagal melakukan transaksi. Kode USSD belum terdefinisi.' |
293 | }); | 294 | }); |
294 | return; | 295 | return; |
295 | } | 296 | } |
296 | 297 | ||
297 | suspendPull(task.trx_id); | 298 | suspendPull(task.trx_id); |
298 | last_trx_id = task.trx_id; | 299 | last_trx_id = task.trx_id; |
299 | 300 | ||
300 | pendingArchive.put(task, function(err) { | 301 | pendingArchive.put(task, function(err) { |
301 | if (err) { | 302 | if (err) { |
302 | 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}); |
303 | onTrxFinish(task.trx_id); | 304 | onTrxFinish(task.trx_id); |
304 | report({ | 305 | report({ |
305 | trx_id: task.trx_id, | 306 | trx_id: task.trx_id, |
306 | rc: '40', | 307 | rc: '40', |
307 | 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.' |
308 | }); | 309 | }); |
309 | 310 | ||
310 | return; | 311 | return; |
311 | } | 312 | } |
312 | 313 | ||
313 | 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); |
314 | 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}); |
315 | 316 | ||
316 | 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) { |
317 | if (err) { | 318 | if (err) { |
318 | logger.warn('Error inserting ussd command to local database', {err: err}); | 319 | logger.warn('Error inserting ussd command to local database', {err: err}); |
319 | } | 320 | } |
320 | }); | 321 | }); |
321 | modem.sendUSSD(ussd_command, function() {}); | 322 | modem.sendUSSD(ussd_command, function() {}); |
322 | }) | 323 | }) |
323 | } | 324 | } |
324 | 325 | ||
325 | function report(data) { | 326 | function report(data) { |
326 | if (data.message) { | 327 | if (data.message) { |
327 | if (matrix.modem.imsi) { | 328 | if (matrix.modem.imsi) { |
328 | data.message = 'CHIP-IMSI: ' + matrix.modem.imsi + '; ' + data.message; | 329 | data.message = 'CHIP-IMSI: ' + matrix.modem.imsi + '; ' + data.message; |
329 | } | 330 | } |
330 | 331 | ||
331 | const msisdn = chips && chips.by_imsi && chips.by_imsi[imsi] && chips.by_imsi[imsi].msisdn ? chips.by_imsi[imsi].msisdn : config.partner.msisdn; | 332 | if (matrix.modem.msisdn) { |
332 | if (msisdn) { | 333 | data.message = 'CHIP-MSISDN: ' + matrix.modem.msisdn + '; ' + data.message; |
333 | data.message = 'CHIP-MSISDN: ' + msisdn + '; ' + data.message; | ||
334 | } | 334 | } |
335 | } | 335 | } |
336 | pullgw.report(data); | 336 | pullgw.report(data); |
337 | } | 337 | } |
338 | 338 | ||
339 | exports.buy = buy; | 339 | exports.buy = buy; |