Commit 200f359d8a599b988f54db6f332dfc843ad8c973

Authored by Adhidarma Hadiwinoto
1 parent 1a0a4c0bee
Exists in master

more data on mongodb

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