Commit 0f68673d63330ae03a4ae0ca41a1301dab1cc954

Authored by Adhidarma Hadiwinoto
1 parent d4d0ccb0a5
Exists in master

0012 hash data tidak sesuai - 40

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