Commit 774e1bf20c952aa0b77d790e53ad1230d447d53b

Authored by Adhidarma Hadiwinoto
1 parent 96e4677f6e
Exists in master

push supplier name to mongodb

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