Commit d4db1a32fd2a629b166914b0ceeec89ab94db85d

Authored by Adhidarma Hadiwinoto
1 parent 3ffb299d4e
Exists in master

voucherPay

Showing 1 changed file with 1 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 = 10000; 14 var adviceDelay = 10000;
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 putTaskToRedis(task) { 45 function putTaskToRedis(task) {
46 var redisKey = getRedisKey(task); 46 var redisKey = getRedisKey(task);
47 var taskInJSON = JSON.stringify(task); 47 var taskInJSON = JSON.stringify(task);
48 48
49 redisClient.set(redisKey, taskInJSON); 49 redisClient.set(redisKey, taskInJSON);
50 redisClient.expire(redisKey, 3600*24*7); 50 redisClient.expire(redisKey, 3600*24*7);
51 } 51 }
52 52
53 function topupRequest(task, retry) { 53 function topupRequest(task, retry) {
54 var redisKey = getRedisKey(task); 54 var redisKey = getRedisKey(task);
55 55
56 redisClient.get(redisKey, function(err, result) { 56 redisClient.get(redisKey, function(err, result) {
57 if (err || !result) { 57 if (err || !result) {
58 58
59 //logger.info('Redis error or not found', {redisKey: redisKey, error: err, result: result}); 59 //logger.info('Redis error or not found', {redisKey: redisKey, error: err, result: result});
60 putTaskToRedis(task); 60 putTaskToRedis(task);
61 payVoucher(task); 61 voucherPay(task);
62 62
63 } else { 63 } else {
64 advice(task); 64 advice(task);
65 } 65 }
66 }); 66 });
67 } 67 }
68 68
69 function calculateSignature(cid, secret, dt) { 69 function calculateSignature(cid, secret, dt) {
70 return crypto.createHash('sha256').update(cid + dt + secret).digest().toString('hex'); 70 return crypto.createHash('sha256').update(cid + dt + secret).digest().toString('hex');
71 } 71 }
72 72
73 function parsePaymentResponse(message) { 73 function parsePaymentResponse(message) {
74 var data = message.split('#'); 74 var data = message.split('#');
75 var retval = { 75 var retval = {
76 raw: message 76 raw: message
77 }; 77 };
78 78
79 if (data[0] == 'ERROR') { 79 if (data[0] == 'ERROR') {
80 retval = { 80 retval = {
81 status: data[0], 81 status: data[0],
82 rc: data[1], 82 rc: data[1],
83 rcmessage: data[2], 83 rcmessage: data[2],
84 } 84 }
85 85
86 } else { 86 } else {
87 87
88 var i = 0; 88 var i = 0;
89 retval = { 89 retval = {
90 status: data[i++], 90 status: data[i++],
91 rc: data[i++], 91 rc: data[i++],
92 rcmessage: data[i++], 92 rcmessage: data[i++],
93 resptext: data[i++], 93 resptext: data[i++],
94 dt: data[i++], 94 dt: data[i++],
95 refnum: data[i++], 95 refnum: data[i++],
96 voucherid: data[i++], 96 voucherid: data[i++],
97 nominal: data[i++] 97 nominal: data[i++]
98 } 98 }
99 } 99 }
100 100
101 return retval; 101 return retval;
102 } 102 }
103 103
104 function reportPaymentSuccess(task, response) { 104 function reportPaymentSuccess(task, response) {
105 var message = 'SN=' + response.refnum + '; ' + response.raw; 105 var message = 'SN=' + response.refnum + '; ' + response.raw;
106 106
107 logger.info('Report payment success to ST24', {task: task, response: response}); 107 logger.info('Report payment success to ST24', {task: task, response: response});
108 108
109 callbackReport(task.requestId, '00', message); 109 callbackReport(task.requestId, '00', message);
110 } 110 }
111 111
112 function reportPaymentError(task, response) { 112 function reportPaymentError(task, response) {
113 var errorCode = getErrorCode(response.rcmessage); 113 var errorCode = getErrorCode(response.rcmessage);
114 var st24rc = getST24ResponseCode(errorCode); 114 var st24rc = getST24ResponseCode(errorCode);
115 115
116 if (st24rc == '68') { 116 if (st24rc == '68') {
117 logger.info('Got pending response, requesting advice in ' + adviceDelay + 'ms', {task: task, response: response}); 117 logger.info('Got pending response, requesting advice in ' + adviceDelay + 'ms', {task: task, response: response});
118 setTimeout(advice, adviceDelay, task); 118 setTimeout(advice, adviceDelay, task);
119 } 119 }
120 120
121 logger.info('Report payment error/pending to ST24', {supplier_rc: errorCode, st24_rc: st24rc, task: task, response: response}); 121 logger.info('Report payment error/pending to ST24', {supplier_rc: errorCode, st24_rc: st24rc, task: task, response: response});
122 122
123 callbackReport( 123 callbackReport(
124 task.requestId, 124 task.requestId,
125 getST24ResponseCode(errorCode), 125 getST24ResponseCode(errorCode),
126 response.raw 126 response.raw
127 ); 127 );
128 } 128 }
129 129
130 function getST24ResponseCode(supplierResponseCode) { 130 function getST24ResponseCode(supplierResponseCode) {
131 var st24rc = '40'; 131 var st24rc = '40';
132 132
133 if (supplierResponseCode.length == 1) { 133 if (supplierResponseCode.length == 1) {
134 supplierResponseCode = '0' + supplierResponseCode; 134 supplierResponseCode = '0' + supplierResponseCode;
135 } 135 }
136 136
137 if (['00', '13', '14', '47', '68'].indexOf(supplierResponseCode) >= 0) { 137 if (['00', '13', '14', '47', '68'].indexOf(supplierResponseCode) >= 0) {
138 st24rc = supplierResponseCode; 138 st24rc = supplierResponseCode;
139 } 139 }
140 else if (supplierResponseCode == '15') { 140 else if (supplierResponseCode == '15') {
141 st24rc = '14'; 141 st24rc = '14';
142 } 142 }
143 else if (['05', '18', '63', '68'].indexOf(supplierResponseCode) >= 0) { 143 else if (['05', '18', '63', '68'].indexOf(supplierResponseCode) >= 0) {
144 st24rc = '68'; 144 st24rc = '68';
145 } 145 }
146 else if (supplierResponseCode == '67') { 146 else if (supplierResponseCode == '67') {
147 st24rc = '91' 147 st24rc = '91'
148 } 148 }
149 else if (supplierResponseCode == '46') { 149 else if (supplierResponseCode == '46') {
150 st24rc = '40' 150 st24rc = '40'
151 151
152 if (aaa && config && config.globals && config.globals.pause_on_not_enough_balance 152 if (aaa && config && config.globals && config.globals.pause_on_not_enough_balance
153 && (config.globals.pause_on_not_enough_balance == '1')) { 153 && (config.globals.pause_on_not_enough_balance == '1')) {
154 154
155 logger.warn('Not enough balance detected. Going to pause the system.'); 155 logger.warn('Not enough balance detected. Going to pause the system.');
156 aaa.pause(); 156 aaa.pause();
157 } 157 }
158 } 158 }
159 159
160 return st24rc; 160 return st24rc;
161 } 161 }
162 162
163 function getErrorCode(rcmessage) { 163 function getErrorCode(rcmessage) {
164 try { 164 try {
165 var errorCode = rcmessage.match(/\[(\d+)\]/); 165 var errorCode = rcmessage.match(/\[(\d+)\]/);
166 return errorCode[1]; 166 return errorCode[1];
167 } 167 }
168 catch(err) { 168 catch(err) {
169 logger.warn('Empty RCMESSAGE, returning 68 as RC for safety'); 169 logger.warn('Empty RCMESSAGE, returning 68 as RC for safety');
170 return '68'; 170 return '68';
171 } 171 }
172 } 172 }
173 173
174 function generateDt(taskTimestamp) { 174 function generateDt(taskTimestamp) {
175 if (!taskTimestamp) { 175 if (!taskTimestamp) {
176 return strftime('%Y%m%d', new Date()); 176 return strftime('%Y%m%d', new Date());
177 } 177 }
178 178
179 return taskTimestamp.slice(0, 8); 179 return taskTimestamp.slice(0, 8);
180 } 180 }
181 181
182 function generateRequestOptions(userid, password, partnerUrl, task) { 182 function generateRequestOptions(userid, password, partnerUrl, task) {
183 var dt = generateDt(task.timestamp); 183 var dt = generateDt(task.timestamp);
184 var sign = calculateSignature(userid, password, dt); 184 var sign = calculateSignature(userid, password, dt);
185 185
186 var requestOptions = { 186 var requestOptions = {
187 method: 'GET', 187 method: 'GET',
188 url: partnerUrl, 188 url: partnerUrl,
189 qs: { 189 qs: {
190 modul: '', 190 modul: '',
191 command: '', 191 command: '',
192 tujuan: task['destination'], 192 tujuan: task['destination'],
193 voucherid: task['remoteProduct'], 193 voucherid: task['remoteProduct'],
194 cid: userid, 194 cid: userid,
195 dt: dt, 195 dt: dt,
196 hc: sign, 196 hc: sign,
197 trxid: task['requestId'], 197 trxid: task['requestId'],
198 } 198 }
199 } 199 }
200 200
201 return requestOptions; 201 return requestOptions;
202 } 202 }
203 203
204 function advice(task, retry) { 204 function advice(task, retry) {
205 205
206 if (retry === null || retry === undefined) { 206 if (retry === null || retry === undefined) {
207 retry = 10; 207 retry = 10;
208 } 208 }
209 209
210 var requestOptions = generateRequestOptions(config.h2h_out.userid, config.h2h_out.password, config.h2h_out.partner, task); 210 var requestOptions = generateRequestOptions(config.h2h_out.userid, config.h2h_out.password, config.h2h_out.partner, task);
211 211
212 requestOptions.qs.modul = 'ISI'; 212 requestOptions.qs.modul = 'ISI';
213 requestOptions.qs.command = 'ADV'; 213 requestOptions.qs.command = 'ADV';
214 214
215 logger.info('Requesting advice to supplier', {requestOptions: requestOptions}); 215 logger.info('Requesting advice to supplier', {requestOptions: requestOptions});
216 request(requestOptions, function(requestError, requestResponse, requestResponseBody) { 216 request(requestOptions, function(requestError, requestResponse, requestResponseBody) {
217 if (requestError || requestResponse.statusCode != 200) { 217 if (requestError || requestResponse.statusCode != 200) {
218 logger.warn('Advice error', {error: request_error, http_response: requestResponse.statusCode}); 218 logger.warn('Advice error', {error: request_error, http_response: requestResponse.statusCode});
219 219
220 if (retry > 0) { 220 if (retry > 0) {
221 logger.warn('Going to retry advice in ' + adviceDelay + 'ms', {task: task, retry: retry}); 221 logger.warn('Going to retry advice in ' + adviceDelay + 'ms', {task: task, retry: retry});
222 setTimeout(advice, adviceDelay, task, --retry); 222 setTimeout(advice, adviceDelay, task, --retry);
223 } 223 }
224 224
225 return; 225 return;
226 } 226 }
227 227
228 var paymentResponse = parsePaymentResponse(requestResponseBody); 228 var paymentResponse = parsePaymentResponse(requestResponseBody);
229 logger.info('Got advice payment response', {paymentResponse: paymentResponse}); 229 logger.info('Got advice payment response', {paymentResponse: paymentResponse});
230 230
231 if (paymentResponse.status == 'SUCCESS') { 231 if (paymentResponse.status == 'SUCCESS') {
232 reportPaymentSuccess(task, paymentResponse); 232 reportPaymentSuccess(task, paymentResponse);
233 } 233 }
234 else { 234 else {
235 reportPaymentError(task, paymentResponse); 235 reportPaymentError(task, paymentResponse);
236 } 236 }
237 }); 237 });
238 238
239 } 239 }
240 240
241 function voucherPay(task) { 241 function voucherPay(task) {
242 var requestOptions = generateRequestOptions(config.h2h_out.userid, config.h2h_out.password, config.h2h_out.partner, task); 242 var requestOptions = generateRequestOptions(config.h2h_out.userid, config.h2h_out.password, config.h2h_out.partner, task);
243 243
244 requestOptions.qs.modul = 'ISI'; 244 requestOptions.qs.modul = 'ISI';
245 requestOptions.qs.command = 'PAY'; 245 requestOptions.qs.command = 'PAY';
246 246
247 logger.info('Requesting auto payment to supplier', {requestOptions: requestOptions}); 247 logger.info('Requesting auto payment to supplier', {requestOptions: requestOptions});
248 request(requestOptions, function(requestError, requestResponse, requestResponseBody) { 248 request(requestOptions, function(requestError, requestResponse, requestResponseBody) {
249 if (requestError) { 249 if (requestError) {
250 logger.warn('Request error', {error: requestError}); 250 logger.warn('Request error', {error: requestError});
251 251
252 setTimeout(advice, adviceDelay, task); 252 setTimeout(advice, adviceDelay, task);
253 return; 253 return;
254 } 254 }
255 255
256 if (requestResponse.statusCode != 200) { 256 if (requestResponse.statusCode != 200) {
257 logger.warn('HTTP response status code is not 200', {http_response: requestResponse.statusCode}); 257 logger.warn('HTTP response status code is not 200', {http_response: requestResponse.statusCode});
258 258
259 setTimeout(advice, adviceDelay, task); 259 setTimeout(advice, adviceDelay, task);
260 return; 260 return;
261 } 261 }
262 262
263 logger.info('Supplier response: ' + requestResponseBody); 263 logger.info('Supplier response: ' + requestResponseBody);
264 264
265 var paymentResponse = parsePaymentResponse(requestResponseBody); 265 var paymentResponse = parsePaymentResponse(requestResponseBody);
266 logger.info('Got payment response', {paymentResponse: paymentResponse}); 266 logger.info('Got payment response', {paymentResponse: paymentResponse});
267 267
268 if (paymentResponse.status == 'SUCCESS') { 268 if (paymentResponse.status == 'SUCCESS') {
269 reportPaymentSuccess(task, paymentResponse); 269 reportPaymentSuccess(task, paymentResponse);
270 } 270 }
271 else { 271 else {
272 reportPaymentError(task, paymentResponse); 272 reportPaymentError(task, paymentResponse);
273 } 273 }
274 }); 274 });
275 } 275 }
276 276
277 exports.start = start; 277 exports.start = start;
278 exports.topupRequest = topupRequest; 278 exports.topupRequest = topupRequest;
279 exports.calculateSignature = calculateSignature; 279 exports.calculateSignature = calculateSignature;
280 exports.parsePaymentResponse = parsePaymentResponse; 280 exports.parsePaymentResponse = parsePaymentResponse;
281 exports.getErrorCode = getErrorCode; 281 exports.getErrorCode = getErrorCode;
282 exports.getST24ResponseCode = getST24ResponseCode; 282 exports.getST24ResponseCode = getST24ResponseCode;
283 exports.generateDt = generateDt; 283 exports.generateDt = generateDt;
284 284