Commit ac60b51f7ed2504380874cdeaa4ba635d64c28df

Authored by Adhidarma Hadiwinoto
1 parent d077430dfb
Exists in master

perbaikan mongo

Showing 1 changed file with 1 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 mongodb.collection(config.mongodb.collection).updateOne( 102 mongodb.collection(config.mongodb.collection).updateOne(
103 {requestId: task.requestId}, 103 {requestId: task.requestId},
104 { 104 {
105 lastResponse: {},
105 $push: {suppliers: config.globals.gateway_name} 106 $push: {suppliers: config.globals.gateway_name}
106 } 107 }
107 108
108 ) 109 )
109 }); 110 });
110 } 111 }
111 catch(err) { 112 catch(err) {
112 //logger.warn('Exception when inserting document to mongodb', {err: err, task: task}); 113 //logger.warn('Exception when inserting document to mongodb', {err: err, task: task});
113 } 114 }
114 } 115 }
115 116
116 function pushResponseToMongoDb(task, response) { 117 function pushResponseToMongoDb(task, response) {
117 if (!isMongoReady()) { return; } 118 if (!isMongoReady()) { return; }
118 119
119 try { 120 try {
120 mongodb.collection(config.mongodb.collection).updateOne( 121 mongodb.collection(config.mongodb.collection).updateOne(
121 {requestId: task.requestId}, 122 {requestId: task.requestId},
122 { 123 {
123 $push: {responses: response} 124 $push: {responses: response}
124 }, 125 },
125 function(err, result) { 126 function(err, result) {
126 if (err) { 127 if (err) {
127 logger.warn('Error when pushing response to mongodb', {err: err, task: task, response: response}); 128 logger.warn('Error when pushing response to mongodb', {err: err, task: task, response: response});
128 return; 129 return;
129 } 130 }
130 } 131 }
131 ); 132 );
132 133
133 if (response.parsed && response.parsed.ciwaru) { 134 if (response.parsed && response.parsed.ciwaru) {
134 mongodb.collection(config.mongodb.collection).updateOne( 135 mongodb.collection(config.mongodb.collection).updateOne(
135 {requestId: task.requestId}, 136 {requestId: task.requestId},
136 { 137 {
137 lastResponse: response.parsed.ciwaru 138 lastResponse: response.parsed.ciwaru
138 }, 139 },
139 function(err, result) { 140 function(err, result) {
140 if (err) { 141 if (err) {
141 logger.warn('Error when updating last response to mongodb', {err: err, task: task, response: response}); 142 logger.warn('Error when updating last response to mongodb', {err: err, task: task, response: response});
142 return; 143 return;
143 } 144 }
144 } 145 }
145 ); 146 );
146 } 147 }
147 148
148 } 149 }
149 catch(err) { 150 catch(err) {
150 logger.warn('Exception when pushing response to mongodb', {err: err, task: task, response: response}); 151 logger.warn('Exception when pushing response to mongodb', {err: err, task: task, response: response});
151 } 152 }
152 } 153 }
153 154
154 function isMongoReady() { 155 function isMongoReady() {
155 if (!config.mongodb) { return; } 156 if (!config.mongodb) { return; }
156 if (!config.mongodb.collection) { return; } 157 if (!config.mongodb.collection) { return; }
157 if (!mongodb) { return; } 158 if (!mongodb) { return; }
158 159
159 return true; 160 return true;
160 } 161 }
161 162
162 function getSNFromMessage(message) { 163 function getSNFromMessage(message) {
163 try { 164 try {
164 var sn_match = message.match(/SN: (\w+)/); 165 var sn_match = message.match(/SN: (\w+)/);
165 return sn_match[1].trim(); 166 return sn_match[1].trim();
166 } 167 }
167 catch(err) { 168 catch(err) {
168 if (logger) { 169 if (logger) {
169 logger.verbose('Exception on getting sn from message', {err: err}); 170 logger.verbose('Exception on getting sn from message', {err: err});
170 } 171 }
171 return ''; 172 return '';
172 } 173 }
173 } 174 }
174 175
175 function hasSuccessKeywords(message) { 176 function hasSuccessKeywords(message) {
176 var keywords = ['SUKSES', 'Finish']; 177 var keywords = ['SUKSES', 'Finish'];
177 178
178 var count = keywords.length; 179 var count = keywords.length;
179 for (var i=0; i < count; i++) { 180 for (var i=0; i < count; i++) {
180 if (message.indexOf(keywords[i]) >= 0) { 181 if (message.indexOf(keywords[i]) >= 0) {
181 return true; 182 return true;
182 } 183 }
183 } 184 }
184 return false; 185 return false;
185 } 186 }
186 187
187 function supplierRcToST24Rc(rc) { 188 function supplierRcToST24Rc(rc) {
188 var rcs = { 189 var rcs = {
189 '0001': '40', 190 '0001': '40',
190 '0012': '40', // hash data tidak sesuai 191 '0012': '40', // hash data tidak sesuai
191 '0019': '13', // produk tidak tersedia 192 '0019': '13', // produk tidak tersedia
192 } 193 }
193 194
194 if (rcs[rc]) { 195 if (rcs[rc]) {
195 return rcs[rc]; 196 return rcs[rc];
196 } else { 197 } else {
197 return; 198 return;
198 } 199 }
199 } 200 }
200 201
201 function getSNFromResponseObject(respObj) { 202 function getSNFromResponseObject(respObj) {
202 try { 203 try {
203 return respObj.ciwaru.sn[0].trim(); 204 return respObj.ciwaru.sn[0].trim();
204 } 205 }
205 catch(err) { 206 catch(err) {
206 return; 207 return;
207 } 208 }
208 } 209 }
209 210
210 function topupResponseHandler(body, task) { 211 function topupResponseHandler(body, task) {
211 212
212 //logger.info('Got reply from partner', {body: body}); 213 //logger.info('Got reply from partner', {body: body});
213 214
214 xml2js(body, function(err, result) { 215 xml2js(body, function(err, result) {
215 var ts = strftime('%Y-%m-%d %H:%M:%S', new Date()); 216 var ts = strftime('%Y-%m-%d %H:%M:%S', new Date());
216 217
217 if (err) { 218 if (err) {
218 logger.warn('Got invalid XML from partner', {err: err, body: body, task: task}); 219 logger.warn('Got invalid XML from partner', {err: err, body: body, task: task});
219 callbackReport(task.requestId, '68', body); 220 callbackReport(task.requestId, '68', body);
220 221
221 pushResponseToMongoDb(task, {ts: ts, raw: body}); 222 pushResponseToMongoDb(task, {ts: ts, raw: body});
222 return; 223 return;
223 } 224 }
224 logger.info('XML message from partner', {result: result}); 225 logger.info('XML message from partner', {result: result});
225 pushResponseToMongoDb(task, {ts: ts, raw: body, parsed: result}); 226 pushResponseToMongoDb(task, {ts: ts, raw: body, parsed: result});
226 227
227 var rc = '68'; 228 var rc = '68';
228 var message = result.ciwaru.msg[0]; 229 var message = result.ciwaru.msg[0];
229 230
230 if (message.toUpperCase().indexOf('PENDING') >= 0) { 231 if (message.toUpperCase().indexOf('PENDING') >= 0) {
231 rc = '68'; 232 rc = '68';
232 } 233 }
233 else if (hasSuccessKeywords(message)) { 234 else if (hasSuccessKeywords(message)) {
234 235
235 var sn = getSNFromResponseObject(result); 236 var sn = getSNFromResponseObject(result);
236 237
237 if (!sn) { 238 if (!sn) {
238 sn = getSNFromMessage(message); 239 sn = getSNFromMessage(message);
239 } 240 }
240 241
241 message = 'SN=' + sn + '; ' + message; 242 message = 'SN=' + sn + '; ' + message;
242 rc = '00'; 243 rc = '00';
243 244
244 } 245 }
245 else if (message.indexOf('Nomor Pelanggan Salah') >= 0) { 246 else if (message.indexOf('Nomor Pelanggan Salah') >= 0) {
246 247
247 rc = '14'; 248 rc = '14';
248 249
249 } else { 250 } else {
250 rc = supplierRcToST24Rc(result.ciwaru.rc[0]); 251 rc = supplierRcToST24Rc(result.ciwaru.rc[0]);
251 if (!rc) { 252 if (!rc) {
252 rc = '68'; 253 rc = '68';
253 } 254 }
254 } 255 }
255 256
256 if ((task.retry == maxRetry) || (rc != '68')) { 257 if ((task.retry == maxRetry) || (rc != '68')) {
257 callbackReport(task.requestId, rc, message); 258 callbackReport(task.requestId, rc, message);
258 } else { 259 } else {
259 logger.info('Not reporting to AAA for duplicate 68', {task: task}); 260 logger.info('Not reporting to AAA for duplicate 68', {task: task});
260 } 261 }
261 262
262 if (rc == '68') { 263 if (rc == '68') {
263 topupRequestRetry(task); 264 topupRequestRetry(task);
264 } 265 }
265 }); 266 });
266 } 267 }
267 268
268 function topupRequestRetry(task) { 269 function topupRequestRetry(task) {
269 task.retry--; 270 task.retry--;
270 271
271 if (task.retry > 0) { 272 if (task.retry > 0) {
272 logger.info('Retrying in ' + sleepBeforeRetry + 's'); 273 logger.info('Retrying in ' + sleepBeforeRetry + 's');
273 setTimeout(topupRequest, sleepBeforeRetry * 1000, task, task.retry); 274 setTimeout(topupRequest, sleepBeforeRetry * 1000, task, task.retry);
274 } 275 }
275 else { 276 else {
276 logger.warn('Maximum retry for pending status exceeded', {task: task}); 277 logger.warn('Maximum retry for pending status exceeded', {task: task});
277 } 278 }
278 } 279 }
279 280
280 function topupRequest(task, retry) { 281 function topupRequest(task, retry) {
281 282
282 if (retry === undefined) { 283 if (retry === undefined) {
283 284
284 task.ts = moment(task.timestamp, 'YYYYMMDDHHmmss').format('YYYY-MM-DD HH:mm:ss'); 285 task.ts = moment(task.timestamp, 'YYYYMMDDHHmmss').format('YYYY-MM-DD HH:mm:ss');
285 task.ts_date = moment(task.timestamp, 'YYYYMMDDHHmmss').format('YYYY-MM-DD'); 286 task.ts_date = moment(task.timestamp, 'YYYYMMDDHHmmss').format('YYYY-MM-DD');
286 287
287 insertTaskToMongoDb(task); 288 insertTaskToMongoDb(task);
288 289
289 retry = maxRetry; 290 retry = maxRetry;
290 } 291 }
291 292
292 if (!task.retry) { 293 if (!task.retry) {
293 task.retry = retry; 294 task.retry = retry;
294 } 295 }
295 296
296 var remoteProduct = task.remoteProduct.split(','); 297 var remoteProduct = task.remoteProduct.split(',');
297 298
298 var params = { 299 var params = {
299 trxtype: '01', 300 trxtype: '01',
300 prdcode: remoteProduct[0], 301 prdcode: remoteProduct[0],
301 value: remoteProduct[1], 302 value: remoteProduct[1],
302 msisdn: task.destination, 303 msisdn: task.destination,
303 trxid: task.requestId, 304 trxid: task.requestId,
304 uid: config.h2h_out.userid, 305 uid: config.h2h_out.userid,
305 password: config.h2h_out.password, 306 password: config.h2h_out.password,
306 }; 307 };
307 308
308 var postBody = createXmlPayload(params); 309 var postBody = createXmlPayload(params);
309 310
310 var partnerUrl = url.parse(config.h2h_out.partner); 311 var partnerUrl = url.parse(config.h2h_out.partner);
311 var postRequest = { 312 var postRequest = {
312 host: partnerUrl.hostname, 313 host: partnerUrl.hostname,
313 path: partnerUrl.path, 314 path: partnerUrl.path,
314 port: partnerUrl.port, 315 port: partnerUrl.port,
315 method: "POST", 316 method: "POST",
316 headers: { 317 headers: {
317 'Content-Type': 'text/xml', 318 'Content-Type': 'text/xml',
318 'Content-Length': Buffer.byteLength(postBody) 319 'Content-Length': Buffer.byteLength(postBody)
319 } 320 }
320 }; 321 };
321 322
322 logger.info('POST to partner', {postRequest: postRequest}); 323 logger.info('POST to partner', {postRequest: postRequest});
323 var req = http.request(postRequest, function( res ) { 324 var req = http.request(postRequest, function( res ) {
324 325
325 logger.verbose('Status code: ' + res.statusCode ); 326 logger.verbose('Status code: ' + res.statusCode );
326 var buffer = ""; 327 var buffer = "";
327 328
328 res.on( "data", function( data ) { 329 res.on( "data", function( data ) {
329 buffer = buffer + data; 330 buffer = buffer + data;
330 }); 331 });
331 332
332 res.on( "end", function( data ) { 333 res.on( "end", function( data ) {
333 topupResponseHandler(buffer, task); 334 topupResponseHandler(buffer, task);
334 }); 335 });
335 336
336 }); 337 });
337 338
338 req.on('error', function(e) { 339 req.on('error', function(e) {
339 logger.warn('problem with request: ' + e.message); 340 logger.warn('problem with request: ' + e.message);
340 callbackReport(task['requestId'], '68', e.message); 341 callbackReport(task['requestId'], '68', e.message);
341 342
342 topupRequestRetry(task); 343 topupRequestRetry(task);
343 }); 344 });
344 345
345 req.write(postBody); 346 req.write(postBody);
346 req.end(); 347 req.end();
347 } 348 }
348 349
349 exports.start = start; 350 exports.start = start;
350 exports.topupRequest = topupRequest; 351 exports.topupRequest = topupRequest;
351 exports.calculateSignature = calculateSignature; 352 exports.calculateSignature = calculateSignature;
352 exports.createXmlPayload = createXmlPayload; 353 exports.createXmlPayload = createXmlPayload;
353 exports.getSNFromMessage = getSNFromMessage; 354 exports.getSNFromMessage = getSNFromMessage;
354 355