Commit b09a296804dbbcc021dee75578cb9101bdc72508
1 parent
10577ce2af
Exists in
master
insertTaskToMongoDb
Showing 1 changed file with 0 additions and 1 deletions Inline Diff
partner-hpay.js
1 | process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; | 1 | process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; |
2 | 2 | ||
3 | var request = require('request'); | 3 | var request = require('request'); |
4 | var xml2js = require('xml2js'); | 4 | var xml2js = require('xml2js'); |
5 | 5 | ||
6 | var resendDelay = require('sate24/resend-delay.js'); | 6 | var resendDelay = require('sate24/resend-delay.js'); |
7 | var taskHistory = require('./task-history.js'); | 7 | var taskHistory = require('./task-history.js'); |
8 | var antiSameDayDupe = require('./anti-same-day-dupe.js'); | 8 | var antiSameDayDupe = require('./anti-same-day-dupe.js'); |
9 | 9 | ||
10 | var config; | 10 | var config; |
11 | var aaa; | 11 | var aaa; |
12 | var _callbackReport; | 12 | var _callbackReport; |
13 | var logger; | 13 | var logger; |
14 | 14 | ||
15 | var xmlBuilder = new xml2js.Builder({rootName: 'xml', headless: true}); | 15 | var xmlBuilder = new xml2js.Builder({rootName: 'xml', headless: true}); |
16 | 16 | ||
17 | function start(options) { | 17 | function start(options) { |
18 | if (!options) { | 18 | if (!options) { |
19 | console.log('Undefined options, terminating....'); | 19 | console.log('Undefined options, terminating....'); |
20 | process.exit(1); | 20 | process.exit(1); |
21 | } | 21 | } |
22 | 22 | ||
23 | if (options.config) { | 23 | if (options.config) { |
24 | config = options.config; | 24 | config = options.config; |
25 | } else { | 25 | } else { |
26 | console.log('Undefined options.config, terminating....') | 26 | console.log('Undefined options.config, terminating....') |
27 | process.exit(1); | 27 | process.exit(1); |
28 | } | 28 | } |
29 | 29 | ||
30 | if (options.aaa) { | 30 | if (options.aaa) { |
31 | aaa = options.aaa; | 31 | aaa = options.aaa; |
32 | _callbackReport = options.aaa.callbackReportWithPushToMongoDb; | 32 | _callbackReport = options.aaa.callbackReportWithPushToMongoDb; |
33 | } else { | 33 | } else { |
34 | console.log('Undefined options.aaa, terminating....') | 34 | console.log('Undefined options.aaa, terminating....') |
35 | process.exit(1); | 35 | process.exit(1); |
36 | } | 36 | } |
37 | 37 | ||
38 | if (options && options.logger) { | 38 | if (options && options.logger) { |
39 | logger = options.logger; | 39 | logger = options.logger; |
40 | } else { | 40 | } else { |
41 | console.log('Undefined options.logger, terminating....') | 41 | console.log('Undefined options.logger, terminating....') |
42 | process.exit(1); | 42 | process.exit(1); |
43 | } | 43 | } |
44 | 44 | ||
45 | resendDelay.init({ | 45 | resendDelay.init({ |
46 | config: config, | 46 | config: config, |
47 | topupRequest: _topupStatus, | 47 | topupRequest: _topupStatus, |
48 | logger: logger | 48 | logger: logger |
49 | }); | 49 | }); |
50 | 50 | ||
51 | taskHistory.init(options); | 51 | taskHistory.init(options); |
52 | antiSameDayDupe.init(options); | 52 | antiSameDayDupe.init(options); |
53 | } | 53 | } |
54 | 54 | ||
55 | function callbackReport(requestId, responseCode, msg, responseToLog) { | 55 | function callbackReport(requestId, responseCode, msg, responseToLog) { |
56 | if (responseCode != '68') { | 56 | if (responseCode != '68') { |
57 | resendDelay.cancel(requestId) | 57 | resendDelay.cancel(requestId) |
58 | } else { | 58 | } else { |
59 | taskHistory.get(requestId, function(err, task) { | 59 | taskHistory.get(requestId, function(err, task) { |
60 | if (task) { | 60 | if (task) { |
61 | resendDelay.register(task); | 61 | resendDelay.register(task); |
62 | } | 62 | } |
63 | }); | 63 | }); |
64 | } | 64 | } |
65 | 65 | ||
66 | aaa.callbackReportWithPushToMongoDb(requestId, responseCode, msg, null, responseToLog); | 66 | aaa.callbackReportWithPushToMongoDb(requestId, responseCode, msg, null, responseToLog); |
67 | } | 67 | } |
68 | 68 | ||
69 | function parseResponse(task, response) { | 69 | function parseResponse(task, response) { |
70 | var xmlParser = xml2js.parseString; | 70 | var xmlParser = xml2js.parseString; |
71 | 71 | ||
72 | xmlParser(response, function(err, result) { | 72 | xmlParser(response, function(err, result) { |
73 | if (err) { | 73 | if (err) { |
74 | var msg = 'Error parsing response. ' + err; | 74 | var msg = 'Error parsing response. ' + err; |
75 | logger.warn(msg, {task: task, response: response, err: err}); | 75 | logger.warn(msg, {task: task, response: response, err: err}); |
76 | callbackReport(task.requestId, '68', msg); | 76 | callbackReport(task.requestId, '68', msg); |
77 | return; | 77 | return; |
78 | } | 78 | } |
79 | 79 | ||
80 | logger.verbose('Response parsed', {result: result, task: task}); | 80 | logger.verbose('Response parsed', {result: result, task: task}); |
81 | 81 | ||
82 | var st24rc = '68'; | 82 | var st24rc = '68'; |
83 | 83 | ||
84 | var voucherSerialNumber; | 84 | var voucherSerialNumber; |
85 | var trxId = getTrxId(result); | 85 | var trxId = getTrxId(result); |
86 | var responseCode = getResponseCode(result); | 86 | var responseCode = getResponseCode(result); |
87 | var responseMessage = getResponseMessage(result); | 87 | var responseMessage = getResponseMessage(result); |
88 | var nilaiPulsa = getNilaiPulsa(result); | 88 | var nilaiPulsa = getNilaiPulsa(result); |
89 | var noHp = getNoHp(result); | 89 | var noHp = getNoHp(result); |
90 | 90 | ||
91 | if (responseCode == '00') { | 91 | if (responseCode == '00') { |
92 | st24rc = '00'; | 92 | st24rc = '00'; |
93 | voucherSerialNumber = getVoucherSerialNumber(result); | 93 | voucherSerialNumber = getVoucherSerialNumber(result); |
94 | } | 94 | } |
95 | else if ((responseCode == '99') && (responseMessage == 'Member Not Found')) { | 95 | else if ((responseCode == '99') && (responseMessage == 'Member Not Found')) { |
96 | st24rc = '40'; | 96 | st24rc = '40'; |
97 | } | 97 | } |
98 | else if (responseCode == '99') { | 98 | else if (responseCode == '99') { |
99 | st24rc = '68'; | 99 | st24rc = '68'; |
100 | } | 100 | } |
101 | else { | 101 | else { |
102 | st24rc = '40'; | 102 | st24rc = '40'; |
103 | } | 103 | } |
104 | 104 | ||
105 | var msg = ''; | 105 | var msg = ''; |
106 | msg += ' responseCode: ' + responseCode; | 106 | msg += ' responseCode: ' + responseCode; |
107 | msg += ' responseMessage: ' + responseMessage; | 107 | msg += ' responseMessage: ' + responseMessage; |
108 | msg += ' nilaiPulsa: ' + nilaiPulsa; | 108 | msg += ' nilaiPulsa: ' + nilaiPulsa; |
109 | msg += ' noHp: ' + noHp; | 109 | msg += ' noHp: ' + noHp; |
110 | msg += ' trxId: ' + trxId; | 110 | msg += ' trxId: ' + trxId; |
111 | 111 | ||
112 | if (voucherSerialNumber) { | 112 | if (voucherSerialNumber) { |
113 | msg = 'SN=' + voucherSerialNumber + ';' + msg + ' voucherSerialNumber: ' + voucherSerialNumber; | 113 | msg = 'SN=' + voucherSerialNumber + ';' + msg + ' voucherSerialNumber: ' + voucherSerialNumber; |
114 | } | 114 | } |
115 | 115 | ||
116 | var responseToLog = { | 116 | var responseToLog = { |
117 | raw: response, | 117 | raw: response, |
118 | parsed: { | 118 | parsed: { |
119 | MESSAGE: msg | 119 | MESSAGE: msg |
120 | } | 120 | } |
121 | } | 121 | } |
122 | 122 | ||
123 | callbackReport(task.requestId, st24rc, msg, responseToLog); | 123 | callbackReport(task.requestId, st24rc, msg, responseToLog); |
124 | }); | 124 | }); |
125 | } | 125 | } |
126 | 126 | ||
127 | function getNilaiPulsa(data) { | 127 | function getNilaiPulsa(data) { |
128 | var result; | 128 | var result; |
129 | try { | 129 | try { |
130 | result = data.hpay.content.nilaiPulsa[0]; | 130 | result = data.hpay.content.nilaiPulsa[0]; |
131 | } | 131 | } |
132 | catch(e) { | 132 | catch(e) { |
133 | //logger.warn('Exception on getNilaiPulsa', {data: data}); | 133 | //logger.warn('Exception on getNilaiPulsa', {data: data}); |
134 | return; | 134 | return; |
135 | } | 135 | } |
136 | 136 | ||
137 | return result; | 137 | return result; |
138 | } | 138 | } |
139 | 139 | ||
140 | function getNoHp(data) { | 140 | function getNoHp(data) { |
141 | var result; | 141 | var result; |
142 | try { | 142 | try { |
143 | result = data.hpay.content.noHp[0]; | 143 | result = data.hpay.content.noHp[0]; |
144 | } | 144 | } |
145 | catch(e) { | 145 | catch(e) { |
146 | //logger.warn('Exception on getNoHp', {data: data}); | 146 | //logger.warn('Exception on getNoHp', {data: data}); |
147 | return; | 147 | return; |
148 | } | 148 | } |
149 | 149 | ||
150 | return result; | 150 | return result; |
151 | } | 151 | } |
152 | 152 | ||
153 | function getVoucherSerialNumber(data) { | 153 | function getVoucherSerialNumber(data) { |
154 | var result; | 154 | var result; |
155 | try { | 155 | try { |
156 | result = data.hpay.content.voucherSerialNumber[0]; | 156 | result = data.hpay.content.voucherSerialNumber[0]; |
157 | } | 157 | } |
158 | catch(e) { | 158 | catch(e) { |
159 | //logger.warn('Exception on getVoucherSerialNumber', {data: data}); | 159 | //logger.warn('Exception on getVoucherSerialNumber', {data: data}); |
160 | return; | 160 | return; |
161 | } | 161 | } |
162 | 162 | ||
163 | return result; | 163 | return result; |
164 | } | 164 | } |
165 | 165 | ||
166 | function getTrxId(data) { | 166 | function getTrxId(data) { |
167 | var result; | 167 | var result; |
168 | try { | 168 | try { |
169 | result = data.hpay.trxId[0]; | 169 | result = data.hpay.trxId[0]; |
170 | } | 170 | } |
171 | catch(e) { | 171 | catch(e) { |
172 | //logger.warn('Exception on getTrxId', {data: data}); | 172 | //logger.warn('Exception on getTrxId', {data: data}); |
173 | return; | 173 | return; |
174 | } | 174 | } |
175 | 175 | ||
176 | return result; | 176 | return result; |
177 | } | 177 | } |
178 | 178 | ||
179 | function getResponseCode(data) { | 179 | function getResponseCode(data) { |
180 | var result; | 180 | var result; |
181 | try { | 181 | try { |
182 | result = data.hpay.responseCode[0]; | 182 | result = data.hpay.responseCode[0]; |
183 | } | 183 | } |
184 | catch(e) { | 184 | catch(e) { |
185 | logger.warn('Exception on getResponseCode', {data: data}); | 185 | logger.warn('Exception on getResponseCode', {data: data}); |
186 | return; | 186 | return; |
187 | } | 187 | } |
188 | 188 | ||
189 | return result; | 189 | return result; |
190 | } | 190 | } |
191 | 191 | ||
192 | function getResponseMessage(data) { | 192 | function getResponseMessage(data) { |
193 | var result; | 193 | var result; |
194 | try { | 194 | try { |
195 | result = data.hpay.responseMessage[0]; | 195 | result = data.hpay.responseMessage[0]; |
196 | } | 196 | } |
197 | catch(e) { | 197 | catch(e) { |
198 | logger.warn('Exception on getResponseMessage', {data: data}); | 198 | logger.warn('Exception on getResponseMessage', {data: data}); |
199 | return; | 199 | return; |
200 | } | 200 | } |
201 | 201 | ||
202 | return result; | 202 | return result; |
203 | } | 203 | } |
204 | 204 | ||
205 | 205 | ||
206 | function requestToPartner(methodName, task) { | 206 | function requestToPartner(methodName, task) { |
207 | var payload = createPayload(methodName, task, config.h2h_out.userid, config.h2h_out.noid, config.h2h_out.password); | 207 | var payload = createPayload(methodName, task, config.h2h_out.userid, config.h2h_out.noid, config.h2h_out.password); |
208 | if (!payload) { | 208 | if (!payload) { |
209 | callbackReport(task.requestId, '40', 'ERROR: Undefined payload'); | 209 | callbackReport(task.requestId, '40', 'ERROR: Undefined payload'); |
210 | return; | 210 | return; |
211 | } | 211 | } |
212 | 212 | ||
213 | var requestOpts = { | 213 | var requestOpts = { |
214 | url: config.h2h_out.partner, | 214 | url: config.h2h_out.partner, |
215 | method: "POST", | 215 | method: "POST", |
216 | body: payload, | 216 | body: payload, |
217 | 217 | ||
218 | } | 218 | } |
219 | 219 | ||
220 | logger.verbose('Requesting to partner', {methodName: methodName, task: task, requestOpts: requestOpts}); | 220 | logger.verbose('Requesting to partner', {methodName: methodName, task: task, requestOpts: requestOpts}); |
221 | request(requestOpts, function (err, response, responseBody) { | 221 | request(requestOpts, function (err, response, responseBody) { |
222 | if (err) { | 222 | if (err) { |
223 | var rc = '68'; | 223 | var rc = '68'; |
224 | if (methodName === 'pay') { | 224 | if (methodName === 'pay') { |
225 | rc = '40'; | 225 | rc = '40'; |
226 | } | 226 | } |
227 | 227 | ||
228 | var msg = 'Error requesting pay method. ' + err; | 228 | var msg = 'Error requesting pay method. ' + err; |
229 | callbackReport(task.requestId, rc, msg); | 229 | callbackReport(task.requestId, rc, msg); |
230 | return; | 230 | return; |
231 | } | 231 | } |
232 | 232 | ||
233 | logger.info('Got direct response from partner', {task: task, responseBody: responseBody}); | 233 | logger.info('Got direct response from partner', {task: task, responseBody: responseBody}); |
234 | parseResponse(task, responseBody); | 234 | parseResponse(task, responseBody); |
235 | }); | 235 | }); |
236 | } | 236 | } |
237 | 237 | ||
238 | 238 | ||
239 | function topupRequest(task) { | 239 | function topupRequest(task) { |
240 | if (!aaa.isTodayTrx(task)) { | 240 | if (!aaa.isTodayTrx(task)) { |
241 | logger.warn('Maaf, transaksi beda hari tidak dapat dilakukan'); | 241 | logger.warn('Maaf, transaksi beda hari tidak dapat dilakukan'); |
242 | callbackReport(task.requestId, '68', 'Maaf, transaksi beda hari tidak dapat dilakukan'); | 242 | callbackReport(task.requestId, '68', 'Maaf, transaksi beda hari tidak dapat dilakukan'); |
243 | resendDelay.cancel(task); | 243 | resendDelay.cancel(task); |
244 | return; | 244 | return; |
245 | } | 245 | } |
246 | 246 | ||
247 | aaa.insertTaskToMongoDb(task); | 247 | aaa.insertTaskToMongoDb(task); |
248 | |||
249 | antiSameDayDupe.check(task, _topupRequest, onSameDayDupe, _topupStatus); | 248 | antiSameDayDupe.check(task, _topupRequest, onSameDayDupe, _topupStatus); |
250 | } | 249 | } |
251 | 250 | ||
252 | function _topupRequest(task) { | 251 | function _topupRequest(task) { |
253 | taskHistory.put(task, function() { | 252 | taskHistory.put(task, function() { |
254 | requestToPartner('pay', task);; | 253 | requestToPartner('pay', task);; |
255 | }); | 254 | }); |
256 | } | 255 | } |
257 | 256 | ||
258 | function _topupStatus(task) { | 257 | function _topupStatus(task) { |
259 | requestToPartner('checking', task); | 258 | requestToPartner('checking', task); |
260 | } | 259 | } |
261 | 260 | ||
262 | function onSameDayDupe(task) { | 261 | function onSameDayDupe(task) { |
263 | callbackReport(task.requestId, '55', 'Transaksi duplikat dalam satu hari yang sama'); | 262 | callbackReport(task.requestId, '55', 'Transaksi duplikat dalam satu hari yang sama'); |
264 | } | 263 | } |
265 | 264 | ||
266 | function extractProductDetail(remoteProduct) { | 265 | function extractProductDetail(remoteProduct) { |
267 | var product; | 266 | var product; |
268 | 267 | ||
269 | try { | 268 | try { |
270 | product = remoteProduct.split(','); | 269 | product = remoteProduct.split(','); |
271 | } | 270 | } |
272 | catch(e) { | 271 | catch(e) { |
273 | logger.warn('extractProductDetail: exception on split'); | 272 | logger.warn('extractProductDetail: exception on split'); |
274 | return null; | 273 | return null; |
275 | } | 274 | } |
276 | 275 | ||
277 | if (product.length !== 3) { | 276 | if (product.length !== 3) { |
278 | logger.warn('extractProductDetail: product.length <> 3'); | 277 | logger.warn('extractProductDetail: product.length <> 3'); |
279 | return null; | 278 | return null; |
280 | } | 279 | } |
281 | 280 | ||
282 | return {product: product[0], productType: product[1], nominal: product[2]}; | 281 | return {product: product[0], productType: product[1], nominal: product[2]}; |
283 | } | 282 | } |
284 | 283 | ||
285 | function createPayload(transactionType, task, user, noid, pin) { | 284 | function createPayload(transactionType, task, user, noid, pin) { |
286 | var product = extractProductDetail(task.remoteProduct); | 285 | var product = extractProductDetail(task.remoteProduct); |
287 | if (!product) { | 286 | if (!product) { |
288 | logger.warn('createPayload: undefined product'); | 287 | logger.warn('createPayload: undefined product'); |
289 | return; | 288 | return; |
290 | } | 289 | } |
291 | 290 | ||
292 | var payload = { | 291 | var payload = { |
293 | transactionType: transactionType, | 292 | transactionType: transactionType, |
294 | product: product.product, | 293 | product: product.product, |
295 | productType: product.productType, | 294 | productType: product.productType, |
296 | idpel: task.destination, | 295 | idpel: task.destination, |
297 | pin: pin, | 296 | pin: pin, |
298 | noid: noid, | 297 | noid: noid, |
299 | user: user, | 298 | user: user, |
300 | nominal: product.nominal | 299 | nominal: product.nominal |
301 | }; | 300 | }; |
302 | 301 | ||
303 | return xmlBuilder.buildObject(payload); | 302 | return xmlBuilder.buildObject(payload); |
304 | } | 303 | } |
305 | 304 | ||
306 | exports.start = start; | 305 | exports.start = start; |
307 | exports.topupRequest = topupRequest; | 306 | exports.topupRequest = topupRequest; |
308 | 307 |