Commit b0fb9b5454e6158240da4f82b593c8db1b454fc1

Authored by Adhidarma Hadiwinoto
1 parent 2d5d6a476c
Exists in master

insertTaskToMongoDb rc 68

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