Commit 53eca1490240022535ce12d9f7962cc944b51265

Authored by Adhidarma Hadiwinoto
1 parent 6655fe4b7e
Exists in master

rehashRefnum

Showing 1 changed file with 16 additions and 1 deletions Inline Diff

partner-masterpulsa-voucher.js
1 var winston = require('winston'); 1 var winston = require('winston');
2 var request = require('request'); 2 var request = require('request');
3 var strftime = require('strftime'); 3 var strftime = require('strftime');
4 var crypto = require('crypto'); 4 var crypto = require('crypto');
5 var redis = require('redis'); 5 var redis = require('redis');
6 6
7 var config; 7 var config;
8 var callbackReport; 8 var callbackReport;
9 var aaa; 9 var aaa;
10 var logger; 10 var logger;
11 var options; 11 var options;
12 var redisClient; 12 var redisClient;
13 13
14 var adviceDelay = 30000; 14 var adviceDelay = 30000;
15 15
16 function createRedisClient() { 16 function createRedisClient() {
17 redisClient = redis.createClient(config.globals.redis_port, config.globals.redis_host); 17 redisClient = redis.createClient(config.globals.redis_port, config.globals.redis_host);
18 } 18 }
19 19
20 function start(_config, _callbackReport, options) { 20 function start(_config, _callbackReport, options) {
21 config = _config; 21 config = _config;
22 callbackReport = _callbackReport 22 callbackReport = _callbackReport
23 23
24 if (options && options.aaa) { 24 if (options && options.aaa) {
25 aaa = options.aaa; 25 aaa = options.aaa;
26 } 26 }
27 27
28 if (options && options.logger) { 28 if (options && options.logger) {
29 logger = options.logger; 29 logger = options.logger;
30 } else { 30 } else {
31 logger = new winston.Logger({ 31 logger = new winston.Logger({
32 transports: [ 32 transports: [
33 new (winston.transports.Console)() 33 new (winston.transports.Console)()
34 ] 34 ]
35 }); 35 });
36 } 36 }
37 37
38 createRedisClient(); 38 createRedisClient();
39 } 39 }
40 40
41 function getRedisKey(task) { 41 function getRedisKey(task) {
42 return config.globals.gateway_name + '.tid:' + task.requestId; 42 return config.globals.gateway_name + '.tid:' + task.requestId;
43 } 43 }
44 44
45 function topupRequest(task, retry) { 45 function topupRequest(task, retry) {
46 var key = 'DUPCHECK.gw:' + config.globals.gateway_name + '.prod:' + task.remoteProduct + '.dest:' + task.destination + '.date:' + strftime('%Y%m%d', new Date); 46 var key = 'DUPCHECK.gw:' + config.globals.gateway_name + '.prod:' + task.remoteProduct + '.dest:' + task.destination + '.date:' + strftime('%Y%m%d', new Date);
47 redisClient.get(key, function(err, data) { 47 redisClient.get(key, function(err, data) {
48 if (err) { 48 if (err) {
49 callbackReport(task.requestId, '40', 'Gagal cek anti transaksi duplikat (redis error)'); 49 callbackReport(task.requestId, '40', 'Gagal cek anti transaksi duplikat (redis error)');
50 return; 50 return;
51 } 51 }
52 52
53 if (!data) { 53 if (!data) {
54 logger.verbose('Belum ada trx dengan tujuan dan denom yang sama pada hari ini. Lanjutkan.'); 54 logger.verbose('Belum ada trx dengan tujuan dan denom yang sama pada hari ini. Lanjutkan.');
55 55
56 redisClient.set(key, JSON.stringify(task)); 56 redisClient.set(key, JSON.stringify(task));
57 redisClient.expire(key, 3600 * 24 * 2); 57 redisClient.expire(key, 3600 * 24 * 2);
58 58
59 voucherPay(task, retry); 59 voucherPay(task, retry);
60 60
61 } else { 61 } else {
62 62
63 try { 63 try {
64 var taskOnRedis = JSON.parse(data); 64 var taskOnRedis = JSON.parse(data);
65 if (task.requestId == taskOnRedis.requestId) { 65 if (task.requestId == taskOnRedis.requestId) {
66 logger.verbose('Sudah ada trx dengan tujuan dan denom yg sama, requestId jg sama. Lanjutkan dengan advice.') 66 logger.verbose('Sudah ada trx dengan tujuan dan denom yg sama, requestId jg sama. Lanjutkan dengan advice.')
67 advice(task, retry); 67 advice(task, retry);
68 } else { 68 } else {
69 logger.verbose('Sudah ada trx dengan tujuan dan denom yg sama, requestId tidak sama. Batalkan.') 69 logger.verbose('Sudah ada trx dengan tujuan dan denom yg sama, requestId tidak sama. Batalkan.')
70 callbackReport(task.requestId, '55', 'Transaksi duplikat') 70 callbackReport(task.requestId, '55', 'Transaksi duplikat')
71 } 71 }
72 } 72 }
73 catch(errJSONParse) { 73 catch(errJSONParse) {
74 callbackReport(task.requestId, '68', "error parsing json"); 74 callbackReport(task.requestId, '68', "error parsing json");
75 } 75 }
76 } 76 }
77 }); 77 });
78 } 78 }
79 79
80 function calculateSignature(cid, secret, dt) { 80 function calculateSignature(cid, secret, dt) {
81 return crypto.createHash('sha256').update(cid + dt + secret).digest().toString('hex'); 81 return crypto.createHash('sha256').update(cid + dt + secret).digest().toString('hex');
82 } 82 }
83 83
84 function parsePaymentResponse(message) { 84 function parsePaymentResponse(message) {
85 var data = message.split('#'); 85 var data = message.split('#');
86 var retval = {}; 86 var retval = {};
87 87
88 if (data[0] == 'ERROR') { 88 if (data[0] == 'ERROR') {
89 retval = { 89 retval = {
90 status: data[0], 90 status: data[0],
91 rc: data[1], 91 rc: data[1],
92 rcmessage: data[2], 92 rcmessage: data[2],
93 } 93 }
94 94
95 } else { 95 } else {
96 96
97 var i = 0; 97 var i = 0;
98 retval = { 98 retval = {
99 status: data[i++], 99 status: data[i++],
100 rc: data[i++], 100 rc: data[i++],
101 rcmessage: data[i++], 101 rcmessage: data[i++],
102 resptext: data[i++], 102 resptext: data[i++],
103 dt: data[i++], 103 dt: data[i++],
104 refnum: data[i++], 104 refnum: data[i++],
105 voucherid: data[i++], 105 voucherid: data[i++],
106 nominal: data[i++] 106 nominal: data[i++]
107 } 107 }
108 } 108 }
109 109
110 retval.raw = message; 110 retval.raw = message;
111 111
112 return retval; 112 return retval;
113 } 113 }
114 114
115 function rehashRefnum(refnum) {
116 var hashed = refnum;
117 try {
118 hashed = hashed.replace(/A/g, '1').replace(/B/g, '2').replace(/C/g, '3').replace(/D/g, '4').replace(/E/g, '5').replace('/F/g', '6');
119 }
120 catch(err) {
121 hashed = refnum;
122 }
123 return hashed;
124
125
126
127 }
128
115 function reportPaymentSuccess(task, response) { 129 function reportPaymentSuccess(task, response) {
116 var message = 'SN=' + response.refnum + '; ' + response.raw; 130 var sn = rehashRefnum(response.refnum);
131 var message = 'SN=' + sn + '; ' + response.raw;
117 132
118 logger.info('Report payment success to ST24', {task: task, response: response}); 133 logger.info('Report payment success to ST24', {task: task, response: response});
119 134
120 callbackReport(task.requestId, '00', message); 135 callbackReport(task.requestId, '00', message);
121 } 136 }
122 137
123 function reportPaymentError(task, response) { 138 function reportPaymentError(task, response) {
124 var errorCode = getErrorCode(response.rcmessage); 139 var errorCode = getErrorCode(response.rcmessage);
125 var st24rc = getST24ResponseCode(errorCode); 140 var st24rc = getST24ResponseCode(errorCode);
126 141
127 if (st24rc == '68') { 142 if (st24rc == '68') {
128 logger.info('Got pending response, requesting advice in ' + adviceDelay + 'ms', {task: task, response: response}); 143 logger.info('Got pending response, requesting advice in ' + adviceDelay + 'ms', {task: task, response: response});
129 setTimeout(advice, adviceDelay, task); 144 setTimeout(advice, adviceDelay, task);
130 } 145 }
131 146
132 logger.info('Report payment error/pending to ST24', {supplier_rc: errorCode, st24_rc: st24rc, task: task, response: response}); 147 logger.info('Report payment error/pending to ST24', {supplier_rc: errorCode, st24_rc: st24rc, task: task, response: response});
133 148
134 callbackReport( 149 callbackReport(
135 task.requestId, 150 task.requestId,
136 getST24ResponseCode(errorCode), 151 getST24ResponseCode(errorCode),
137 response.raw 152 response.raw
138 ); 153 );
139 } 154 }
140 155
141 function getST24ResponseCode(supplierResponseCode) { 156 function getST24ResponseCode(supplierResponseCode) {
142 var st24rc = '40'; 157 var st24rc = '40';
143 158
144 if (supplierResponseCode.length == 1) { 159 if (supplierResponseCode.length == 1) {
145 supplierResponseCode = '0' + supplierResponseCode; 160 supplierResponseCode = '0' + supplierResponseCode;
146 } 161 }
147 162
148 if (supplierResponseCode == '05') { 163 if (supplierResponseCode == '05') {
149 st24rc = '40'; 164 st24rc = '40';
150 } 165 }
151 else if (['00', '13', '14', '47', '68'].indexOf(supplierResponseCode) >= 0) { 166 else if (['00', '13', '14', '47', '68'].indexOf(supplierResponseCode) >= 0) {
152 st24rc = supplierResponseCode; 167 st24rc = supplierResponseCode;
153 } 168 }
154 else if (['15', '56'].indexOf(supplierResponseCode) >= 0) { 169 else if (['15', '56'].indexOf(supplierResponseCode) >= 0) {
155 // nomor tidak valid 170 // nomor tidak valid
156 st24rc = '14'; 171 st24rc = '14';
157 } 172 }
158 else if (['18', '63', '68'].indexOf(supplierResponseCode) >= 0) { 173 else if (['18', '63', '68'].indexOf(supplierResponseCode) >= 0) {
159 st24rc = '68'; 174 st24rc = '68';
160 } 175 }
161 else if (supplierResponseCode == '67') { 176 else if (supplierResponseCode == '67') {
162 st24rc = '91' 177 st24rc = '91'
163 } 178 }
164 else if (supplierResponseCode == '46') { 179 else if (supplierResponseCode == '46') {
165 st24rc = '40' 180 st24rc = '40'
166 181
167 if (aaa && config && config.globals && config.globals.pause_on_not_enough_balance 182 if (aaa && config && config.globals && config.globals.pause_on_not_enough_balance
168 && (config.globals.pause_on_not_enough_balance == '1')) { 183 && (config.globals.pause_on_not_enough_balance == '1')) {
169 184
170 logger.warn('Not enough balance detected. Going to pause the system.'); 185 logger.warn('Not enough balance detected. Going to pause the system.');
171 aaa.pause(); 186 aaa.pause();
172 } 187 }
173 } 188 }
174 189
175 return st24rc; 190 return st24rc;
176 } 191 }
177 192
178 function getErrorCode(rcmessage) { 193 function getErrorCode(rcmessage) {
179 try { 194 try {
180 var errorCode = rcmessage.match(/\[(\d+)\]/); 195 var errorCode = rcmessage.match(/\[(\d+)\]/);
181 return errorCode[1]; 196 return errorCode[1];
182 } 197 }
183 catch(err) { 198 catch(err) {
184 logger.warn('Empty RCMESSAGE, returning 68 as RC for safety'); 199 logger.warn('Empty RCMESSAGE, returning 68 as RC for safety');
185 return '68'; 200 return '68';
186 } 201 }
187 } 202 }
188 203
189 function generateDt(taskTimestamp) { 204 function generateDt(taskTimestamp) {
190 if (!taskTimestamp) { 205 if (!taskTimestamp) {
191 return strftime('%Y%m%d', new Date()); 206 return strftime('%Y%m%d', new Date());
192 } 207 }
193 208
194 return taskTimestamp.slice(0, 8); 209 return taskTimestamp.slice(0, 8);
195 } 210 }
196 211
197 function generateRequestOptions(userid, password, partnerUrl, task) { 212 function generateRequestOptions(userid, password, partnerUrl, task) {
198 var dt = generateDt(task.timestamp); 213 var dt = generateDt(task.timestamp);
199 var sign = calculateSignature(userid, password, dt); 214 var sign = calculateSignature(userid, password, dt);
200 215
201 var requestOptions = { 216 var requestOptions = {
202 method: 'GET', 217 method: 'GET',
203 url: partnerUrl, 218 url: partnerUrl,
204 qs: { 219 qs: {
205 modul: '', 220 modul: '',
206 command: '', 221 command: '',
207 tujuan: task['destination'], 222 tujuan: task['destination'],
208 voucherid: task['remoteProduct'], 223 voucherid: task['remoteProduct'],
209 cid: userid, 224 cid: userid,
210 dt: dt, 225 dt: dt,
211 hc: sign, 226 hc: sign,
212 trxid: task['requestId'], 227 trxid: task['requestId'],
213 } 228 }
214 } 229 }
215 230
216 return requestOptions; 231 return requestOptions;
217 } 232 }
218 233
219 function advice(task, retry) { 234 function advice(task, retry) {
220 235
221 if (retry === null || retry === undefined) { 236 if (retry === null || retry === undefined) {
222 retry = 10; 237 retry = 10;
223 } 238 }
224 239
225 var requestOptions = generateRequestOptions(config.h2h_out.userid, config.h2h_out.password, config.h2h_out.partner, task); 240 var requestOptions = generateRequestOptions(config.h2h_out.userid, config.h2h_out.password, config.h2h_out.partner, task);
226 241
227 requestOptions.qs.modul = 'ISI'; 242 requestOptions.qs.modul = 'ISI';
228 requestOptions.qs.command = 'ADV'; 243 requestOptions.qs.command = 'ADV';
229 244
230 logger.info('Requesting advice to supplier', {requestOptions: requestOptions}); 245 logger.info('Requesting advice to supplier', {requestOptions: requestOptions});
231 request(requestOptions, function(requestError, requestResponse, requestResponseBody) { 246 request(requestOptions, function(requestError, requestResponse, requestResponseBody) {
232 if (requestError || requestResponse.statusCode != 200) { 247 if (requestError || requestResponse.statusCode != 200) {
233 logger.warn('Advice error', {error: request_error, http_response: requestResponse.statusCode}); 248 logger.warn('Advice error', {error: request_error, http_response: requestResponse.statusCode});
234 249
235 if (retry > 0) { 250 if (retry > 0) {
236 logger.warn('Going to retry advice in ' + adviceDelay + 'ms', {task: task, retry: retry}); 251 logger.warn('Going to retry advice in ' + adviceDelay + 'ms', {task: task, retry: retry});
237 setTimeout(advice, adviceDelay, task, --retry); 252 setTimeout(advice, adviceDelay, task, --retry);
238 } 253 }
239 254
240 return; 255 return;
241 } 256 }
242 257
243 var paymentResponse = parsePaymentResponse(requestResponseBody); 258 var paymentResponse = parsePaymentResponse(requestResponseBody);
244 logger.info('Got advice payment response', {paymentResponse: paymentResponse}); 259 logger.info('Got advice payment response', {paymentResponse: paymentResponse});
245 260
246 if (paymentResponse.status == 'SUCCESS') { 261 if (paymentResponse.status == 'SUCCESS') {
247 reportPaymentSuccess(task, paymentResponse); 262 reportPaymentSuccess(task, paymentResponse);
248 } 263 }
249 else { 264 else {
250 reportPaymentError(task, paymentResponse); 265 reportPaymentError(task, paymentResponse);
251 } 266 }
252 }); 267 });
253 268
254 } 269 }
255 270
256 function voucherPay(task) { 271 function voucherPay(task) {
257 var requestOptions = generateRequestOptions(config.h2h_out.userid, config.h2h_out.password, config.h2h_out.partner, task); 272 var requestOptions = generateRequestOptions(config.h2h_out.userid, config.h2h_out.password, config.h2h_out.partner, task);
258 273
259 requestOptions.qs.modul = 'ISI'; 274 requestOptions.qs.modul = 'ISI';
260 requestOptions.qs.command = 'PAY'; 275 requestOptions.qs.command = 'PAY';
261 276
262 logger.info('Requesting auto payment to supplier', {requestOptions: requestOptions}); 277 logger.info('Requesting auto payment to supplier', {requestOptions: requestOptions});
263 request(requestOptions, function(requestError, requestResponse, requestResponseBody) { 278 request(requestOptions, function(requestError, requestResponse, requestResponseBody) {
264 if (requestError) { 279 if (requestError) {
265 logger.warn('Request error', {error: requestError}); 280 logger.warn('Request error', {error: requestError});
266 281
267 setTimeout(advice, adviceDelay, task); 282 setTimeout(advice, adviceDelay, task);
268 return; 283 return;
269 } 284 }
270 285
271 if (requestResponse.statusCode != 200) { 286 if (requestResponse.statusCode != 200) {
272 logger.warn('HTTP response status code is not 200', {http_response: requestResponse.statusCode}); 287 logger.warn('HTTP response status code is not 200', {http_response: requestResponse.statusCode});
273 288
274 setTimeout(advice, adviceDelay, task); 289 setTimeout(advice, adviceDelay, task);
275 return; 290 return;
276 } 291 }
277 292
278 logger.info('Supplier response: ' + requestResponseBody); 293 logger.info('Supplier response: ' + requestResponseBody);
279 294
280 var paymentResponse = parsePaymentResponse(requestResponseBody); 295 var paymentResponse = parsePaymentResponse(requestResponseBody);
281 logger.info('Got payment response', {paymentResponse: paymentResponse}); 296 logger.info('Got payment response', {paymentResponse: paymentResponse});
282 297
283 if (paymentResponse.status == 'SUCCESS') { 298 if (paymentResponse.status == 'SUCCESS') {
284 reportPaymentSuccess(task, paymentResponse); 299 reportPaymentSuccess(task, paymentResponse);
285 } 300 }
286 else { 301 else {
287 reportPaymentError(task, paymentResponse); 302 reportPaymentError(task, paymentResponse);
288 } 303 }
289 }); 304 });
290 } 305 }
291 306
292 exports.start = start; 307 exports.start = start;
293 exports.topupRequest = topupRequest; 308 exports.topupRequest = topupRequest;
294 exports.calculateSignature = calculateSignature; 309 exports.calculateSignature = calculateSignature;
295 exports.parsePaymentResponse = parsePaymentResponse; 310 exports.parsePaymentResponse = parsePaymentResponse;
296 exports.getErrorCode = getErrorCode; 311 exports.getErrorCode = getErrorCode;
297 exports.getST24ResponseCode = getST24ResponseCode; 312 exports.getST24ResponseCode = getST24ResponseCode;
298 exports.generateDt = generateDt; 313 exports.generateDt = generateDt;
299 314