node-paytmpg 5.3.0 → 5.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,514 +1,515 @@
1
- var crypto = require('crypto');
2
- const { resolve } = require('path');
3
- var reqpost = require('request');
4
-
5
- class OpenMoney {
6
- config
7
- constructor(npconfig) {
8
- npconfig.accesskey = npconfig.KEY
9
- npconfig.secretkey = npconfig.SECRET
10
- npconfig.url = npconfig.open_money_url
11
- npconfig.script_url = (npconfig.url && npconfig.url.indexOf("sandbox") == -1) ? "https://payments.open.money/layer" : "https://sandbox-payments.open.money/layer"
12
- this.config = npconfig;
13
-
14
- }
15
-
16
- generatePaymentToken(params) {
17
-
18
- let config = this.config;
19
- return new Promise((resolve, reject) => {
20
- var payment_token_data;
21
- let open_txn = {
22
- "amount": params['TXN_AMOUNT'],
23
- "currency": params['CURRENCY'] || "INR",
24
- "name": params['NAME'],
25
- "email_id": params['EMAIL'],
26
- "contact_number": ("" + params['MOBILE_NO']).replace("+91", ""),
27
- "mtx": params['ORDER_ID']
28
- }
29
- create_payment_token(open_txn,
30
- config.accesskey,
31
- config.secretkey,
32
- config.url, function (layer_payment_token_data) {
33
- /*Object.keys(layer_payment_token_data).forEach(function(key) {
34
- console.log(key + layer_payment_token_data[key]);
35
- });*/
36
-
37
- if (typeof layer_payment_token_data['error'] != 'undefined')
38
- return reject(JSON.stringify('E55 Payment error. ' + layer_payment_token_data['error']));
39
-
40
- if (typeof layer_payment_token_data["id"] == 'undefined' || !layer_payment_token_data["id"])
41
- return reject(JSON.stringify('Payment error. ' + 'Layer token ID cannot be empty.'));
42
-
43
- if (typeof layer_payment_token_data["id"] != 'undefined') {
44
-
45
- get_payment_token(layer_payment_token_data["id"], config.accesskey, config.secretkey, config.url, function (payment_token_data) {
46
-
47
- if (payment_token_data.error) {
48
- return reject({
49
- error: payment_token_data.error
50
- })
51
- }
52
- payment_token_data = JSON.parse(payment_token_data);
53
-
54
- if (typeof payment_token_data['error'] != 'undefined')
55
- return reject({ error: (JSON.stringify('E56 Payment error. ' + payment_token_data['error'])) })
56
- if (typeof payment_token_data['status'] != 'undefined' && payment_token_data['status'] == "paid")
57
- return reject({ error: (JSON.stringify("Layer: this order has already been paid.")) })
58
- if (parseFloat(payment_token_data['amount']) != parseFloat(params['TXN_AMOUNT']))
59
- return reject({ error: (JSON.stringify("Layer: an amount mismatch occurred.")) })
60
-
61
- var hash = create_hash({
62
- 'layer_pay_token_id': payment_token_data['id'],
63
- 'layer_order_amount': payment_token_data['amount'],
64
- 'tranid': params['ORDER_ID'],
65
- }, config.accesskey, config.secretkey);
66
- params['CHECKSUM'] = hash;
67
-
68
- var html = `<form action='${params['CALLBACK_URL']}' method='post' style='display: none' name='layer_payment_int_form'>`;
69
- html += "<input type='hidden' name='layer_pay_token_id' value='" + payment_token_data['id'] + "'>";
70
- html += "<input type='hidden' name='tranid' value='" + params['ORDER_ID'] + "'>";
71
- html += "<input type='hidden' name='layer_order_amount' value='" + payment_token_data['amount'] + "'>";
72
- html += "<input type='hidden' id='layer_payment_id' name='layer_payment_id' value=''>";
73
- html += "<input type='hidden' id='fallback_url' name='fallback_url' value=''>";
74
- html += "<input type='hidden' name='hash' value='" + hash + "'></form>";
75
- html += "<script>";
76
- html += "var layer_params = {payment_token_id:'" + payment_token_data['id'] + "',accesskey:'" + config.accesskey + "'};";
77
- html += "</script>";
78
- html += `<script src="layer_checkout.js"></script>`;
79
-
80
- return resolve({
81
- html: html,
82
- params: params,
83
- data: config,
84
- tokenid: payment_token_data['id'],
85
- amount: payment_token_data['amount'],
86
- hash: hash
87
- })
88
- });
89
- }
90
- });
91
- })
92
- }
93
-
94
- verifyResult(req) {
95
- let config = this.config;
96
- return new Promise((resolve, reje) => {
97
-
98
- var txnid = "";
99
- var amount = "";
100
- var status = "";
101
- var msg = "";
102
- var tokenid = "";
103
- var paymentid = "";
104
- var payment_data = {};
105
-
106
- if (!req.body.layer_payment_id) {
107
- return resolve({
108
- STATUS: 'TXN_FAILURE',
109
- ORDERID: txnid,
110
- TXNID: paymentid,
111
- reason: 'invalid response'
112
- })
113
- }
114
- else {
115
- txnid = req.body.tranid;
116
- amount = req.body.layer_order_amount;
117
- tokenid = req.body.layer_pay_token_id;
118
- paymentid = req.body.layer_payment_id;
119
- }
120
- var data = {
121
- 'layer_pay_token_id': tokenid,
122
- 'layer_order_amount': amount,
123
- 'tranid': txnid,
124
- };
125
-
126
- if (verify_hash(data, req.body.hash, config.accesskey, config.secretkey, config.url)) {
127
- get_payment_details(paymentid, config.accesskey, config.secretkey, config.url, function (response) {
128
- if (response === "{}") {
129
-
130
- return resolve({
131
- STATUS: 'TXN_FAILURE',
132
- ORDERID: txnid,
133
- TXNID: paymentid,
134
- message: 'Invalid Response',
135
- data: payment_data
136
- })
137
-
138
- }
139
- else {
140
- payment_data = JSON.parse(response);
141
- if (!payment_data['payment_token'] || payment_data['payment_token']['id'] != tokenid) {
142
- return resolve({
143
- STATUS: 'TXN_FAILURE',
144
- ORDERID: txnid,
145
- TXNID: paymentid,
146
- message: 'received layer_pay_token_id and collected layer_pay_token_id doesnt match',
147
- data: payment_data
148
- })
149
- }
150
- else {
151
- let status = ""
152
- if (payment_data.status == "captured" ||
153
- payment_data.status == "late_authorized") {
154
- status = 'TXN_SUCCESS'
155
- }
156
- else if (payment_data.status == "pending") {
157
- status = 'TXN_PENDING'
158
- }
159
- else {
160
- status = 'TXN_FAILURE'
161
- }
162
-
163
- return resolve({
164
- STATUS: status,
165
- ORDERID: txnid,
166
- TXNID: paymentid,
167
- data: (payment_data)
168
- })
169
- }
170
- }
171
- });
172
-
173
- }
174
- else {
175
- return resolve({
176
- STATUS: 'TXN_FAILURE',
177
- ORDERID: txnid,
178
- TXNID: paymentid,
179
- message: 'Invalid Response'
180
- })
181
- }
182
- })
183
- }
184
-
185
- processWebhook(req, res, updateTransaction) {
186
- let config = this.config;
187
- let events = [
188
- "payment_captured", "payment_pending",
189
- "payment_failed",
190
- "payment_cancelled"]
191
- if (req.body.event && events.indexOf(req.body.event) > -1) {
192
- if (req.body.payment_token) {
193
-
194
- let payment_token = req.body.payment_token;
195
- let orderId = payment_token.mtx
196
- let paymentid = req.body.id
197
- let tokenid = payment_token.id
198
- let payment_data = {}
199
- let amount = req.body.amount;
200
-
201
- setTimeout(() => {
202
-
203
- req.body.layer_pay_token_id = tokenid;
204
- // var data = {
205
- // 'layer_pay_token_id': tokenid,
206
- // 'layer_order_amount': amount,
207
- // 'tranid': orderId,
208
- // };
209
-
210
- // if (verify_hash(data, req.headers['x-webhook-signature'], config.accesskey, config.secretkey, config.url)) {
211
- // console.log('TODO verify signature')
212
- // }
213
- get_payment_details(paymentid, config.accesskey, config.secretkey, config.url, function (response) {
214
- if (response === "{}") {
215
- req.body.STATUS = 'TXN_FAILURE';
216
- req.body.ORDERID = orderId;
217
- req.body.TXNID = paymentid;
218
- }
219
- else {
220
- payment_data = JSON.parse(response);
221
- if (!payment_data['payment_token'] || payment_data['payment_token']['id'] != tokenid) {
222
- req.body.STATUS = 'TXN_FAILURE';
223
- req.body.ORDERID = orderId;
224
- req.body.TXNID = paymentid;
225
- }
226
- else {
227
- let status = "INITIATED"
228
- if (payment_data.status == "captured" ||
229
- payment_data.status == "late_authorized") {
230
- status = 'TXN_SUCCESS'
231
- }
232
- else if (payment_data.status == "pending") {
233
- status = 'TXN_PENDING'
234
- }
235
- // else {
236
- // status = 'TXN_FAILURE'
237
- // }
238
-
239
- if (status != 'TXN_SUCCESS') {
240
- if (req.body.status == "paid" || req.body.status == 'captured') {
241
- status = 'TXN_SUCCESS'
242
- }
243
- // else if (req.body.status == 'failed') {
244
- // status = 'TXN_FAILURE'
245
- // }
246
- else if (req.body.status == 'pending') {
247
- status = 'TXN_PENDING'
248
- }
249
- }
250
- console.log(`Open Money ${req.body.event} webhook for order=${payment_token.mtx} payid=${paymentid} status=${req.body.status} || ${status}`)
251
-
252
- req.body.STATUS = status;
253
- req.body.ORDERID = orderId;
254
- req.body.TXNID = paymentid;
255
- }
256
-
257
- }
258
- updateTransaction(req, res)
259
-
260
- });
261
- }, 3000)
262
- }
263
- else {
264
- res.status(401)
265
- res.send({ message: "Missing payment_token" })
266
- }
267
- }
268
- else {
269
- res.status(201)
270
- res.send({ message: "Webhook not supported" })
271
- }
272
- }
273
-
274
- getPaymentStatus(paymentTokenId, cb) {
275
- return new Promise((resolve, reject) => {
276
- get_payment_token_details(paymentTokenId, this.config.accesskey, this.config.secretkey, this.config.url, (data) => {
277
- resolve(data)
278
- if (cb) {
279
- cb(data)
280
- }
281
- })
282
- })
283
- }
284
-
285
- renderProcessingPage(params, pmttoken, res, loadingSVG) {
286
- res.writeHead(200, { 'Content-Type': 'text/html' });
287
- res.write(`<html><head><title>Merchant Checkout Page</title>
288
- <script src="${this.config.script_url}"></script>
289
- </head><body><center><h1>Processing ! Please do not refresh this page...</h1><br>${pmttoken.html}<br><br>${loadingSVG}</center><script>triggerLayer();</script></body></html>`);
290
- res.end();
291
- }
292
-
293
- renderError(params, error, res) {
294
-
295
- console.log('ERROR:::', error, '\n');
296
- res.status(500)
297
- var form_fields = "";
298
- let errorResp = {
299
- TXNID: "na",
300
- STATUS: "TXN_FAILURE",
301
- CANCELLED: "cancelled",
302
- ORDERID: params["ORDER_ID"]
303
- }
304
- for (var x in errorResp) {
305
- form_fields += "<input type='hidden' name='" + x + "' value='" + errorResp[x] + "' >";
306
- }
307
- form_fields += "<input type='hidden' name='CHECKSUMHASH' value='" + params["CHECKSUM"] + "' >";
308
-
309
- res.writeHead(200, { 'Content-Type': 'text/html' });
310
- res.write(`<html>
311
-
312
- <head>
313
- <title>Merchant Checkout Error</title>
314
- </head>
315
-
316
- <body>
317
- <center>
318
- <h1>Something went wrong. Please wait you will be redirected automatically...</h1>
319
- </center>
320
- <form method="post" action="${params['CALLBACK_URL']}" name="f1">${form_fields}</form>
321
- <script type="text/javascript">document.f1.submit();</script>
322
- </body>
323
-
324
- </html>`);
325
- res.end();
326
-
327
- }
328
-
329
-
330
- }
331
-
332
-
333
-
334
- //Layer functions
335
- function create_payment_token(data, accesskey, secretkey, baseurl, callback) {
336
- try {
337
- var pay_token_request_data = {
338
- 'amount': (data['amount']) ? data['amount'] : null,
339
- 'currency': (data['currency']) ? data['currency'] : null,
340
- 'name': (data['name']) ? data['name'] : null,
341
- 'email_id': (data['email_id']) ? data['email_id'] : null,
342
- 'contact_number': (data['contact_number']) ? data['contact_number'] : null,
343
- 'mtx': (data['mtx']) ? data['mtx'] : null,
344
- 'udf': (data['udf']) ? data['udf'] : null,
345
- };
346
- http_post(pay_token_request_data, "payment_token", accesskey, secretkey, baseurl, function (response) {
347
- return callback(response);
348
- });
349
-
350
- } catch (e) {
351
- return callback({
352
- 'error': e
353
- });
354
- }
355
- }
356
-
357
- function get_payment_token(payment_token_id, accesskey, secretkey, url, callback) {
358
- if (!payment_token_id) {
359
- throw new Error("payment_token_id cannot be empty");
360
- }
361
-
362
- try {
363
- http_get("payment_token/" + payment_token_id, accesskey, secretkey, url, function (response) {
364
- return callback(response);
365
- });
366
- } catch (e) {
367
- return callback({
368
- 'error': e
369
- });
370
- }
371
- }
372
-
373
- function get_payment_token_details(payment_tokenid, accesskey, secretkey, baseurl, callback) {
374
-
375
- if (!payment_tokenid) {
376
- throw new Error("payment_id cannot be empty");
377
- }
378
- try {
379
- http_get("payment_token/" + payment_tokenid + '/payment', accesskey, secretkey, baseurl, function (response) {
380
- return callback(response);
381
- });
382
- } catch (e) {
383
- callback({
384
- 'error': e
385
- })
386
- }
387
- }
388
-
389
- function get_payment_details(payment_id, accesskey, secretkey, baseurl, callback) {
390
-
391
- if (!payment_id) {
392
- throw new Error("payment_id cannot be empty");
393
- }
394
- try {
395
- http_get("payment/" + payment_id, accesskey, secretkey, baseurl, function (response) {
396
- return callback(response);
397
- });
398
- } catch (e) {
399
- callback({
400
- 'error': e
401
- })
402
- }
403
- }
404
-
405
- function http_post(data, route, accesskey, secretkey, baseurl, callback) {
406
- Object.keys(data).forEach(function (key) {
407
- if (data[key] === null)
408
- delete data[key];
409
- });
410
-
411
- var url = baseurl + "/" + route;
412
-
413
- var options = {
414
- method: 'POST',
415
- uri: url,
416
- json: true,
417
- form: {
418
- amount: data['amount'],
419
- currency: data['currency'],
420
- name: data['name'],
421
- email_id: data['email_id'],
422
- contact_number: data['contact_number'],
423
- mtx: data['mtx']
424
- },
425
- headers: {
426
- 'Content-Type': 'application/json',
427
- 'Authorization': 'Bearer ' + accesskey + ':' + secretkey
428
- }
429
- };
430
-
431
- reqpost(options)
432
- .on('response', function (resp) {
433
- //console.log('STATUS:'+resp.statusCode);
434
- resp.setEncoding('utf8');
435
- resp.on('data', function (chunk) {
436
- var data = JSON.parse(chunk);
437
- var rdata = "";
438
- if ("error" in data) {
439
- Object.keys(data).forEach(function (key) {
440
- if (key == "error_data") {
441
- var obj = data[key];
442
- Object.keys(obj).forEach(function (k) {
443
- rdata += obj[k] + ' ';
444
- });
445
- }
446
- });
447
- return callback({ "error": rdata });
448
- }
449
- else
450
- return callback(data);
451
-
452
- });
453
- })
454
- .on('error', function (err) {
455
- return callback(err);
456
- });
457
- }
458
-
459
- function http_get(route, accesskey, secretkey, baseurl, callback) {
460
-
461
- var url = baseurl + "/" + route;
462
-
463
- var options = {
464
- method: 'GET',
465
- uri: url,
466
- headers: {
467
- 'Content-Type': 'application/json',
468
- 'Authorization': 'Bearer ' + accesskey + ':' + secretkey
469
- }
470
- };
471
-
472
- reqpost(options)
473
- .on('response', function (resp) {
474
- resp.setEncoding('utf8');
475
- resp.on('data', function (chunk) {
476
- return callback(chunk);
477
- });
478
- })
479
- .on('error', function (err) {
480
- return callback(err);
481
- });
482
- }
483
-
484
- function create_hash(data, accesskey, secretkey) {
485
- data = ksort(data);
486
- hash_string = accesskey;
487
- Object.keys(data).forEach(function (key) {
488
- hash_string += '|' + data[key];
489
- });
490
- var cryp = crypto.createHash('sha256', secretkey);
491
- cryp.update(hash_string);
492
- return cryp.digest('hex');
493
- }
494
-
495
- function verify_hash(data, rec_hash, accesskey, secretkey) {
496
- var gen_hash = create_hash(data, accesskey, secretkey);
497
- if (gen_hash === rec_hash) {
498
- return true;
499
- }
500
- return false;
501
- }
502
-
503
- function ksort(obj) {
504
- var keys = Object.keys(obj).sort(), sortedObj = {};
505
-
506
- for (var i in keys) {
507
- sortedObj[keys[i]] = obj[keys[i]];
508
- }
509
-
510
- return sortedObj;
511
- }
512
-
513
-
514
- module.exports = OpenMoney;
1
+ const axios = require('axios');
2
+ var crypto = require('crypto');
3
+ const { resolve } = require('path');
4
+ var reqpost = require('request');
5
+
6
+ class OpenMoney {
7
+ config
8
+ constructor(npconfig) {
9
+ npconfig.accesskey = npconfig.KEY
10
+ npconfig.secretkey = npconfig.SECRET
11
+ npconfig.url = npconfig.open_money_url
12
+ npconfig.script_url = (npconfig.url && npconfig.url.indexOf("sandbox") == -1) ? "https://payments.open.money/layer" : "https://sandbox-payments.open.money/layer"
13
+ this.config = npconfig;
14
+
15
+ }
16
+
17
+ generatePaymentToken(params) {
18
+
19
+ let config = this.config;
20
+ return new Promise((resolve, reject) => {
21
+ var payment_token_data;
22
+ let open_txn = {
23
+ "amount": params['TXN_AMOUNT'],
24
+ "currency": params['CURRENCY'] || "INR",
25
+ "name": params['NAME'],
26
+ "email_id": params['EMAIL'],
27
+ "contact_number": ("" + params['MOBILE_NO']).replace("+91", ""),
28
+ "mtx": params['ORDER_ID']
29
+ }
30
+ create_payment_token(open_txn,
31
+ config.accesskey,
32
+ config.secretkey,
33
+ config.url, function (layer_payment_token_data) {
34
+ /*Object.keys(layer_payment_token_data).forEach(function(key) {
35
+ console.log(key + layer_payment_token_data[key]);
36
+ });*/
37
+
38
+ if (typeof layer_payment_token_data['error'] != 'undefined')
39
+ return reject(JSON.stringify('E55 Payment error. ' + layer_payment_token_data['error']));
40
+
41
+ if (typeof layer_payment_token_data["id"] == 'undefined' || !layer_payment_token_data["id"])
42
+ return reject(JSON.stringify('Payment error. ' + 'Layer token ID cannot be empty.'));
43
+
44
+ if (typeof layer_payment_token_data["id"] != 'undefined') {
45
+
46
+ get_payment_token(layer_payment_token_data["id"], config.accesskey, config.secretkey, config.url, function (payment_token_data) {
47
+
48
+ if (payment_token_data.error) {
49
+ return reject({
50
+ error: payment_token_data.error
51
+ })
52
+ }
53
+ payment_token_data = JSON.parse(payment_token_data);
54
+
55
+ if (typeof payment_token_data['error'] != 'undefined')
56
+ return reject({ error: (JSON.stringify('E56 Payment error. ' + payment_token_data['error'])) })
57
+ if (typeof payment_token_data['status'] != 'undefined' && payment_token_data['status'] == "paid")
58
+ return reject({ error: (JSON.stringify("Layer: this order has already been paid.")) })
59
+ if (parseFloat(payment_token_data['amount']) != parseFloat(params['TXN_AMOUNT']))
60
+ return reject({ error: (JSON.stringify("Layer: an amount mismatch occurred.")) })
61
+
62
+ var hash = create_hash({
63
+ 'layer_pay_token_id': payment_token_data['id'],
64
+ 'layer_order_amount': payment_token_data['amount'],
65
+ 'tranid': params['ORDER_ID'],
66
+ }, config.accesskey, config.secretkey);
67
+ params['CHECKSUM'] = hash;
68
+
69
+ var html = `<form action='${params['CALLBACK_URL']}' method='post' style='display: none' name='layer_payment_int_form'>`;
70
+ html += "<input type='hidden' name='layer_pay_token_id' value='" + payment_token_data['id'] + "'>";
71
+ html += "<input type='hidden' name='tranid' value='" + params['ORDER_ID'] + "'>";
72
+ html += "<input type='hidden' name='layer_order_amount' value='" + payment_token_data['amount'] + "'>";
73
+ html += "<input type='hidden' id='layer_payment_id' name='layer_payment_id' value=''>";
74
+ html += "<input type='hidden' id='fallback_url' name='fallback_url' value=''>";
75
+ html += "<input type='hidden' name='hash' value='" + hash + "'></form>";
76
+ html += "<script>";
77
+ html += "var layer_params = {payment_token_id:'" + payment_token_data['id'] + "',accesskey:'" + config.accesskey + "'};";
78
+ html += "</script>";
79
+ html += `<script src="layer_checkout.js"></script>`;
80
+
81
+ return resolve({
82
+ html: html,
83
+ params: params,
84
+ data: config,
85
+ tokenid: payment_token_data['id'],
86
+ amount: payment_token_data['amount'],
87
+ hash: hash
88
+ })
89
+ });
90
+ }
91
+ });
92
+ })
93
+ }
94
+
95
+ verifyResult(req) {
96
+ let config = this.config;
97
+ return new Promise((resolve, reje) => {
98
+
99
+ var txnid = "";
100
+ var amount = "";
101
+ var status = "";
102
+ var msg = "";
103
+ var tokenid = "";
104
+ var paymentid = "";
105
+ var payment_data = {};
106
+
107
+ if (!req.body.layer_payment_id) {
108
+ return resolve({
109
+ STATUS: 'TXN_FAILURE',
110
+ ORDERID: txnid,
111
+ TXNID: paymentid,
112
+ reason: 'invalid response'
113
+ })
114
+ }
115
+ else {
116
+ txnid = req.body.tranid;
117
+ amount = req.body.layer_order_amount;
118
+ tokenid = req.body.layer_pay_token_id;
119
+ paymentid = req.body.layer_payment_id;
120
+ }
121
+ var data = {
122
+ 'layer_pay_token_id': tokenid,
123
+ 'layer_order_amount': amount,
124
+ 'tranid': txnid,
125
+ };
126
+
127
+ if (verify_hash(data, req.body.hash, config.accesskey, config.secretkey, config.url)) {
128
+ get_payment_details(paymentid, config.accesskey, config.secretkey, config.url, function (response) {
129
+ if (response === "{}") {
130
+
131
+ return resolve({
132
+ STATUS: 'TXN_FAILURE',
133
+ ORDERID: txnid,
134
+ TXNID: paymentid,
135
+ message: 'Invalid Response',
136
+ data: payment_data
137
+ })
138
+
139
+ }
140
+ else {
141
+ payment_data = JSON.parse(response);
142
+ if (!payment_data['payment_token'] || payment_data['payment_token']['id'] != tokenid) {
143
+ return resolve({
144
+ STATUS: 'TXN_FAILURE',
145
+ ORDERID: txnid,
146
+ TXNID: paymentid,
147
+ message: 'received layer_pay_token_id and collected layer_pay_token_id doesnt match',
148
+ data: payment_data
149
+ })
150
+ }
151
+ else {
152
+ let status = ""
153
+ if (payment_data.status == "captured" ||
154
+ payment_data.status == "late_authorized") {
155
+ status = 'TXN_SUCCESS'
156
+ }
157
+ else if (payment_data.status == "pending") {
158
+ status = 'TXN_PENDING'
159
+ }
160
+ else {
161
+ status = 'TXN_FAILURE'
162
+ }
163
+
164
+ return resolve({
165
+ STATUS: status,
166
+ ORDERID: txnid,
167
+ TXNID: paymentid,
168
+ data: (payment_data)
169
+ })
170
+ }
171
+ }
172
+ });
173
+
174
+ }
175
+ else {
176
+ return resolve({
177
+ STATUS: 'TXN_FAILURE',
178
+ ORDERID: txnid,
179
+ TXNID: paymentid,
180
+ message: 'Invalid Response'
181
+ })
182
+ }
183
+ })
184
+ }
185
+
186
+ processWebhook(req, res, updateTransaction) {
187
+ let config = this.config;
188
+ let events = [
189
+ "payment_captured", "payment_pending",
190
+ "payment_failed",
191
+ "payment_cancelled"]
192
+ if (req.body.event && events.indexOf(req.body.event) > -1) {
193
+ if (req.body.payment_token) {
194
+
195
+ let payment_token = req.body.payment_token;
196
+ let orderId = payment_token.mtx
197
+ let paymentid = req.body.id
198
+ let tokenid = payment_token.id
199
+ let payment_data = {}
200
+ let amount = req.body.amount;
201
+
202
+ setTimeout(() => {
203
+
204
+ req.body.layer_pay_token_id = tokenid;
205
+ // var data = {
206
+ // 'layer_pay_token_id': tokenid,
207
+ // 'layer_order_amount': amount,
208
+ // 'tranid': orderId,
209
+ // };
210
+
211
+ // if (verify_hash(data, req.headers['x-webhook-signature'], config.accesskey, config.secretkey, config.url)) {
212
+ // console.log('TODO verify signature')
213
+ // }
214
+ get_payment_details(paymentid, config.accesskey, config.secretkey, config.url, function (response) {
215
+ if (response === "{}") {
216
+ req.body.STATUS = 'TXN_FAILURE';
217
+ req.body.ORDERID = orderId;
218
+ req.body.TXNID = paymentid;
219
+ }
220
+ else {
221
+ payment_data = JSON.parse(response);
222
+ if (!payment_data['payment_token'] || payment_data['payment_token']['id'] != tokenid) {
223
+ req.body.STATUS = 'TXN_FAILURE';
224
+ req.body.ORDERID = orderId;
225
+ req.body.TXNID = paymentid;
226
+ }
227
+ else {
228
+ let status = "INITIATED"
229
+ if (payment_data.status == "captured" ||
230
+ payment_data.status == "late_authorized") {
231
+ status = 'TXN_SUCCESS'
232
+ }
233
+ else if (payment_data.status == "pending") {
234
+ status = 'TXN_PENDING'
235
+ }
236
+ // else {
237
+ // status = 'TXN_FAILURE'
238
+ // }
239
+
240
+ if (status != 'TXN_SUCCESS') {
241
+ if (req.body.status == "paid" || req.body.status == 'captured') {
242
+ status = 'TXN_SUCCESS'
243
+ }
244
+ // else if (req.body.status == 'failed') {
245
+ // status = 'TXN_FAILURE'
246
+ // }
247
+ else if (req.body.status == 'pending') {
248
+ status = 'TXN_PENDING'
249
+ }
250
+ }
251
+ console.log(`Open Money ${req.body.event} webhook for order=${payment_token.mtx} payid=${paymentid} status=${req.body.status} || ${status}`)
252
+
253
+ req.body.STATUS = status;
254
+ req.body.ORDERID = orderId;
255
+ req.body.TXNID = paymentid;
256
+ }
257
+
258
+ }
259
+ updateTransaction(req, res)
260
+
261
+ });
262
+ }, 3000)
263
+ }
264
+ else {
265
+ res.status(401)
266
+ res.send({ message: "Missing payment_token" })
267
+ }
268
+ }
269
+ else {
270
+ res.status(201)
271
+ res.send({ message: "Webhook not supported" })
272
+ }
273
+ }
274
+
275
+ getPaymentStatus(paymentTokenId, cb) {
276
+ return new Promise((resolve, reject) => {
277
+ get_payment_token_details(paymentTokenId, this.config.accesskey, this.config.secretkey, this.config.url, (data) => {
278
+ resolve(data)
279
+ if (cb) {
280
+ cb(data)
281
+ }
282
+ })
283
+ })
284
+ }
285
+
286
+ renderProcessingPage(params, pmttoken, res, loadingSVG) {
287
+ res.writeHead(200, { 'Content-Type': 'text/html' });
288
+ res.write(`<html><head><title>Merchant Checkout Page</title>
289
+ <script src="${this.config.script_url}"></script>
290
+ </head><body><center><h1>Processing ! Please do not refresh this page...</h1><br>${pmttoken.html}<br><br>${loadingSVG}</center><script>triggerLayer();</script></body></html>`);
291
+ res.end();
292
+ }
293
+
294
+ renderError(params, error, res) {
295
+
296
+ console.log('ERROR:::', error, '\n');
297
+ res.status(500)
298
+ var form_fields = "";
299
+ let errorResp = {
300
+ TXNID: "na",
301
+ STATUS: "TXN_FAILURE",
302
+ CANCELLED: "cancelled",
303
+ ORDERID: params["ORDER_ID"]
304
+ }
305
+ for (var x in errorResp) {
306
+ form_fields += "<input type='hidden' name='" + x + "' value='" + errorResp[x] + "' >";
307
+ }
308
+ form_fields += "<input type='hidden' name='CHECKSUMHASH' value='" + params["CHECKSUM"] + "' >";
309
+
310
+ res.writeHead(200, { 'Content-Type': 'text/html' });
311
+ res.write(`<html>
312
+
313
+ <head>
314
+ <title>Merchant Checkout Error</title>
315
+ </head>
316
+
317
+ <body>
318
+ <center>
319
+ <h1>Something went wrong. Please wait you will be redirected automatically...</h1>
320
+ </center>
321
+ <form method="post" action="${params['CALLBACK_URL']}" name="f1">${form_fields}</form>
322
+ <script type="text/javascript">document.f1.submit();</script>
323
+ </body>
324
+
325
+ </html>`);
326
+ res.end();
327
+
328
+ }
329
+
330
+
331
+ }
332
+
333
+
334
+
335
+ //Layer functions
336
+ function create_payment_token(data, accesskey, secretkey, baseurl, callback) {
337
+ try {
338
+ var pay_token_request_data = {
339
+ 'amount': (data['amount']) ? data['amount'] : null,
340
+ 'currency': (data['currency']) ? data['currency'] : null,
341
+ 'name': (data['name']) ? data['name'] : null,
342
+ 'email_id': (data['email_id']) ? data['email_id'] : null,
343
+ 'contact_number': (data['contact_number']) ? data['contact_number'] : null,
344
+ 'mtx': (data['mtx']) ? data['mtx'] : null,
345
+ 'udf': (data['udf']) ? data['udf'] : null,
346
+ };
347
+ http_post(pay_token_request_data, "payment_token", accesskey, secretkey, baseurl, function (response) {
348
+ return callback(response);
349
+ });
350
+
351
+ } catch (e) {
352
+ return callback({
353
+ 'error': e
354
+ });
355
+ }
356
+ }
357
+
358
+ function get_payment_token(payment_token_id, accesskey, secretkey, url, callback) {
359
+ if (!payment_token_id) {
360
+ throw new Error("payment_token_id cannot be empty");
361
+ }
362
+
363
+ try {
364
+ http_get("payment_token/" + payment_token_id, accesskey, secretkey, url, function (response) {
365
+ return callback(response);
366
+ });
367
+ } catch (e) {
368
+ return callback({
369
+ 'error': e
370
+ });
371
+ }
372
+ }
373
+
374
+ function get_payment_token_details(payment_tokenid, accesskey, secretkey, baseurl, callback) {
375
+
376
+ if (!payment_tokenid) {
377
+ throw new Error("payment_id cannot be empty");
378
+ }
379
+ try {
380
+ http_get("payment_token/" + payment_tokenid + '/payment', accesskey, secretkey, baseurl, function (response) {
381
+ return callback(response);
382
+ });
383
+ } catch (e) {
384
+ callback({
385
+ 'error': e
386
+ })
387
+ }
388
+ }
389
+
390
+ function get_payment_details(payment_id, accesskey, secretkey, baseurl, callback) {
391
+
392
+ if (!payment_id) {
393
+ throw new Error("payment_id cannot be empty");
394
+ }
395
+ try {
396
+ http_get("payment/" + payment_id, accesskey, secretkey, baseurl, function (response) {
397
+ return callback(response);
398
+ });
399
+ } catch (e) {
400
+ callback({
401
+ 'error': e
402
+ })
403
+ }
404
+ }
405
+
406
+ function http_post(data, route, accesskey, secretkey, baseurl, callback) {
407
+ Object.keys(data).forEach(function (key) {
408
+ if (data[key] === null)
409
+ delete data[key];
410
+ });
411
+
412
+ var url = baseurl + "/" + route;
413
+
414
+ var options = {
415
+ method: 'POST',
416
+ uri: url,
417
+ json: true,
418
+ form: {
419
+ amount: data['amount'],
420
+ currency: data['currency'],
421
+ name: data['name'],
422
+ email_id: data['email_id'],
423
+ contact_number: data['contact_number'],
424
+ mtx: data['mtx']
425
+ },
426
+ headers: {
427
+ 'Content-Type': 'application/json',
428
+ 'Authorization': 'Bearer ' + accesskey + ':' + secretkey
429
+ }
430
+ };
431
+
432
+ reqpost(options)
433
+ .on('response', function (resp) {
434
+ //console.log('STATUS:'+resp.statusCode);
435
+ resp.setEncoding('utf8');
436
+ resp.on('data', function (chunk) {
437
+ var data = JSON.parse(chunk);
438
+ var rdata = "";
439
+ if ("error" in data) {
440
+ Object.keys(data).forEach(function (key) {
441
+ if (key == "error_data") {
442
+ var obj = data[key];
443
+ Object.keys(obj).forEach(function (k) {
444
+ rdata += obj[k] + ' ';
445
+ });
446
+ }
447
+ });
448
+ return callback({ "error": rdata });
449
+ }
450
+ else
451
+ return callback(data);
452
+
453
+ });
454
+ })
455
+ .on('error', function (err) {
456
+ return callback(err);
457
+ });
458
+ }
459
+
460
+ function http_get(route, accesskey, secretkey, baseurl, callback) {
461
+
462
+ var url = baseurl + "/" + route;
463
+
464
+ var options = {
465
+ method: 'GET',
466
+ uri: url,
467
+ url: url,
468
+ headers: {
469
+ 'Content-Type': 'application/json',
470
+ 'Authorization': 'Bearer ' + accesskey + ':' + secretkey
471
+ }
472
+ };
473
+
474
+ // console.log('Axios Calling API: ' + url)
475
+ axios(options).then((d) => {
476
+ // console.log('Axios Response API: ' + url + " >>> " + JSON.stringify(d.data))
477
+
478
+ callback(JSON.stringify(d.data))
479
+ }).catch((e) => {
480
+ // console.log('Axios Response API Error. ' + url + " >>> " + e.message)
481
+ callback("{}")
482
+ });
483
+ }
484
+
485
+ function create_hash(data, accesskey, secretkey) {
486
+ data = ksort(data);
487
+ hash_string = accesskey;
488
+ Object.keys(data).forEach(function (key) {
489
+ hash_string += '|' + data[key];
490
+ });
491
+ var cryp = crypto.createHash('sha256', secretkey);
492
+ cryp.update(hash_string);
493
+ return cryp.digest('hex');
494
+ }
495
+
496
+ function verify_hash(data, rec_hash, accesskey, secretkey) {
497
+ var gen_hash = create_hash(data, accesskey, secretkey);
498
+ if (gen_hash === rec_hash) {
499
+ return true;
500
+ }
501
+ return false;
502
+ }
503
+
504
+ function ksort(obj) {
505
+ var keys = Object.keys(obj).sort(), sortedObj = {};
506
+
507
+ for (var i in keys) {
508
+ sortedObj[keys[i]] = obj[keys[i]];
509
+ }
510
+
511
+ return sortedObj;
512
+ }
513
+
514
+
515
+ module.exports = OpenMoney;