Commit d83e1d69fd472796d72b14d8c91c8fcebc4409ed

Authored by Adhidarma Hadiwinoto
1 parent 95d2d01784
Exists in master

perbaikan mongo

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