Commit 5544ecfdf51a9b95c3e0418d5c71fdd97e4f08ec
1 parent
6c417c09c4
Exists in
master
partner-im
Showing 4 changed files with 446 additions and 147 deletions Side-by-side Diff
adaptor-xmpp.js
... | ... | @@ -5,11 +5,10 @@ var password; |
5 | 5 | |
6 | 6 | var callbacks; |
7 | 7 | |
8 | - | |
9 | -function onLoginSuccessful(data) { | |
8 | +function onOnline(data) { | |
10 | 9 | logger.info('XMPP login successful', {data: data}); |
11 | - if (callbacks.onLoginSuccessful) { | |
12 | - callbacks.onLoginSuccessful(); | |
10 | + if (callbacks.onOnline) { | |
11 | + callbacks.onOnline(); | |
13 | 12 | } |
14 | 13 | } |
15 | 14 | |
... | ... | @@ -20,6 +19,11 @@ function onPM(sender, msg) { |
20 | 19 | } |
21 | 20 | } |
22 | 21 | |
22 | +function onError(err) { | |
23 | + logger.warn('XMPP error, terminating in 3 secs', {err: err}); | |
24 | + setTimeout(process.exit, 3000, 1); | |
25 | +} | |
26 | + | |
23 | 27 | function onSubscribe(sender) { |
24 | 28 | xmpp.acceptSubscription(sender); |
25 | 29 | } |
... | ... | @@ -30,7 +34,7 @@ function init(_username, _password, _logger, _callbacks) { |
30 | 34 | logger = _logger; |
31 | 35 | callbacks = _callbacks; |
32 | 36 | |
33 | - xmpp.on('online', onLoginSuccessful); | |
37 | + xmpp.on('online', onOnline); | |
34 | 38 | xmpp.on('chat', onPM); |
35 | 39 | xmpp.on('error', onError); |
36 | 40 | xmpp.on('subscribe', onSubscribe) |
index.js
1 | 1 | var fs = require('fs'); |
2 | 2 | var ini = require('ini'); |
3 | 3 | var expresso = require('sate24-expresso'); |
4 | -var partner = require('./partner-xmpp'); | |
5 | 4 | var config = ini.parse(fs.readFileSync(__dirname + '/config.ini', 'utf-8')); |
6 | 5 | |
7 | 6 | process.chdir(__dirname); |
... | ... | @@ -9,7 +8,9 @@ process.chdir(__dirname); |
9 | 8 | var logger = require('sate24/logger.js').start(); |
10 | 9 | var HttpServer = require('sate24/httpserver.js'); |
11 | 10 | var aaa = require('sate24/aaa.js'); |
12 | -var partner = require('./partner-ym.js'); | |
11 | +var partner = require('./partner-im.js'); | |
12 | +var imAdaptor = require('./adaptor-xmpp'); | |
13 | + | |
13 | 14 | |
14 | 15 | var matrix = aaa.prepareMatrix(); |
15 | 16 | |
... | ... | @@ -19,6 +20,7 @@ var options = { |
19 | 20 | 'config': config, |
20 | 21 | 'matrix': matrix, |
21 | 22 | 'partner': partner, |
23 | + 'imAdaptor': imAdaptor | |
22 | 24 | } |
23 | 25 | |
24 | 26 | var httpServer = HttpServer.start(config, options); |
partner-im.js
... | ... | @@ -0,0 +1,433 @@ |
1 | +var redis = require('redis'); | |
2 | +var moment = require('moment'); | |
3 | +var LRU = require('lru-cache'); | |
4 | + | |
5 | +var config; | |
6 | +var logger; | |
7 | +var aaa; | |
8 | +var callbackReport; | |
9 | +var partner; | |
10 | +var imConfig; | |
11 | +var redisClient; | |
12 | + | |
13 | +var resendHandlers = LRU({max: 2000, maxAge: 1000 * 3600 * 36}); | |
14 | + | |
15 | +function dumpStats() { | |
16 | + if (config.globals.auto_resend_delay_secs) { | |
17 | + logger.verbose('DUMP STATS', { | |
18 | + 'resendHandlers:length': resendHandlers.length, | |
19 | + 'resendHandlers:itemCount': resendHandlers.itemCount, | |
20 | + }); | |
21 | + } | |
22 | +} | |
23 | + | |
24 | +function dumpStatsPeriodic() { | |
25 | + var dumpStatsInterval = 1000 * 120; | |
26 | + if (config.globals.dump_stats_interval_secs) { | |
27 | + dumpStatsInterval = config.globals.dump_stats_interval_secs * 1000; | |
28 | + } | |
29 | + logger.verbose('Dump stats every ' + dumpStatsInterval / 1000 + ' secs (override it with config.globals.dump_stats_interval_secs)'); | |
30 | + setInterval(dumpStats, dumpStatsInterval); | |
31 | +} | |
32 | + | |
33 | +function init(options) { | |
34 | + if (options && options.config) { | |
35 | + config = options.config; | |
36 | + } else { | |
37 | + console.log(__filename + ': Undefined options.config. Terminating.'); | |
38 | + process.exit(230); | |
39 | + } | |
40 | + | |
41 | + if (options && options.logger) { | |
42 | + logger = options.logger; | |
43 | + } else { | |
44 | + console.log(__filename + ': Undefined options.logger. Terminating.'); | |
45 | + process.exit(231); | |
46 | + } | |
47 | + | |
48 | + if (options && options.partner) { | |
49 | + partner = options.partner; | |
50 | + } else { | |
51 | + logger.warn(__filename + ': Undefined options.partner. Terminating.'); | |
52 | + process.exit(232); | |
53 | + } | |
54 | + | |
55 | + if (options && options.aaa) { | |
56 | + aaa = options.aaa; | |
57 | + } else { | |
58 | + logger.warn(__filename + ': Undefined options.aaa. Terminating.'); | |
59 | + process.exit(233); | |
60 | + } | |
61 | + | |
62 | + if (options && options.aaa && options.aaa.callbackReport) { | |
63 | + callbackReport = options.aaa.callbackReport; | |
64 | + } else { | |
65 | + logger.warn(__filename + ': Unknown options.aaa.callbackReport') | |
66 | + process.exit(234); | |
67 | + } | |
68 | + | |
69 | + if (options && options.imAdaptor) { | |
70 | + imAdaptor = options.imAdaptor; | |
71 | + } else { | |
72 | + logger.warn(__filename + ': Unknown options.imAdaptor') | |
73 | + process.exit(235); | |
74 | + } | |
75 | + | |
76 | + var imAdaptorcallbacks = { | |
77 | + onOnline: onOnline, | |
78 | + onPM: onPM, | |
79 | + } | |
80 | + | |
81 | + imAdaptor.init(config.h2h_out.im_username, config.h2h_out.im_password, logger, imAdaptorcallbacks); | |
82 | + | |
83 | + createRedisClient(config.globals.redis_host, config.globals.redis_port); | |
84 | + readImConfig(); | |
85 | + | |
86 | + dumpStatsPeriodic(); | |
87 | +} | |
88 | + | |
89 | +function createRedisClient(host, port) { | |
90 | + try { | |
91 | + redisClient = redis.createClient(port, host); | |
92 | + } catch(err) { | |
93 | + logger.warn("Error creating redis client to " + host + ':' + port); | |
94 | + } | |
95 | +} | |
96 | + | |
97 | +function readImConfig(filename) { | |
98 | + | |
99 | + if (!filename) { | |
100 | + filename = process.cwd() + '/config.im.json'; | |
101 | + } | |
102 | + | |
103 | + try { | |
104 | + imConfig = require(filename); | |
105 | + } | |
106 | + catch(e) { | |
107 | + imConfig = {}; | |
108 | + } | |
109 | + | |
110 | + logger.verbose('IM Config', {imConfig: imConfig}); | |
111 | + return imConfig; | |
112 | +} | |
113 | + | |
114 | +function getPatternFromMessage(message, pattern, patternMatchIndex) { | |
115 | + var re = new RegExp(pattern); | |
116 | + var matches = message.match(re); | |
117 | + | |
118 | + if (!matches) { | |
119 | + return null; | |
120 | + } | |
121 | + | |
122 | + if (patternMatchIndex < matches.length) { | |
123 | + return matches[patternMatchIndex]; | |
124 | + } else { | |
125 | + return null; | |
126 | + } | |
127 | +} | |
128 | + | |
129 | +function getPatternsFromMessage(message, patterns) { | |
130 | + var patternCount = patterns.length; | |
131 | + for (var i = 0; i < patternCount; i++) { | |
132 | + | |
133 | + var pattern = patterns[i]; | |
134 | + | |
135 | + var result = getPatternFromMessage(message, pattern.pattern, pattern.matchIndex); | |
136 | + if (result) { | |
137 | + return result; | |
138 | + } | |
139 | + } | |
140 | +} | |
141 | + | |
142 | +function getTaskKey(task, chipInfo, today) { | |
143 | + if (!chipInfo && config && config.globals && config.globals.gateway_name) { | |
144 | + chipInfo = config.globals.gateway_name; | |
145 | + } | |
146 | + | |
147 | + if (task.timestamp && !today) { | |
148 | + today = moment(task.timestamp, 'YYYYMMDDHHmmss').format('YYYYMMDD'); | |
149 | + } | |
150 | + | |
151 | + return chipInfo + '.trx.date:' + today + '.rProduct:' + task.remoteProduct.toUpperCase() + '.dest:' + task.destination ; | |
152 | +} | |
153 | + | |
154 | +function saveTask(task, cb) { | |
155 | + var key = getTaskKey(task, config.globals.gateway_name); | |
156 | + logger.verbose('Saving task', {key: key, task: task}); | |
157 | + | |
158 | + redisClient.set(key, JSON.stringify(task), function() { | |
159 | + redisClient.expire(key, 3600*24); | |
160 | + if (cb) { | |
161 | + cb(); | |
162 | + } | |
163 | + }); | |
164 | +} | |
165 | + | |
166 | +function getTask(remoteProduct, destination, cb) { | |
167 | + var dummyTask = { | |
168 | + remoteProduct: remoteProduct, | |
169 | + destination: destination, | |
170 | + } | |
171 | + | |
172 | + var key = getTaskKey(dummyTask, config.globals.gateway_name, moment().format('YYYYMMDD')); | |
173 | + redisClient.get(key, function(err, result) { | |
174 | + if (err) { | |
175 | + logger.verbose('getTask: task not found', {key: key, params: dummyTask}); | |
176 | + | |
177 | + cb(err, null); | |
178 | + return; | |
179 | + } | |
180 | + | |
181 | + var task = {}; | |
182 | + | |
183 | + try { | |
184 | + task = JSON.parse(result); | |
185 | + } | |
186 | + catch(e) { | |
187 | + logger.warn('getTask: Can not parse result', {key: key, params: dummyTask, data: result}); | |
188 | + err = "Can not parse result" | |
189 | + } | |
190 | + cb(err, task); | |
191 | + }); | |
192 | +} | |
193 | + | |
194 | +function deleteTask(remoteProduct, destination) { | |
195 | + var dummyTask = { | |
196 | + remoteProduct: remoteProduct, | |
197 | + destination: destination, | |
198 | + } | |
199 | + | |
200 | + var key = getTaskKey(dummyTask, config.globals.gateway_name, moment().format('YYYYMMDD')); | |
201 | + | |
202 | + try { | |
203 | + redisClient.del(key); | |
204 | + } | |
205 | + catch(e) {}; | |
206 | +} | |
207 | + | |
208 | +function createMessage(pattern, keywords) { | |
209 | + var msg = pattern; | |
210 | + | |
211 | + for (var key in keywords) { | |
212 | + msg = msg.replace('[' + key + ']', keywords[key]); | |
213 | + } | |
214 | + return msg; | |
215 | +} | |
216 | + | |
217 | +function getRemoteProductFromMessage(msg) { | |
218 | + return getPatternsFromMessage(msg, imConfig.product_patterns); | |
219 | +} | |
220 | + | |
221 | +function getDestinationFromMessage(msg) { | |
222 | + return getPatternsFromMessage(msg, imConfig.destination_patterns); | |
223 | +} | |
224 | + | |
225 | +function getSnFromMessage(msg) { | |
226 | + return getPatternsFromMessage(msg, imConfig.sn_patterns); | |
227 | +} | |
228 | + | |
229 | +function getRcFromMessage(msg) { | |
230 | + var rcs = imConfig.response_codes; | |
231 | + var rcsCount = rcs.length; | |
232 | + | |
233 | + for (var i = 0; i < rcsCount; i++) { | |
234 | + | |
235 | + var item = rcs[i]; | |
236 | + var re = new RegExp(item.pattern); | |
237 | + if (msg.search(re) != -1) { | |
238 | + return item.rc; | |
239 | + } | |
240 | + | |
241 | + } | |
242 | + return '68'; | |
243 | +} | |
244 | + | |
245 | +function isAllowedFrom(sender) { | |
246 | + if (!config || !config.h2h_out || !config.h2h_out.allowed_response_from) { | |
247 | + return true; | |
248 | + } | |
249 | + | |
250 | + whitelist = config.h2h_out.allowed_response_from.split(','); | |
251 | + whitelistCount = whitelist.length; | |
252 | + | |
253 | + for(var i=0; i<whitelistCount; i++) { | |
254 | + if (sender == whitelist[i]) { | |
255 | + return true; | |
256 | + } | |
257 | + } | |
258 | + | |
259 | + return false; | |
260 | +} | |
261 | + | |
262 | +function checkForSameDayDuplicate(task, cbNoDupe, cbDupe, cbDupeWithSameReqId) { | |
263 | + getTask(task.remoteProduct, task.destination, function(err, archivedTask) { | |
264 | + if (err) { | |
265 | + logger.warn('Error on checking same day duplicate', {task: task}); | |
266 | + cbNoDupe(task); | |
267 | + return; | |
268 | + } | |
269 | + | |
270 | + if (archivedTask && archivedTask.requestId) { | |
271 | + if (cbDupeWithSameReqId && task.requestId == archivedTask.requestId) { | |
272 | + logger.verbose('Duplicate trx on same day with same requestId', {task: task}); | |
273 | + cbDupeWithSameReqId(task, archivedTask); | |
274 | + return; | |
275 | + } | |
276 | + | |
277 | + logger.verbose('Duplicate trx on same day', {task: task, archivedTask: archivedTask}); | |
278 | + cbDupe(task, archivedTask); | |
279 | + return; | |
280 | + } | |
281 | + | |
282 | + cbNoDupe(task); | |
283 | + }); | |
284 | +} | |
285 | + | |
286 | +function registerResendDelay(task) { | |
287 | + if (!task.requestId) { | |
288 | + logger.warn('Invalid task on resendDelay') | |
289 | + return; | |
290 | + } | |
291 | + | |
292 | + if (!config || !config.globals || !Number(config.globals.auto_resend_delay_secs)) { | |
293 | + return; | |
294 | + } | |
295 | + | |
296 | + if (!partner || !partner.topupRequest) { | |
297 | + logger.warn('Skip request resend delay because partner.topupRequest is not exists'); | |
298 | + return; | |
299 | + } | |
300 | + | |
301 | + var retry = 10; | |
302 | + var oldHandler = resendHandlers.get(task.requestId); | |
303 | + if (oldHandler) { | |
304 | + retry = oldHandler.retry - 1; | |
305 | + | |
306 | + try { | |
307 | + cancelResendDelay(task); | |
308 | + } | |
309 | + catch(e) {} | |
310 | + } | |
311 | + | |
312 | + if (retry <= 0) { | |
313 | + logger.verbose('Resend delay retry exceeded', {task: task}); | |
314 | + cancelResendDelay(task); | |
315 | + return; | |
316 | + } | |
317 | + | |
318 | + logger.verbose('Registering resend delay task request', {task: task, delay: config.globals.auto_resend_delay_secs, retry: retry}); | |
319 | + var handlerData = { | |
320 | + handler: setTimeout(partner.topupRequest, config.globals.auto_resend_delay_secs * 1000, task), | |
321 | + task: task, | |
322 | + retry: retry | |
323 | + } | |
324 | + | |
325 | + resendHandlers.set(task.requestId, handlerData); | |
326 | +} | |
327 | + | |
328 | +function cancelResendDelay(task) { | |
329 | + if (!task || !task.requestId) { | |
330 | + logger.warn('Invalid task on cancelResendDelay'); | |
331 | + return; | |
332 | + } | |
333 | + | |
334 | + var oldHandler = resendHandlers.get(task.requestId); | |
335 | + if (!oldHandler) { | |
336 | + return; | |
337 | + } | |
338 | + | |
339 | + logger.verbose('Canceling resend delay', {task: task}); | |
340 | + | |
341 | + try { | |
342 | + if (oldHandler.handler) { | |
343 | + clearTimeout(oldHandler.handler); | |
344 | + } | |
345 | + } | |
346 | + catch(e) {}; | |
347 | + | |
348 | + try { | |
349 | + resendHandlers.del(task.requestId); | |
350 | + } | |
351 | + catch(e) {}; | |
352 | +} | |
353 | + | |
354 | +function onOnline() { | |
355 | + logger.info('Login successful, resuming aaa communication'); | |
356 | + try { | |
357 | + aaa.resume(); | |
358 | + } | |
359 | + catch(e) { | |
360 | + logger.warn('Exception on resuming aaa module: ' + e); | |
361 | + } | |
362 | +} | |
363 | + | |
364 | +function onPM(from, msg) { | |
365 | + | |
366 | + if (!isAllowedFrom(from)) { | |
367 | + logger.info('Ignoring message from unknown sender', {from: from, msg: msg}); | |
368 | + return; | |
369 | + } | |
370 | + | |
371 | + var remoteProduct = getRemoteProductFromMessage(msg); | |
372 | + var destination = getDestinationFromMessage(msg); | |
373 | + | |
374 | + logger.verbose("Extract remoteProduct and destination from message", {remoteProduct: remoteProduct, destination: destination, msg: msg}); | |
375 | + | |
376 | + if (!remoteProduct || !destination) { | |
377 | + logger.info('Missing remote product or destination', {remoteProduct: remoteProduct, destination: destination, msg: msg}); | |
378 | + return; | |
379 | + } | |
380 | + | |
381 | + logger.info('Got report from partner', {remoteProduct: remoteProduct, destination: destination, msg: msg}); | |
382 | + getTask(remoteProduct, destination, function(err, task) { | |
383 | + if (err) { | |
384 | + logger.warn('Error getting relevant task'); | |
385 | + return; | |
386 | + } | |
387 | + | |
388 | + if (!task) { | |
389 | + logger.warn('Something wrong, undefined task without error') | |
390 | + return; | |
391 | + } | |
392 | + | |
393 | + logger.verbose('Got relevant task', {task: task, msg: msg}); | |
394 | + | |
395 | + var rc = getRcFromMessage(msg); | |
396 | + if (rc == '00') { | |
397 | + var sn = getSnFromMessage(msg); | |
398 | + if (sn) { | |
399 | + msg = 'SN=' + sn + ';' + msg; | |
400 | + } | |
401 | + } | |
402 | + | |
403 | + if (['00', '55', '68'].indexOf(rc) == -1) { | |
404 | + deleteTask(remoteProduct, destination); | |
405 | + } | |
406 | + | |
407 | + if (rc != '68') { | |
408 | + cancelResendDelay(task); | |
409 | + } | |
410 | + | |
411 | + callbackReport(task.requestId, rc, msg); | |
412 | + }); | |
413 | +} | |
414 | + | |
415 | +exports.init = init; | |
416 | +exports.start = init; | |
417 | +exports.getPatternFromMessage = getPatternFromMessage; | |
418 | +exports.getPatternsFromMessage = getPatternsFromMessage; | |
419 | +exports.saveTask = saveTask; | |
420 | +exports.getTask = getTask; | |
421 | +exports.readImConfig = readImConfig; | |
422 | +exports.createMessage = createMessage; | |
423 | +exports.getRemoteProductFromMessage = getRemoteProductFromMessage; | |
424 | +exports.getDestinationFromMessage = getDestinationFromMessage; | |
425 | +exports.getRcFromMessage = getRcFromMessage; | |
426 | +exports.getSnFromMessage = getSnFromMessage; | |
427 | +exports.isAllowedFrom = isAllowedFrom; | |
428 | +exports.checkForSameDayDuplicate = checkForSameDayDuplicate; | |
429 | +exports.deleteTask = deleteTask; | |
430 | +exports.registerResendDelay = registerResendDelay; | |
431 | +exports.cancelResendDelay = cancelResendDelay; | |
432 | +exports.onOnline = onOnline; | |
433 | +exports.onPM = onPM; |
partner-xmpp.js
... | ... | @@ -1,140 +0,0 @@ |
1 | -var im = require('sate24/im.js') | |
2 | -var imAdaptor = require('./adaptor-xmpp'); | |
3 | - | |
4 | -var config; | |
5 | -var aaa; | |
6 | -var logger; | |
7 | -var callbackReport; | |
8 | - | |
9 | -function onLoginSuccessful() { | |
10 | - logger.info('Login successful, resuming aaa communication'); | |
11 | - aaa.resume(); | |
12 | -} | |
13 | - | |
14 | -function onPM(from, msg) { | |
15 | - | |
16 | - if (!im.isAllowedFrom(from)) { | |
17 | - logger.info('Ignoring message from unknown sender', {from: from, msg: msg}); | |
18 | - return; | |
19 | - } | |
20 | - | |
21 | - var remoteProduct = im.getRemoteProductFromMessage(msg); | |
22 | - var destination = im.getDestinationFromMessage(msg); | |
23 | - | |
24 | - if (!remoteProduct && !destination) { | |
25 | - logger.warn('Missing remote product or destination', {remoteProduct: remoteProduct, destination: destination, msg: msg}); | |
26 | - return; | |
27 | - } | |
28 | - | |
29 | - logger.info('Got report from partner', {remoteProduct: remoteProduct, destination: destination, msg: msg}); | |
30 | - im.getTask(remoteProduct, destination, function(err, task) { | |
31 | - if (err) { | |
32 | - logger.warn('Error getting relevant task'); | |
33 | - return; | |
34 | - } | |
35 | - | |
36 | - if (!task) { | |
37 | - logger.warn('Something wrong, undefined task without error') | |
38 | - return; | |
39 | - } | |
40 | - | |
41 | - logger.verbose('Got relevant task', {task: task, msg: msg}); | |
42 | - var rc = im.getRcFromMessage(msg); | |
43 | - if (rc == '00') { | |
44 | - var sn = im.getSnFromMessage(msg); | |
45 | - if (sn) { | |
46 | - msg = 'SN=' + sn + ';' + msg; | |
47 | - } | |
48 | - } | |
49 | - | |
50 | - if (['00', '55', '68'].indexOf(rc) == -1) { | |
51 | - im.deleteTask(remoteProduct, destination); | |
52 | - } | |
53 | - | |
54 | - if (rc != '68') { | |
55 | - im.cancelResendDelay(task); | |
56 | - } | |
57 | - | |
58 | - callbackReport(task.requestId, rc, msg); | |
59 | - }); | |
60 | -} | |
61 | - | |
62 | -function start(options) { | |
63 | - if (options && options.config) { | |
64 | - config = options.config; | |
65 | - } else { | |
66 | - console.log('Unknown options.config'); | |
67 | - process.exit('1'); | |
68 | - } | |
69 | - | |
70 | - if (options && options.aaa) { | |
71 | - aaa = options.aaa; | |
72 | - } | |
73 | - | |
74 | - if (options && options.aaa && options.aaa.callbackReport) { | |
75 | - callbackReport = options.aaa.callbackReport; | |
76 | - } else { | |
77 | - console.log('Unknown options.aaa.callbackReport') | |
78 | - process.exit(2); | |
79 | - } | |
80 | - | |
81 | - if (options && options.logger) { | |
82 | - logger = options.logger; | |
83 | - } else { | |
84 | - logger = new winston.Logger({ | |
85 | - transports: [ | |
86 | - new (winston.transports.Console)() | |
87 | - ] | |
88 | - }); | |
89 | - } | |
90 | - | |
91 | - var callbacks = { | |
92 | - onLoginSuccessful: onLoginSuccessful, | |
93 | - onPM: onPM, | |
94 | - } | |
95 | - | |
96 | - im.init(options); | |
97 | - imAdaptor.init(config.h2h_out.ym_id, config.h2h_out.ym_password, logger, callbacks); | |
98 | -} | |
99 | - | |
100 | -function onSameDayDupe(task, archivedTask) { | |
101 | - if (task.requestId == archivedTask.requestId) { | |
102 | - logger.info('Mengulang trx untuk advice', {task: task}); | |
103 | - _topupRequest(task); | |
104 | - } else { | |
105 | - logger.info('Terdeteksi trx sama dalam satu hari yang sama', {task: task}); | |
106 | - callbackReport(task.requestId, '55', 'Terdeteksi trx sama dalam satu hari yang sama'); | |
107 | - } | |
108 | -} | |
109 | - | |
110 | -function _topupRequest(task) { | |
111 | - var pattern = config.h2h_out.request_pattern; | |
112 | - | |
113 | - var keywords = { | |
114 | - remoteProduct: task.remoteProduct, | |
115 | - destination: task.destination, | |
116 | - pin: config.h2h_out.pin | |
117 | - } | |
118 | - | |
119 | - im.saveTask(task, function() { | |
120 | - im.registerResendDelay(task); | |
121 | - | |
122 | - var msg = im.createMessage(pattern, keywords); | |
123 | - imAdaptor.sendMessage(config.h2h_out.partner, msg); | |
124 | - }); | |
125 | - | |
126 | -} | |
127 | - | |
128 | -function topupRequest(task) { | |
129 | - if (!aaa.isTodayTrx(task)) { | |
130 | - logger.warn('Maaf, transaksi beda hari tidak dapat dilakukan'); | |
131 | - callbackReport(task.requestId, '68', 'Maaf, transaksi beda hari tidak dapat dilakukan'); | |
132 | - im.cancelResendDelay(task); | |
133 | - return; | |
134 | - } | |
135 | - | |
136 | - im.checkForSameDayDuplicate(task, _topupRequest, onSameDayDupe, _topupRequest); | |
137 | -} | |
138 | - | |
139 | -exports.start = start; | |
140 | -exports.topupRequest = topupRequest; |