Commit 0e90ae10a3936f39513c7211ff6735b64f66f48c

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