node-paytmpg 5.3.2 → 6.4.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.
- package/app/controllers/adapters/payu.js +251 -0
- package/app/controllers/np_user.controller.js +88 -79
- package/app/controllers/payment_controller.js +213 -84
- package/app/models/np_multidbplugin.js +111 -101
- package/app/views/init.hbs +85 -80
- package/app/views/layouts/index.hbs +46 -51
- package/app/views/result.hbs +43 -47
- package/example.js +33 -50
- package/index.js +75 -15
- package/lib/config/buildConfig.js +113 -0
- package/lib/config/defaults.js +37 -0
- package/lib/config/validator.js +103 -0
- package/lib/services/database.service.js +153 -0
- package/lib/utils/id-generator.js +30 -0
- package/lib/utils/sanitizer.js +25 -0
- package/package.json +44 -42
- package/public/css/style.css +373 -203
|
@@ -1,101 +1,111 @@
|
|
|
1
|
-
module.exports = function (modelName, db) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
async
|
|
24
|
-
|
|
25
|
-
if (
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
1
|
+
module.exports = function (modelName, db, sampleData) {
|
|
2
|
+
|
|
3
|
+
if (db && sampleData && db.create) {
|
|
4
|
+
db.create(modelName, sampleData)
|
|
5
|
+
.then(() => {
|
|
6
|
+
console.log('Model Created in db ', modelName);
|
|
7
|
+
})
|
|
8
|
+
.catch((e) => {
|
|
9
|
+
console.log('Error in creating model ', e);
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
class MultiDbMapper {
|
|
14
|
+
|
|
15
|
+
idFieldName
|
|
16
|
+
objectData
|
|
17
|
+
constructor(objectData) {
|
|
18
|
+
MultiDbMapper.sanitizeRequest(objectData)
|
|
19
|
+
this.objectData = objectData;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
static async sanitizeRequest(body) {
|
|
24
|
+
|
|
25
|
+
if (!body)
|
|
26
|
+
return;
|
|
27
|
+
if (body.amount)
|
|
28
|
+
body.amount = parseFloat(body.amount);
|
|
29
|
+
if (body.TXN_AMOUNT)
|
|
30
|
+
body.amount = parseFloat(body.TXN_AMOUNT);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async save() {
|
|
34
|
+
var response = await MultiDbMapper.db.insert(MultiDbMapper.modelname, this.objectData, this.objectData[MultiDbMapper.idFieldName]);
|
|
35
|
+
if (typeof response == Object && response.ops[0])
|
|
36
|
+
response = response.ops[0];
|
|
37
|
+
else
|
|
38
|
+
response = this.objectData
|
|
39
|
+
|
|
40
|
+
MultiDbMapper.sanitizeRequest(response)
|
|
41
|
+
|
|
42
|
+
return response;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
//callback(err,resp)
|
|
46
|
+
static async findOne(query, cb) {
|
|
47
|
+
|
|
48
|
+
var response;
|
|
49
|
+
try {
|
|
50
|
+
response = await MultiDbMapper.db.getOne(MultiDbMapper.modelname, query);
|
|
51
|
+
MultiDbMapper.sanitizeRequest(response)
|
|
52
|
+
} catch (e) {
|
|
53
|
+
if (cb)
|
|
54
|
+
return cb(e, undefined)
|
|
55
|
+
else
|
|
56
|
+
throw e;
|
|
57
|
+
}
|
|
58
|
+
if (cb)
|
|
59
|
+
cb(undefined, response);
|
|
60
|
+
else
|
|
61
|
+
return response;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
static async updateOne(query, newValue, cb) {
|
|
65
|
+
|
|
66
|
+
var response;
|
|
67
|
+
try {
|
|
68
|
+
|
|
69
|
+
response = await MultiDbMapper.db.update(MultiDbMapper.modelname, query, newValue['$set']);
|
|
70
|
+
|
|
71
|
+
} catch (e) {
|
|
72
|
+
if (cb)
|
|
73
|
+
return cb(e, undefined)
|
|
74
|
+
else
|
|
75
|
+
throw e;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (cb)
|
|
79
|
+
cb(undefined, response);
|
|
80
|
+
else
|
|
81
|
+
return response;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
static async deleteOne(query, cb) {
|
|
85
|
+
|
|
86
|
+
var response;
|
|
87
|
+
try {
|
|
88
|
+
|
|
89
|
+
response = await MultiDbMapper.db.delete(MultiDbMapper.modelname, query);
|
|
90
|
+
MultiDbMapper.sanitizeRequest(response)
|
|
91
|
+
|
|
92
|
+
} catch (e) {
|
|
93
|
+
if (cb)
|
|
94
|
+
return cb(e, undefined)
|
|
95
|
+
else
|
|
96
|
+
throw e;
|
|
97
|
+
}
|
|
98
|
+
if (cb)
|
|
99
|
+
cb(undefined, response)
|
|
100
|
+
else
|
|
101
|
+
return response;
|
|
102
|
+
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
MultiDbMapper.modelname = modelName;
|
|
108
|
+
MultiDbMapper.db = db;
|
|
109
|
+
return MultiDbMapper;
|
|
110
|
+
}
|
|
111
|
+
|
package/app/views/init.hbs
CHANGED
|
@@ -1,93 +1,98 @@
|
|
|
1
|
-
<
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
<div class="checkout-grid">
|
|
2
|
+
<aside class="product-panel card">
|
|
3
|
+
{{#if productImage}}
|
|
4
|
+
<div class="product-preview">
|
|
5
|
+
<img src="{{productImage}}" alt="{{PRODUCT_NAME}}" style="width:100%;height:100%;object-fit:cover" />
|
|
6
|
+
</div>
|
|
7
|
+
{{/if}}
|
|
8
|
+
|
|
9
|
+
<div class="product-price">
|
|
10
|
+
<div class="pill">Product</div>
|
|
11
|
+
<div class="price">{{PRODUCT_NAME}}</div>
|
|
12
|
+
</div>
|
|
13
|
+
{{#if PRODUCT_DESC}}
|
|
14
|
+
<p class="helper" style="margin-top:14px;">{{PRODUCT_DESC}}</p>
|
|
15
|
+
{{/if}}
|
|
16
|
+
</aside>
|
|
17
|
+
|
|
18
|
+
<section class="form-panel card">
|
|
19
|
+
<header class="card__header">
|
|
20
|
+
<div>
|
|
21
|
+
<p class="eyebrow">Payment</p>
|
|
22
|
+
<h2>Review & pay</h2>
|
|
23
|
+
</div>
|
|
24
|
+
<div class="amount-chip">₹ {{TXN_AMOUNT}}</div>
|
|
25
|
+
</header>
|
|
13
26
|
|
|
14
|
-
|
|
15
|
-
<li class="form-list__row">
|
|
16
|
-
<label>E-Mail</label>
|
|
17
|
-
<input type="text" name="EMAIL" required="" value="{{EMAIL}}" {{readonly}} />
|
|
18
|
-
</li>
|
|
27
|
+
<p class="helper">Your payment is processed over an encrypted channel. Double-check the details before you continue.</p>
|
|
19
28
|
|
|
20
|
-
<
|
|
21
|
-
|
|
22
|
-
<
|
|
23
|
-
|
|
29
|
+
<form action="{{action}}" method="POST" class="form-grid" id="payment-form">
|
|
30
|
+
{{#if check}}
|
|
31
|
+
<label class="field">
|
|
32
|
+
<span class="field__label">Full Name</span>
|
|
33
|
+
<input type="text" name="NAME" required value="{{NAME}}" {{readonly}} />
|
|
34
|
+
</label>
|
|
35
|
+
{{else}}
|
|
36
|
+
<input type="hidden" name="NAME" required value="{{NAME}}" {{readonly}} />
|
|
37
|
+
{{/if}}
|
|
24
38
|
|
|
39
|
+
<label class="field">
|
|
40
|
+
<span class="field__label">Email address</span>
|
|
41
|
+
<input type="email" name="EMAIL" required value="{{EMAIL}}" {{readonly}} />
|
|
42
|
+
</label>
|
|
25
43
|
|
|
26
|
-
|
|
44
|
+
<label class="field">
|
|
45
|
+
<span class="field__label">Phone</span>
|
|
46
|
+
<input type="text" name="MOBILE_NO" required value="{{MOBILE_NO}}" {{readonly}} />
|
|
47
|
+
</label>
|
|
27
48
|
|
|
28
49
|
{{#if check}}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
<
|
|
32
|
-
|
|
33
|
-
</label>
|
|
34
|
-
<input type="text" name="PRODUCT_NAME" required="" value="{{PRODUCT_NAME}}" {{readonly}} />
|
|
35
|
-
</div>
|
|
50
|
+
<label class="field">
|
|
51
|
+
<span class="field__label">Product</span>
|
|
52
|
+
<input type="text" name="PRODUCT_NAME" required value="{{PRODUCT_NAME}}" {{readonly}} />
|
|
53
|
+
</label>
|
|
36
54
|
{{else}}
|
|
37
|
-
<input type="hidden" name="PRODUCT_NAME" required
|
|
55
|
+
<input type="hidden" name="PRODUCT_NAME" required value="{{PRODUCT_NAME}}" {{readonly}} />
|
|
38
56
|
{{/if}}
|
|
39
57
|
|
|
40
|
-
|
|
41
|
-
|
|
58
|
+
<label class="field">
|
|
59
|
+
<span class="field__label">Amount</span>
|
|
60
|
+
<input type="text" name="TXN_AMOUNT" required value="{{TXN_AMOUNT}}" {{readonly}} />
|
|
61
|
+
</label>
|
|
42
62
|
|
|
43
|
-
<div>
|
|
44
|
-
<label>
|
|
45
|
-
|
|
63
|
+
<div style="grid-column:1 / -1; display:flex; gap:10px; align-items:center; justify-content:space-between;">
|
|
64
|
+
<label class="checkbox" style="margin:0">
|
|
65
|
+
<input type="checkbox" name="save_cc" checked="checked" />
|
|
66
|
+
<span>I agree to the merchant terms</span>
|
|
46
67
|
</label>
|
|
47
|
-
<
|
|
68
|
+
<div style="font-size:12px; color:rgba(255,255,255,0.6)">Secure by PCI-DSS</div>
|
|
48
69
|
</div>
|
|
49
70
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
<
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
<input type="hidden" name="MID" value="{{MID}}" {{readonly}}>
|
|
80
|
-
<input type="hidden" name="WEBSITE" value="{{WEBSITE}}" {{readonly}}>
|
|
81
|
-
<input type="hidden" name="ORDER_ID" value="{{ORDER_ID}}" {{readonly}}>
|
|
82
|
-
<input type="hidden" name="CUST_ID" value="{{CUST_ID}}" {{readonly}}>
|
|
83
|
-
<input type="hidden" name="INDUSTRY_TYPE_ID" value="{{INDUSTRY_TYPE_ID}}" {{readonly}}>
|
|
84
|
-
<input type="hidden" name="CHANNEL_ID" value="{{CHANNEL_ID}}" {{readonly}}>
|
|
85
|
-
<input type="hidden" name="CALLBACK_URL" value="{{CALLBACK_URL}}" {{readonly}}>
|
|
86
|
-
<input type="hidden" name="CHECKSUMHASH" value="{{CHECKSUMHASH}}" {{readonly}}>
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
</form>
|
|
71
|
+
<button id="pay-button" type="submit" class="button">{{BUTTON}}</button>
|
|
72
|
+
|
|
73
|
+
<input type="hidden" name="MID" value="{{MID}}" {{readonly}} />
|
|
74
|
+
<input type="hidden" name="WEBSITE" value="{{WEBSITE}}" {{readonly}} />
|
|
75
|
+
<input type="hidden" name="ORDER_ID" value="{{ORDER_ID}}" {{readonly}} />
|
|
76
|
+
<input type="hidden" name="CUST_ID" value="{{CUST_ID}}" {{readonly}} />
|
|
77
|
+
<input type="hidden" name="INDUSTRY_TYPE_ID" value="{{INDUSTRY_TYPE_ID}}" {{readonly}} />
|
|
78
|
+
<input type="hidden" name="CHANNEL_ID" value="{{CHANNEL_ID}}" {{readonly}} />
|
|
79
|
+
<input type="hidden" name="CALLBACK_URL" value="{{CALLBACK_URL}}" {{readonly}} />
|
|
80
|
+
<input type="hidden" name="CHECKSUMHASH" value="{{CHECKSUMHASH}}" {{readonly}} />
|
|
81
|
+
</form>
|
|
82
|
+
</section>
|
|
83
|
+
</div>
|
|
84
|
+
|
|
85
|
+
{{!-- <script>
|
|
86
|
+
(function(){
|
|
87
|
+
if (window.__npPayBtnBound) return;
|
|
88
|
+
window.__npPayBtnBound = true;
|
|
89
|
+
const payBtn = document.getElementById('pay-button');
|
|
90
|
+
if (payBtn) {
|
|
91
|
+
payBtn.addEventListener('click', () => {
|
|
92
|
+
payBtn.setAttribute('data-loading', 'true');
|
|
93
|
+
payBtn.setAttribute('disabled', 'disabled');
|
|
94
|
+
setTimeout(() => payBtn.innerText = 'Processing…', 10);
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
})();
|
|
98
|
+
</script> --}}
|
|
@@ -1,58 +1,53 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
|
-
<html>
|
|
3
|
-
|
|
2
|
+
<html lang="en">
|
|
4
3
|
<head>
|
|
5
|
-
<meta charset="UTF-8"
|
|
6
|
-
<
|
|
7
|
-
<
|
|
8
|
-
|
|
9
|
-
<
|
|
10
|
-
<link
|
|
11
|
-
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/
|
|
12
|
-
|
|
13
|
-
<link rel="
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
</head>
|
|
17
|
-
|
|
18
|
-
<body>
|
|
19
|
-
|
|
20
|
-
<div class="modal">
|
|
21
|
-
<div class="modal__container">
|
|
22
|
-
|
|
23
|
-
<div class="modal__content">
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
{{{body}}}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
</div> <!-- END: .modal__content -->
|
|
33
|
-
</div> <!-- END: .modal__container -->
|
|
34
|
-
</div> <!-- END: .modal -->
|
|
35
|
-
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js'></script>
|
|
36
|
-
|
|
37
|
-
<script src="js/index.js"></script>
|
|
38
|
-
|
|
39
|
-
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>{{brand}} · Secure Checkout</title>
|
|
7
|
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
8
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
9
|
+
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&display=swap" rel="stylesheet" />
|
|
10
|
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css" />
|
|
11
|
+
<link rel="stylesheet" href="css/style.css" />
|
|
12
|
+
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2016%2016'%3E%3Crect%20width='16'%20height='16'%20rx='3'%20fill='%23ff5722'/%3E%3C/svg%3E" />
|
|
13
|
+
<link rel="shortcut icon" href="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2016%2016'%3E%3Crect%20width='16'%20height='16'%20rx='3'%20fill='%23ff5722'/%3E%3C/svg%3E" />
|
|
40
14
|
<style>
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
color:
|
|
49
|
-
|
|
50
|
-
input {
|
|
51
|
-
color: #cc0f0f;
|
|
15
|
+
:root {
|
|
16
|
+
--color-primary: {{theme.primary}};
|
|
17
|
+
--color-accent: {{theme.accent}};
|
|
18
|
+
--color-surface: {{theme.surface}};
|
|
19
|
+
--color-text: {{theme.text}};
|
|
20
|
+
--color-success: {{theme.success}};
|
|
21
|
+
--color-danger: {{theme.danger}};
|
|
22
|
+
--color-outline: rgba(255,255,255,0.08);
|
|
23
|
+
--radius: 14px;
|
|
52
24
|
}
|
|
53
|
-
|
|
54
|
-
*/
|
|
55
25
|
</style>
|
|
26
|
+
</head>
|
|
27
|
+
<body class="theme-{{themeName}}">
|
|
28
|
+
<div class="shell">
|
|
29
|
+
<header class="shell__header">
|
|
30
|
+
<div class="brand">
|
|
31
|
+
{{#if logo}}
|
|
32
|
+
<span class="brand__mark brand__mark--img"><img src="{{logo}}" alt="{{brand}} logo"></span>
|
|
33
|
+
{{else}}
|
|
34
|
+
<span class="brand__mark">{{brand}}</span>
|
|
35
|
+
{{/if}}
|
|
36
|
+
<div class="brand__text">
|
|
37
|
+
<div class="brand__title">{{brand}}</div>
|
|
38
|
+
<div class="brand__meta">Secure checkout</div>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
<div class="pill">Encrypted</div>
|
|
42
|
+
</header>
|
|
43
|
+
|
|
44
|
+
<main class="shell__content">
|
|
45
|
+
{{{body}}}
|
|
46
|
+
</main>
|
|
47
|
+
|
|
48
|
+
<footer class="shell__footer">
|
|
49
|
+
<span>Protected by {{brand}}</span>
|
|
50
|
+
</footer>
|
|
51
|
+
</div>
|
|
56
52
|
</body>
|
|
57
|
-
|
|
58
53
|
</html>
|
package/app/views/result.hbs
CHANGED
|
@@ -1,50 +1,46 @@
|
|
|
1
|
-
|
|
1
|
+
<section class="card" style="text-align:center; padding:36px 28px;">
|
|
2
|
+
<div style="display:flex; flex-direction:column; align-items:center; gap:18px;" class="status-{{status}}">
|
|
3
|
+
<div style="width:84px; height:84px; border-radius:999px; display:grid; place-items:center; background:rgba(255,255,255,0.03);">
|
|
4
|
+
<svg class="icon-success" width="40" height="40" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M20 6L9 17l-5-5" stroke="#4cff9f" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
|
5
|
+
<svg class="icon-fail" width="40" height="40" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" style="display:none"><circle cx="12" cy="12" r="9" stroke="#ff9b9b" stroke-width="2.2"/><path d="M12 8v5" stroke="#ff9b9b" stroke-width="2.2" stroke-linecap="round"/><path d="M12 16h.01" stroke="#ff9b9b" stroke-width="2.2" stroke-linecap="round"/></svg>
|
|
6
|
+
</div>
|
|
2
7
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
8
|
+
<div>
|
|
9
|
+
<h2 style="margin:0">Payment</h2>
|
|
10
|
+
<p class="helper" style="margin-top:6px">{{message}}</p>
|
|
11
|
+
</div>
|
|
6
12
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
13
|
+
<div class="result-grid" style="max-width:560px; width:100%;">
|
|
14
|
+
<div class="result-item">
|
|
15
|
+
<p class="label">Order ID</p>
|
|
16
|
+
<p class="value">{{orderId}}</p>
|
|
17
|
+
</div>
|
|
18
|
+
<div class="result-item">
|
|
19
|
+
<p class="label">Transaction ID</p>
|
|
20
|
+
<p class="value">{{TXNID}}</p>
|
|
21
|
+
</div>
|
|
22
|
+
<div class="result-item">
|
|
23
|
+
<p class="label">Amount</p>
|
|
24
|
+
<p class="value">{{amount}}</p>
|
|
25
|
+
</div>
|
|
26
|
+
<div class="result-item">
|
|
27
|
+
<p class="label">Date & Time</p>
|
|
28
|
+
<p class="value">{{date}}</p>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
11
31
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
<li class="form-list__row form-list__row--inline">
|
|
29
|
-
|
|
30
|
-
<div>
|
|
31
|
-
<label>
|
|
32
|
-
Amount
|
|
33
|
-
</label>
|
|
34
|
-
<input type="text" name="TXN_AMOUNT" required="" value="{{amount}}" {{readonly}} />
|
|
35
|
-
</div>
|
|
36
|
-
|
|
37
|
-
</li>
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
<li>
|
|
42
|
-
<button type="submit" class="button">DONE</button>
|
|
43
|
-
</li>
|
|
44
|
-
</ul>
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
</form>
|
|
32
|
+
<div style="display:flex; gap:12px; margin-top:8px; width:100%; justify-content:center;">
|
|
33
|
+
<div class="success-buttons" style="display:flex; gap:12px;">
|
|
34
|
+
<a href="{{receiptUrl}}" class="button" style="text-decoration:none;">Download Receipt</a>
|
|
35
|
+
<form action="{{homeAction}}" method="GET" style="display:inline"><button type="submit" class="button">Done</button></form>
|
|
36
|
+
</div>
|
|
37
|
+
<div class="fail-buttons" style="display:flex; gap:12px;">
|
|
38
|
+
<form action="{{retryAction}}" method="POST" style="display:inline">
|
|
39
|
+
<input type="hidden" name="ORDER_ID" value="{{orderId}}" />
|
|
40
|
+
<button type="submit" class="button">Try Again</button>
|
|
41
|
+
</form>
|
|
42
|
+
<form action="{{cancelAction}}" method="GET" style="display:inline"><button type="submit" class="button">Cancel</button></form>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
</section>
|