Commit 95d2d017846a8a9e24dabbc89ae837491b7c303b

Authored by Adhidarma Hadiwinoto
1 parent ac60b51f7e
Exists in master

perbaikan mongo

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

1 var winston = require('winston'); 1 var winston = require('winston');
2 var crypto = require('crypto'); 2 var crypto = require('crypto');
3 var xml = require('xml'); 3 var xml = require('xml');
4 var url = require('url'); 4 var url = require('url');
5 var http = require('http'); 5 var http = require('http');
6 var xml2js = require('xml2js').parseString; 6 var xml2js = require('xml2js').parseString;
7 var mongoClient = require('mongodb').MongoClient; 7 var mongoClient = require('mongodb').MongoClient;
8 var strftime = require('strftime'); 8 var strftime = require('strftime');
9 var moment = require('moment'); 9 var moment = require('moment');
10 10
11 var config; 11 var config;
12 var callbackReport; 12 var callbackReport;
13 var aaa; 13 var aaa;
14 var logger; 14 var logger;
15 var options; 15 var options;
16 var mongodb; 16 var mongodb;
17 17
18 function initMongoClient() { 18 function initMongoClient() {
19 if (!config.mongodb || !config.mongodb.url) { 19 if (!config.mongodb || !config.mongodb.url) {
20 return; 20 return;
21 } 21 }
22 22
23 try { 23 try {
24 var url = config.mongodb.url; 24 var url = config.mongodb.url;
25 25
26 mongoClient.connect(url, function(err, db) { 26 mongoClient.connect(url, function(err, db) {
27 if (err) { 27 if (err) {
28 logger.warn('Failed to connect to mongodb', {err: err}); 28 logger.warn('Failed to connect to mongodb', {err: err});
29 return; 29 return;
30 } 30 }
31 mongodb = db; 31 mongodb = db;
32 logger.info('MongoDB connected'); 32 logger.info('MongoDB connected');
33 }); 33 });
34 } 34 }
35 catch(err) { 35 catch(err) {
36 logger.warn('Exception when connecting to mongodb', {err: err, url: url}); 36 logger.warn('Exception when connecting to mongodb', {err: err, url: url});
37 } 37 }
38 } 38 }
39 39
40 var maxRetry = 10; 40 var maxRetry = 10;
41 var sleepBeforeRetry = 30; 41 var sleepBeforeRetry = 30;
42 42
43 function start(_config, _callbackReport, options) { 43 function start(_config, _callbackReport, options) {
44 config = _config; 44 config = _config;
45 callbackReport = _callbackReport 45 callbackReport = _callbackReport
46 46
47 if (options && options.aaa) { 47 if (options && options.aaa) {
48 aaa = options.aaa; 48 aaa = options.aaa;
49 } 49 }
50 50
51 if (options && options.logger) { 51 if (options && options.logger) {
52 logger = options.logger; 52 logger = options.logger;
53 } else { 53 } else {
54 logger = new winston.Logger({ 54 logger = new winston.Logger({
55 transports: [ 55 transports: [
56 new (winston.transports.Console)() 56 new (winston.transports.Console)()
57 ] 57 ]
58 }); 58 });
59 } 59 }
60 60
61 initMongoClient(); 61 initMongoClient();
62 } 62 }
63 63
64 function calculateSignature(params) { 64 function calculateSignature(params) {
65 var passwordHash = crypto.createHash('sha1').update(params.password).digest().toString('hex'); 65 var passwordHash = crypto.createHash('sha1').update(params.password).digest().toString('hex');
66 var plain = params.trxtype + params.prdcode + params.value + params.msisdn + params.trxid + params.uid + passwordHash; 66 var plain = params.trxtype + params.prdcode + params.value + params.msisdn + params.trxid + params.uid + passwordHash;
67 var signature = crypto.createHash('sha256').update(plain).digest().toString('hex'); 67 var signature = crypto.createHash('sha256').update(plain).digest().toString('hex');
68 68
69 try { 69 try {
70 logger.verbose('Signature calculated', {plain: plain, signature: signature}); 70 logger.verbose('Signature calculated', {plain: plain, signature: signature});
71 } 71 }
72 catch(err) {} 72 catch(err) {}
73 73
74 return signature; 74 return signature;
75 } 75 }
76 76
77 function createXmlPayload(params) { 77 function createXmlPayload(params) {
78 var payload = "<?xml version=\"1.0\" ?>\n" + xml({ 78 var payload = "<?xml version=\"1.0\" ?>\n" + xml({
79 ciwaru: [ 79 ciwaru: [
80 {trxtype: params.trxtype}, 80 {trxtype: params.trxtype},
81 {prdcode: params.prdcode}, 81 {prdcode: params.prdcode},
82 {value: params.value}, 82 {value: params.value},
83 {msisdn: params.msisdn}, 83 {msisdn: params.msisdn},
84 {trxid: params.trxid}, 84 {trxid: params.trxid},
85 {uid: params.uid}, 85 {uid: params.uid},
86 {hash: calculateSignature(params)} 86 {hash: calculateSignature(params)}
87 ] 87 ]
88 }); 88 });
89 89
90 try { logger.verbose("Payload: " + payload); } 90 try { logger.verbose("Payload: " + payload); }
91 catch(errLog) {} 91 catch(errLog) {}
92 92
93 return payload; 93 return payload;
94 } 94 }
95 95
96 function insertTaskToMongoDb(task) { 96 function insertTaskToMongoDb(task) {
97 if (!isMongoReady()) { return; } 97 if (!isMongoReady()) { return; }
98 98
99 try { 99 try {
100 task.suppliers = []; 100 task.suppliers = [];
101 mongodb.collection(config.mongodb.collection).insertOne(task, function(err, result) { 101 mongodb.collection(config.mongodb.collection).insertOne(task, function(err, result) {
102
103 /*
102 mongodb.collection(config.mongodb.collection).updateOne( 104 mongodb.collection(config.mongodb.collection).updateOne(
103 {requestId: task.requestId}, 105 {requestId: task.requestId},
104 { 106 {
105 lastResponse: {}, 107 lastResponse: {},
106 $push: {suppliers: config.globals.gateway_name} 108 $push: {suppliers: config.globals.gateway_name}
107 } 109 }
108 110
109 ) 111 )
112 */
110 }); 113 });
111 } 114 }
112 catch(err) { 115 catch(err) {
113 //logger.warn('Exception when inserting document to mongodb', {err: err, task: task}); 116 //logger.warn('Exception when inserting document to mongodb', {err: err, task: task});
114 } 117 }
115 } 118 }
116 119
117 function pushResponseToMongoDb(task, response) { 120 function pushResponseToMongoDb(task, response) {
118 if (!isMongoReady()) { return; } 121 if (!isMongoReady()) { return; }
119 122
120 try { 123 try {
121 mongodb.collection(config.mongodb.collection).updateOne( 124 mongodb.collection(config.mongodb.collection).updateOne(
122 {requestId: task.requestId}, 125 {requestId: task.requestId},
123 { 126 {
124 $push: {responses: response} 127 $push: {responses: response}
125 }, 128 },
126 function(err, result) { 129 function(err, result) {
127 if (err) { 130 if (err) {
128 logger.warn('Error when pushing response to mongodb', {err: err, task: task, response: response}); 131 logger.warn('Error when pushing response to mongodb', {err: err, task: task, response: response});
129 return; 132 return;
130 } 133 }
131 } 134 }
132 ); 135 );
133 136
137 /*
134 if (response.parsed && response.parsed.ciwaru) { 138 if (response.parsed && response.parsed.ciwaru) {
135 mongodb.collection(config.mongodb.collection).updateOne( 139 mongodb.collection(config.mongodb.collection).updateOne(
136 {requestId: task.requestId}, 140 {requestId: task.requestId},
137 { 141 {
138 lastResponse: response.parsed.ciwaru 142 lastResponse: response.parsed.ciwaru
139 }, 143 },
140 function(err, result) { 144 function(err, result) {
141 if (err) { 145 if (err) {
142 logger.warn('Error when updating last response to mongodb', {err: err, task: task, response: response}); 146 logger.warn('Error when updating last response to mongodb', {err: err, task: task, response: response});
143 return; 147 return;
144 } 148 }
145 } 149 }
146 ); 150 );
147 } 151 }
152 */
148 153
149 } 154 }
150 catch(err) { 155 catch(err) {
151 logger.warn('Exception when pushing response to mongodb', {err: err, task: task, response: response}); 156 logger.warn('Exception when pushing response to mongodb', {err: err, task: task, response: response});
152 } 157 }
153 } 158 }
154 159
155 function isMongoReady() { 160 function isMongoReady() {
156 if (!config.mongodb) { return; } 161 if (!config.mongodb) { return; }
157 if (!config.mongodb.collection) { return; } 162 if (!config.mongodb.collection) { return; }
158 if (!mongodb) { return; } 163 if (!mongodb) { return; }
159 164
160 return true; 165 return true;
161 } 166 }
162 167
163 function getSNFromMessage(message) { 168 function getSNFromMessage(message) {
164 try { 169 try {
165 var sn_match = message.match(/SN: (\w+)/); 170 var sn_match = message.match(/SN: (\w+)/);
166 return sn_match[1].trim(); 171 return sn_match[1].trim();
167 } 172 }
168 catch(err) { 173 catch(err) {
169 if (logger) { 174 if (logger) {
170 logger.verbose('Exception on getting sn from message', {err: err}); 175 logger.verbose('Exception on getting sn from message', {err: err});
171 } 176 }
172 return ''; 177 return '';
173 } 178 }
174 } 179 }
175 180
176 function hasSuccessKeywords(message) { 181 function hasSuccessKeywords(message) {
177 var keywords = ['SUKSES', 'Finish']; 182 var keywords = ['SUKSES', 'Finish'];
178 183
179 var count = keywords.length; 184 var count = keywords.length;
180 for (var i=0; i < count; i++) { 185 for (var i=0; i < count; i++) {
181 if (message.indexOf(keywords[i]) >= 0) { 186 if (message.indexOf(keywords[i]) >= 0) {
182 return true; 187 return true;
183 } 188 }
184 } 189 }
185 return false; 190 return false;
186 } 191 }
187 192
188 function supplierRcToST24Rc(rc) { 193 function supplierRcToST24Rc(rc) {
189 var rcs = { 194 var rcs = {
190 '0001': '40', 195 '0001': '40',
191 '0012': '40', // hash data tidak sesuai 196 '0012': '40', // hash data tidak sesuai
192 '0019': '13', // produk tidak tersedia 197 '0019': '13', // produk tidak tersedia
193 } 198 }
194 199
195 if (rcs[rc]) { 200 if (rcs[rc]) {
196 return rcs[rc]; 201 return rcs[rc];
197 } else { 202 } else {
198 return; 203 return;
199 } 204 }
200 } 205 }
201 206
202 function getSNFromResponseObject(respObj) { 207 function getSNFromResponseObject(respObj) {
203 try { 208 try {
204 return respObj.ciwaru.sn[0].trim(); 209 return respObj.ciwaru.sn[0].trim();
205 } 210 }
206 catch(err) { 211 catch(err) {
207 return; 212 return;
208 } 213 }
209 } 214 }
210 215
211 function topupResponseHandler(body, task) { 216 function topupResponseHandler(body, task) {
212 217
213 //logger.info('Got reply from partner', {body: body}); 218 //logger.info('Got reply from partner', {body: body});
214 219
215 xml2js(body, function(err, result) { 220 xml2js(body, function(err, result) {
216 var ts = strftime('%Y-%m-%d %H:%M:%S', new Date()); 221 var ts = strftime('%Y-%m-%d %H:%M:%S', new Date());
217 222
218 if (err) { 223 if (err) {
219 logger.warn('Got invalid XML from partner', {err: err, body: body, task: task}); 224 logger.warn('Got invalid XML from partner', {err: err, body: body, task: task});
220 callbackReport(task.requestId, '68', body); 225 callbackReport(task.requestId, '68', body);
221 226
222 pushResponseToMongoDb(task, {ts: ts, raw: body}); 227 pushResponseToMongoDb(task, {ts: ts, raw: body});
223 return; 228 return;
224 } 229 }
225 logger.info('XML message from partner', {result: result}); 230 logger.info('XML message from partner', {result: result});
226 pushResponseToMongoDb(task, {ts: ts, raw: body, parsed: result}); 231 pushResponseToMongoDb(task, {ts: ts, raw: body, parsed: result});
227 232
228 var rc = '68'; 233 var rc = '68';
229 var message = result.ciwaru.msg[0]; 234 var message = result.ciwaru.msg[0];
230 235
231 if (message.toUpperCase().indexOf('PENDING') >= 0) { 236 if (message.toUpperCase().indexOf('PENDING') >= 0) {
232 rc = '68'; 237 rc = '68';
233 } 238 }
234 else if (hasSuccessKeywords(message)) { 239 else if (hasSuccessKeywords(message)) {
235 240
236 var sn = getSNFromResponseObject(result); 241 var sn = getSNFromResponseObject(result);
237 242
238 if (!sn) { 243 if (!sn) {
239 sn = getSNFromMessage(message); 244 sn = getSNFromMessage(message);
240 } 245 }
241 246
242 message = 'SN=' + sn + '; ' + message; 247 message = 'SN=' + sn + '; ' + message;
243 rc = '00'; 248 rc = '00';
244 249
245 } 250 }
246 else if (message.indexOf('Nomor Pelanggan Salah') >= 0) { 251 else if (message.indexOf('Nomor Pelanggan Salah') >= 0) {
247 252
248 rc = '14'; 253 rc = '14';
249 254
250 } else { 255 } else {
251 rc = supplierRcToST24Rc(result.ciwaru.rc[0]); 256 rc = supplierRcToST24Rc(result.ciwaru.rc[0]);
252 if (!rc) { 257 if (!rc) {
253 rc = '68'; 258 rc = '68';
254 } 259 }
255 } 260 }
256 261
257 if ((task.retry == maxRetry) || (rc != '68')) { 262 if ((task.retry == maxRetry) || (rc != '68')) {
258 callbackReport(task.requestId, rc, message); 263 callbackReport(task.requestId, rc, message);
259 } else { 264 } else {
260 logger.info('Not reporting to AAA for duplicate 68', {task: task}); 265 logger.info('Not reporting to AAA for duplicate 68', {task: task});
261 } 266 }
262 267
263 if (rc == '68') { 268 if (rc == '68') {
264 topupRequestRetry(task); 269 topupRequestRetry(task);
265 } 270 }
266 }); 271 });
267 } 272 }
268 273
269 function topupRequestRetry(task) { 274 function topupRequestRetry(task) {
270 task.retry--; 275 task.retry--;
271 276
272 if (task.retry > 0) { 277 if (task.retry > 0) {
273 logger.info('Retrying in ' + sleepBeforeRetry + 's'); 278 logger.info('Retrying in ' + sleepBeforeRetry + 's');
274 setTimeout(topupRequest, sleepBeforeRetry * 1000, task, task.retry); 279 setTimeout(topupRequest, sleepBeforeRetry * 1000, task, task.retry);
275 } 280 }
276 else { 281 else {
277 logger.warn('Maximum retry for pending status exceeded', {task: task}); 282 logger.warn('Maximum retry for pending status exceeded', {task: task});
278 } 283 }
279 } 284 }
280 285
281 function topupRequest(task, retry) { 286 function topupRequest(task, retry) {
282 287
283 if (retry === undefined) { 288 if (retry === undefined) {
284 289
285 task.ts = moment(task.timestamp, 'YYYYMMDDHHmmss').format('YYYY-MM-DD HH:mm:ss'); 290 task.ts = moment(task.timestamp, 'YYYYMMDDHHmmss').format('YYYY-MM-DD HH:mm:ss');
286 task.ts_date = moment(task.timestamp, 'YYYYMMDDHHmmss').format('YYYY-MM-DD'); 291 task.ts_date = moment(task.timestamp, 'YYYYMMDDHHmmss').format('YYYY-MM-DD');
287 292
288 insertTaskToMongoDb(task); 293 insertTaskToMongoDb(task);
289 294
290 retry = maxRetry; 295 retry = maxRetry;
291 } 296 }
292 297
293 if (!task.retry) { 298 if (!task.retry) {
294 task.retry = retry; 299 task.retry = retry;
295 } 300 }
296 301
297 var remoteProduct = task.remoteProduct.split(','); 302 var remoteProduct = task.remoteProduct.split(',');
298 303
299 var params = { 304 var params = {
300 trxtype: '01', 305 trxtype: '01',
301 prdcode: remoteProduct[0], 306 prdcode: remoteProduct[0],
302 value: remoteProduct[1], 307 value: remoteProduct[1],
303 msisdn: task.destination, 308 msisdn: task.destination,
304 trxid: task.requestId, 309 trxid: task.requestId,
305 uid: config.h2h_out.userid, 310 uid: config.h2h_out.userid,
306 password: config.h2h_out.password, 311 password: config.h2h_out.password,
307 }; 312 };
308 313
309 var postBody = createXmlPayload(params); 314 var postBody = createXmlPayload(params);
310 315
311 var partnerUrl = url.parse(config.h2h_out.partner); 316 var partnerUrl = url.parse(config.h2h_out.partner);
312 var postRequest = { 317 var postRequest = {
313 host: partnerUrl.hostname, 318 host: partnerUrl.hostname,
314 path: partnerUrl.path, 319 path: partnerUrl.path,
315 port: partnerUrl.port, 320 port: partnerUrl.port,
316 method: "POST", 321 method: "POST",
317 headers: { 322 headers: {
318 'Content-Type': 'text/xml', 323 'Content-Type': 'text/xml',
319 'Content-Length': Buffer.byteLength(postBody) 324 'Content-Length': Buffer.byteLength(postBody)
320 } 325 }
321 }; 326 };
322 327
323 logger.info('POST to partner', {postRequest: postRequest}); 328 logger.info('POST to partner', {postRequest: postRequest});
324 var req = http.request(postRequest, function( res ) { 329 var req = http.request(postRequest, function( res ) {
325 330
326 logger.verbose('Status code: ' + res.statusCode ); 331 logger.verbose('Status code: ' + res.statusCode );
327 var buffer = ""; 332 var buffer = "";
328 333
329 res.on( "data", function( data ) { 334 res.on( "data", function( data ) {
330 buffer = buffer + data; 335 buffer = buffer + data;
331 }); 336 });
332 337
333 res.on( "end", function( data ) { 338 res.on( "end", function( data ) {
334 topupResponseHandler(buffer, task); 339 topupResponseHandler(buffer, task);
335 }); 340 });
336 341
337 }); 342 });
338 343
339 req.on('error', function(e) { 344 req.on('error', function(e) {
340 logger.warn('problem with request: ' + e.message); 345 logger.warn('problem with request: ' + e.message);
341 callbackReport(task['requestId'], '68', e.message); 346 callbackReport(task['requestId'], '68', e.message);
342 347
343 topupRequestRetry(task); 348 topupRequestRetry(task);
344 }); 349 });
345 350
346 req.write(postBody); 351 req.write(postBody);
347 req.end(); 352 req.end();
348 } 353 }
349 354
350 exports.start = start; 355 exports.start = start;
351 exports.topupRequest = topupRequest; 356 exports.topupRequest = topupRequest;
352 exports.calculateSignature = calculateSignature; 357 exports.calculateSignature = calculateSignature;
353 exports.createXmlPayload = createXmlPayload; 358 exports.createXmlPayload = createXmlPayload;
354 exports.getSNFromMessage = getSNFromMessage; 359 exports.getSNFromMessage = getSNFromMessage;
355 360