Commit 2d5d6a476ce1b44cac80b9ceda9339ae63b60e9e

Authored by Adhidarma Hadiwinoto
1 parent 1a8b8868c5
Exists in master

put st24 rc to mongo

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