xpay-redirect 0.2.0

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.
@@ -0,0 +1,732 @@
1
+ import * as React from 'react';
2
+ // Material UI
3
+ import {
4
+ Box,
5
+ Button,
6
+ Dialog,
7
+ Grid,
8
+ IconButton,
9
+ Paper,
10
+ Stack,
11
+ styled,
12
+ TextField,
13
+ Typography
14
+ } from '@mui/material';
15
+ import { LoadingButton } from '@mui/lab';
16
+ // Icons
17
+ import HighlightOffRoundedIcon from '@mui/icons-material/HighlightOffRounded';
18
+ import KeyboardBackspaceRoundedIcon from '@mui/icons-material/KeyboardBackspaceRounded';
19
+ // images
20
+ import FTBLogo from '../../../assets/ai Icon/ai Icon-4.png';
21
+ import FTBName from '../../../assets/ai Icon/ai Icon-2.png';
22
+ import FTBSuccess from '../../../assets/ai Icon/ai Icon-1.png';
23
+ // files
24
+ import RegNewAccount from './RegNewAccount';
25
+ import axios from 'axios';
26
+
27
+ const months = [
28
+ 'January',
29
+ 'February',
30
+ 'March',
31
+ 'April',
32
+ 'May',
33
+ 'June',
34
+ 'July',
35
+ 'August',
36
+ 'September',
37
+ 'October',
38
+ 'November',
39
+ 'December'
40
+ ];
41
+
42
+ function formatAMPM(date) {
43
+ var hours = date.getHours();
44
+ var minutes = date.getMinutes();
45
+ var ampm = hours >= 12 ? 'pm' : 'am';
46
+ hours = hours % 12;
47
+ hours = hours ? hours : 12; // the hour '0' should be '12'
48
+ minutes = minutes < 10 ? '0'+minutes : minutes;
49
+
50
+ var strTime = months[date.getMonth()]+' '+date.getDate()+', '+ date.getFullYear()+' '+hours+':'+minutes+' '+ampm;
51
+ return strTime;
52
+ };
53
+
54
+ const BootstrapDialog = styled(Dialog)(({ theme }) => ({
55
+ '& .MuiDialog-paper': {
56
+ borderRadius: '1.6rem',
57
+ backgroundColor: '#0a4e9c',
58
+ },
59
+ // '& .MuiDialogContent-root': {
60
+ // padding: '16px',
61
+ // },
62
+ // '& .MuiDialogActions-root': {
63
+ // padding: '8px',
64
+ // },
65
+ }));
66
+
67
+ const StyledPaper = styled(Paper)(({ theme }) => ({
68
+ backgroundColor: '#fff',
69
+ fontFamily: '"Roboto","Helvetica","Arial",sans-serif',
70
+ fontWeight: '400',
71
+ fontSize: '0.875rem',
72
+ lineHeight: '1.43',
73
+ letterSpacing: '0.01071em',
74
+ // padding: '16px',
75
+ minWidth: 300,
76
+ maxWidth: 400,
77
+ color: 'rgba(0, 0, 0, 0.87)',
78
+ }));
79
+
80
+ export default function FTBxPAYPage(props) {
81
+ const {
82
+ config, baseurl, largeScreen, sessionid, paymenttokenid, initialHours=0, initialMinutes=5, initialSeconds=0
83
+ } = props;
84
+
85
+ // default 3minutes timer
86
+ const timeControl = React.useRef(true);
87
+ const [timer, setTimer] = React.useState(null);
88
+ const [time, setTime] = React.useState({
89
+ h: initialHours,
90
+ m: initialMinutes,
91
+ s: initialSeconds,
92
+ });
93
+
94
+ const onResponse = config?.onResponse
95
+ ? config.onResponse
96
+ : (data) => {
97
+ console.log("Xpay Response ::> ", data);
98
+ };
99
+ const onError = config?.onError
100
+ ? config.onError
101
+ : (err) => {
102
+ throw err;
103
+ };
104
+
105
+ // it disables the acct number or card details
106
+ const [cardDisable, setCardDisable] = React.useState(false);
107
+ // it shows card details and otp input
108
+ // const [pageDisplay, setPageDisplay] = React.useState(false);
109
+ // check bank account or card number is valid and details
110
+ const [acctOrCardNumber, setAcctOrCardNumber] = React.useState('');
111
+ const [acctOrCardFetching, setAcctOrCardFetching] = React.useState(false);
112
+ // verification failed
113
+ const [acctOrCardErrorMsg, setAcctOrCardErrorMsg] = React.useState(false);
114
+ // details after verifying bank account or card number
115
+ const [customerName, setCustomerName] = React.useState('');
116
+ const [accountNumber, setAccountNumber] = React.useState('');
117
+ const [debitAccount, setDebitAccount] = React.useState('');
118
+
119
+ // disable otp till it get to activate
120
+ const [otpInputDisabled, setOtpInputDisabled] = React.useState(true);
121
+ // create account page
122
+ const [openCreateAccount, setOpenCreateAccount] = React.useState(false);
123
+
124
+ // OTP validation
125
+ const [otpNumber, setOtpNumber] = React.useState('');
126
+ const [otpValidFetching, setOtpValidFetching] = React.useState(false);
127
+ // error message for OTP
128
+ const [otpError, setOtpError] = React.useState('');
129
+ const [otpErrorMsg, setOtpErrorMsg] = React.useState('');
130
+ // details after verifying OTP
131
+ const [otpSuccessPopup, setOtpSuccessPopup] = React.useState(false);
132
+ const [otpValidDetail, setOtpValidDetail] = React.useState('');
133
+
134
+ // For new account register
135
+ const [regSentOTP, setRegSentOTP] = React.useState(false);
136
+
137
+ // ---------- Time Access (start) ----------
138
+ const startTimer = () => {
139
+ let myInterval = setInterval(() => {
140
+ setTime((time) => {
141
+ const updatedTime = { ...time };
142
+ if (time.s > 0) {
143
+ updatedTime.s--;
144
+ }
145
+
146
+ if (time.s === 0) {
147
+ if (time.h === 0 && time.m === 0) {
148
+ clearInterval(myInterval);
149
+ } else if (time.m > 0) {
150
+ updatedTime.m--;
151
+ updatedTime.s = 59;
152
+ } else if (updatedTime.h > 0) {
153
+ updatedTime.h--;
154
+ updatedTime.m = 59;
155
+ updatedTime.s = 59;
156
+ }
157
+ }
158
+
159
+ return updatedTime;
160
+ });
161
+ }, 1000);
162
+ setTimer(myInterval);
163
+ };
164
+
165
+ const pauseTimer = () => {
166
+ clearInterval(timer);
167
+ };
168
+
169
+ const cancelTimer = () => {
170
+ clearInterval(timer);
171
+ setTime({
172
+ h: initialHours,
173
+ m: initialMinutes,
174
+ s: initialSeconds,
175
+ });
176
+ };
177
+
178
+ React.useEffect(() => {
179
+ if (timeControl.current) {
180
+ timeControl.current = false
181
+ startTimer();
182
+ }
183
+
184
+ return () => { }
185
+ }, []);
186
+ // ---------- Time Access (end) ----------
187
+
188
+ const handleClearAll = () => {
189
+ setAcctOrCardNumber(""); // acct or card num input empty value
190
+ setCustomerName(""); // customer name empty
191
+ setAccountNumber(""); // acct num empty
192
+ setDebitAccount(""); // debit acct empty
193
+ setAcctOrCardErrorMsg(''); // clear error msg of card
194
+
195
+ setOtpInputDisabled(true); // first page otp input makes disable
196
+ setOtpNumber(''); // otp input empty
197
+ setOtpSuccessPopup(false); // final pop up close
198
+
199
+ setOpenCreateAccount(false); // register page closed access
200
+ setRegSentOTP(false); // register page otp page closed access
201
+ };
202
+
203
+ // cancel session
204
+ const CancelSession = async() => {
205
+ let text = {
206
+ "sessionid": sessionid
207
+ };
208
+
209
+ try {
210
+ const res = await axios({
211
+ method: 'post',
212
+ url: `${baseurl}/CloseSession`,
213
+ data: text
214
+ });
215
+ onResponse({"at":"/CloseSession", "response":res.data});
216
+ handleClearAll();
217
+ sessionStorage.removeItem("sessionid");
218
+ sessionStorage.removeItem("paymenttokenid");
219
+ sessionStorage.clear();
220
+ window.history.back();
221
+ // cancelTimer();
222
+ } catch (error) {
223
+ onError({"at":"/CloseSession", "error":error?.response?.data || error?.message || error});
224
+ }
225
+ }
226
+
227
+ // Account validation
228
+ const acctOrCardNumberSubmit = async(e) => {
229
+ e.preventDefault();
230
+ setAcctOrCardFetching(true);
231
+ try {
232
+ let jobj = {
233
+ "sessionid": sessionid || '',
234
+ "ptokenId": paymenttokenid || '',
235
+ "userdetails": {
236
+ "userid": acctOrCardNumber || '',
237
+ "cardName":'',
238
+ "cardExpiry":'',
239
+ "validThrough":'',
240
+ "paymentOption":'2',
241
+ "xcif": acctOrCardNumber||''
242
+ }
243
+ };
244
+
245
+ const response = await axios({
246
+ method: 'post',
247
+ url: `${baseurl}/identifyUser`,
248
+ data: jobj,
249
+ });
250
+ onResponse({ 'at':'/identifyUser', 'response':response.data});
251
+
252
+ if(response.data._result === 'success') {
253
+ setCustomerName(response?.data?._username);
254
+ setAccountNumber(response?.data?._userid);
255
+ setDebitAccount(response?.data?.accountlist?.toString());
256
+
257
+ // send security code otp
258
+ try {
259
+ let jobjdata = {
260
+ "sessionid": sessionid || '',
261
+ "ptokenId": paymenttokenid || '',
262
+ "userdetails": {
263
+ "userid": acctOrCardNumber || '',
264
+ "cardName":'',
265
+ "cardExpiry":'',
266
+ "validThrough":'',
267
+ "paymentOption":'2',
268
+ "xcif": acctOrCardNumber||''
269
+ }
270
+ };
271
+
272
+ const res = await axios({
273
+ method: 'post',
274
+ url: `${baseurl}/SendSecurityCode`,
275
+ data: jobjdata,
276
+ });
277
+ onResponse({ 'at':'/SendSecurityCode', 'response':res.data});
278
+ } catch (error) {
279
+ onError({ 'at':'/SendSecurityCode', 'error':error?.response?.data || error?.message || error});
280
+ }
281
+ setOtpInputDisabled(false);
282
+ setAcctOrCardErrorMsg('');
283
+ setOtpErrorMsg('');
284
+ setOtpError('');
285
+ } else {
286
+ setAcctOrCardErrorMsg(response?.data?._message || 'Error');
287
+ setCustomerName("");
288
+ setAccountNumber("");
289
+ setDebitAccount("");
290
+ }
291
+ setAcctOrCardFetching(false);
292
+ } catch (error) {
293
+ onError({ 'at':'/identifyUser', 'error':error?.response?.data || error?.message || error});
294
+ setAcctOrCardErrorMsg(error?.response?.data || error?.message || error);
295
+ setAcctOrCardFetching(false);
296
+ setOtpInputDisabled(true);
297
+ }
298
+ };
299
+
300
+ // OTP Token validation
301
+ const otpNumberSubmit = async(e) => {
302
+ e.preventDefault();
303
+ setOtpValidFetching(true);
304
+ try {
305
+ let jobj = {
306
+ "sessionid": sessionid || '',
307
+ "ptokenId": paymenttokenid || '',
308
+ "userdetails": {
309
+ "userid": acctOrCardNumber || '',
310
+ "cardName":'',
311
+ "cardExpiry":'',
312
+ "validThrough":'',
313
+ "paymentOption":'2',
314
+ "xcif": acctOrCardNumber||''
315
+ },
316
+ "credential": otpNumber
317
+ };
318
+
319
+ const response = await axios({
320
+ method: 'post',
321
+ url: `${baseurl}/verifyTransaction`,
322
+ data: jobj,
323
+ });
324
+ onResponse({"at":"/verifyTransaction", "response":response.data});
325
+ setOtpValidDetail(response.data);
326
+ setOtpSuccessPopup(true);
327
+ setOtpErrorMsg('');
328
+ setOtpError(false);
329
+ setOtpValidFetching(false);
330
+ } catch (error) {
331
+ setOtpSuccessPopup(false);
332
+ setOtpError(true);
333
+ setOtpErrorMsg("Sorry, One Time Password is invalid, Please enter again!" || "Sorry, One Time Password expired!!!")
334
+ setOtpValidFetching(false);
335
+ }
336
+ };
337
+
338
+ React.useEffect(() => {
339
+ if(time.h<=0 && time.m<=0 && time.s<=0 ) {
340
+ setCardDisable(true);
341
+ handleClearAll();
342
+ // setPageDisplay(false);
343
+ }
344
+
345
+ return () => {}
346
+ });
347
+
348
+ return (<>
349
+ <Box
350
+ sx={{
351
+ color:'#fff',
352
+ backgroundColor:'#0a4e9c',
353
+ borderRadius: '1.6rem',
354
+ marginTop:largeScreen?1:0,
355
+ minWidth:largeScreen?'420px':'auto',
356
+ width:largeScreen?'max-content':'100%'
357
+ }}
358
+ >
359
+ {/* --------- Box Header --------- */}
360
+ <div
361
+ style={{
362
+ margin: 0, padding:'12px 16px 8px',
363
+ display:'flex',
364
+ alignItems:'center',
365
+ justifyContent:'space-between'
366
+ }}
367
+ >
368
+ <img src={FTBLogo} alt='FTB' width={70} height={25} />
369
+ <IconButton
370
+ aria-label="close"
371
+ onClick={() => { CancelSession(); }}
372
+ sx={{
373
+ // position: 'absolute',
374
+ // right: 8,
375
+ // top: 8,
376
+ color: '#fff',
377
+ }}
378
+ >
379
+ <HighlightOffRoundedIcon />
380
+ </IconButton>
381
+ </div>
382
+
383
+ {/* --------- Box Content --------- */}
384
+ <div
385
+ style={{
386
+ backgroundColor:'#fff',
387
+ borderRadius:'1.6rem 1.6rem 0 0',
388
+ padding:'16px',
389
+ border: '1px solid #afafaf'
390
+ }}
391
+ >
392
+ {/* --------- CREATE NEW ACCOUNT MODULE --------- */}
393
+ {openCreateAccount ?
394
+ <RegNewAccount
395
+ config={config}
396
+ baseurl={baseurl}
397
+ startTimer={startTimer}
398
+ sessionid={sessionid}
399
+ setAcctOrCardNumber={setAcctOrCardNumber}
400
+ regSentOTP={regSentOTP}
401
+ setRegSentOTP={setRegSentOTP}
402
+ setOpenCreateAccount={setOpenCreateAccount}
403
+ />
404
+ :
405
+ <React.Fragment>
406
+ {/* --------- FORM TOKEN VALIDATE MODULE --------- */}
407
+
408
+ {/* --------- 5MINS TIMER TRANSACTION PROCESS --------- */}
409
+ <Typography
410
+ style={{
411
+ backgroundColor:'#a68206',
412
+ borderRadius:'0.6rem',
413
+ padding:'0.6rem',
414
+ fontSize:'13px',
415
+ color:'#fff',
416
+ textAlign:'center'
417
+ }}
418
+ >
419
+ {(time.h<=0 && time.m<=0 && time.s<=0 )?
420
+ <span style={{ color:'#ff0000',fontWeight:'bold' }}>Payment session expired !</span>
421
+ :
422
+ <span>
423
+ Payment session will expired in 5mins&nbsp;({time.h<10 && time.h!==0 ? `0${time.h}:` : time.h>=10 && `${time.h}:`}
424
+ {time.m < 10 ? `0${time.m}` : time.m}:
425
+ {time.s < 10 ? `0${time.s}` : time.s})
426
+ </span>
427
+ }
428
+ </Typography>
429
+
430
+ {/* --------- TRANSACTION PROCESS DETAILS --------- */}
431
+ <Box sx={{ flexGrow: 1, overflow: 'hidden' }}>
432
+ <StyledPaper sx={{ my:1, mx:'auto', p:2, }}>
433
+ <Grid container spacing={1}>
434
+ <Grid container wrap="nowrap" item spacing={1}>
435
+ <Grid item xs={6}>Amount</Grid>
436
+ <Grid item xs={2}>:</Grid>
437
+ <Grid item xs={6}><b style={{ color:'#a68206' }}>USD {config?.transactionDetails?.amount}</b></Grid>
438
+ </Grid>
439
+ <Grid container wrap="nowrap" item spacing={1}>
440
+ <Grid item xs={6}>Merchant Name</Grid>
441
+ <Grid item xs={2}>:</Grid>
442
+ <Grid item xs={6}><div style={{ color:'#a68206' }}>{config?.merchantName}</div></Grid>
443
+ </Grid>
444
+ <Grid container wrap="nowrap" item spacing={1}>
445
+ <Grid item xs={6}>Transaction ID</Grid>
446
+ <Grid item xs={2}>:</Grid>
447
+ <Grid item xs={6}>{config?.transactionDetails?.txid}</Grid>
448
+ </Grid>
449
+ </Grid>
450
+ </StyledPaper>
451
+
452
+ <StyledPaper sx={{ my:1, mx:'auto', p:2, }}>
453
+ <Grid container spacing={1}>
454
+ <Grid container wrap="nowrap" item spacing={1}>
455
+ <Grid item xs={12}>
456
+ {/* --------- FORM ERROR DISPLAY --------- */}
457
+ {acctOrCardErrorMsg &&
458
+ <div
459
+ style={{
460
+ color: '#ff0000',
461
+ padding: '0px 12px 5px 12px',
462
+ fontSize: '12px',
463
+ textAlign: 'center'
464
+ }}
465
+ >{acctOrCardErrorMsg} (OR) you can {" "}
466
+ <span
467
+ style={{
468
+ textDecoration: 'underline',
469
+ WebkitTextDecorationColor: 'red', // Safari
470
+ textDecorationColor: 'red',
471
+ cursor: 'pointer'
472
+ }}
473
+ onClick={()=>{
474
+ pauseTimer();
475
+ setOpenCreateAccount(true);
476
+ }}
477
+ >
478
+ Register Account Here
479
+ </span>.
480
+ </div>
481
+ }
482
+
483
+ {/* --------- FORM VALIDATE USER ACCOUNT --------- */}
484
+ <form onSubmit={(e)=>acctOrCardNumberSubmit(e)}>
485
+ <Stack direction="row" spacing={1}>
486
+ <TextField
487
+ required
488
+ fullWidth
489
+ autoFocus
490
+ variant='outlined'
491
+ id="acct-card-number"
492
+ value={acctOrCardNumber}
493
+ size="small"
494
+ autoComplete='off'
495
+ // type="number"
496
+ // min="0"
497
+ onKeyPress={(event) => {
498
+ if (!/[0-9.]/.test(event.key)) {
499
+ event.preventDefault();
500
+ }
501
+ }}
502
+ disabled={cardDisable}
503
+ placeholder="Enter bank account/card number"
504
+ onChange={(event) => {
505
+ setAcctOrCardNumber(event.target.value);
506
+ }}
507
+ sx={{
508
+ '& fieldset': {
509
+ borderRadius: '30px',
510
+ },
511
+ }}
512
+ />
513
+ {/* --------- FORM VALIDATE BUTTON --------- */}
514
+ <LoadingButton
515
+ loading={acctOrCardFetching}
516
+ variant='contained'
517
+ type='submit'
518
+ disabled={cardDisable}
519
+ sx={{
520
+ borderRadius: '30px',
521
+ textTransform: "none",
522
+ backgroundColor:'#0a4e9c',
523
+ '&:active, &:focus, &:hover': {
524
+ backgroundColor:'#053e88'
525
+ }
526
+ }}
527
+ >
528
+ &nbsp;Validate&nbsp;
529
+ </LoadingButton>
530
+ </Stack>
531
+ </form>
532
+ </Grid>
533
+ </Grid>
534
+ <Grid container wrap="nowrap" item spacing={1}>
535
+ <Grid item xs={6}>Customer Name</Grid>
536
+ <Grid item xs={2}>:</Grid>
537
+ <Grid item xs={6}><b style={{ color:'#a68206' }}>{customerName}</b></Grid>
538
+ </Grid>
539
+ <Grid container wrap="nowrap" item spacing={1}>
540
+ <Grid item xs={6}>Account Number</Grid>
541
+ <Grid item xs={2}>:</Grid>
542
+ <Grid item xs={6}><div style={{ color:'#a68206' }}>{accountNumber}</div></Grid>
543
+ </Grid>
544
+ <Grid container wrap="nowrap" item spacing={1}>
545
+ <Grid item xs={6}>Debit Account</Grid>
546
+ <Grid item xs={2}>:</Grid>
547
+ <Grid item xs={6}>{debitAccount}</Grid>
548
+ </Grid>
549
+ </Grid>
550
+
551
+ </StyledPaper>
552
+
553
+ <Box
554
+ sx={{
555
+ flexGrow: 1,
556
+ mx:'auto',
557
+ backgroundColor: '#fff',
558
+ p: 2,
559
+ minWidth: 300,
560
+ maxWidth: 400,
561
+ }}
562
+ >
563
+ <Grid container spacing={1}>
564
+ <Grid container wrap="nowrap" item spacing={1}>
565
+ <Grid item xs={12}>
566
+ {/* --------- FORM OTP TOKEN VALIDATE --------- */}
567
+ <form onSubmit={(e)=>otpNumberSubmit(e)}>
568
+ <Stack direction="row" spacing={1}>
569
+ <TextField
570
+ required
571
+ fullWidth
572
+ disabled={otpInputDisabled}
573
+ variant={'outlined'}
574
+ id="otp-number"
575
+ value={otpNumber}
576
+ size="small"
577
+ autoComplete='off'
578
+ // type="number"
579
+ // min="0"
580
+ onKeyPress={(event) => {
581
+ if (!/[0-9.]/.test(event.key)) {
582
+ event.preventDefault();
583
+ }
584
+ }}
585
+ placeholder="Enter OTP Token"
586
+ onChange={(event) => {
587
+ setOtpNumber(event.target.value);
588
+ }}
589
+ sx={{
590
+ '& fieldset': {
591
+ borderRadius: '30px',
592
+ },
593
+ }}
594
+ />
595
+ {/* --------- OTP TOKEN VALID BUTTON --------- */}
596
+ <LoadingButton
597
+ variant='contained'
598
+ type='submit'
599
+ loading={otpValidFetching}
600
+ disabled={otpInputDisabled}
601
+ sx={{
602
+ borderRadius: '30px',
603
+ textTransform: "none",
604
+ backgroundColor:'#0a4e9c',
605
+ '&:active, &:focus, &:hover': {
606
+ backgroundColor:'#053e88'
607
+ }
608
+ }}
609
+ >
610
+ &nbsp;Validate&nbsp;
611
+ </LoadingButton>
612
+ </Stack>
613
+ </form>
614
+ </Grid>
615
+ </Grid>
616
+
617
+ {!otpInputDisabled && otpError==='' && <Grid container wrap="nowrap" item spacing={1}>
618
+ <Grid
619
+ item
620
+ xs={12}
621
+ style={{
622
+ color:'#808080',
623
+ padding:'8px 12px 0',
624
+ textAlign:'center',
625
+ fontSize:'12px'
626
+ }}
627
+ >
628
+ You have mobile one time password security token assigned.
629
+ <br/>
630
+ Please use that for generating OTP.
631
+ </Grid>
632
+ </Grid>}
633
+
634
+ {/* --------- OTP TOKEN ERROR DISPLAY --------- */}
635
+ {otpError && otpErrorMsg && <Grid container wrap="nowrap" item spacing={1}>
636
+ <Grid
637
+ item
638
+ xs={12}
639
+ style={{
640
+ color:'red',
641
+ padding:'8px 12px 0',
642
+ textAlign:'center',
643
+ fontSize:'12px'
644
+ }}
645
+ >
646
+ {otpErrorMsg}
647
+ </Grid>
648
+ </Grid>}
649
+ </Grid>
650
+ </Box>
651
+ </Box>
652
+ </React.Fragment>
653
+ }
654
+ </div>
655
+
656
+ {/* --------- Box Footer --------- */}
657
+ <div style={{
658
+ display:'flex',
659
+ justifyContent:openCreateAccount?'space-between':'flex-end',
660
+ minHeight:'60px',
661
+ padding: '8px 16px 12px'
662
+ }}>
663
+ {/* --------- GET BACK BUTTON --------- */}
664
+ <IconButton
665
+ aria-label="back"
666
+ onClick={() => {
667
+ if(regSentOTP) {
668
+ setRegSentOTP(false)
669
+ } else {
670
+ startTimer();
671
+ setOpenCreateAccount(false)
672
+ }
673
+ }}
674
+ sx={{
675
+ color: '#fff',
676
+ display:openCreateAccount?'block':'none'
677
+ }}
678
+ >
679
+ <KeyboardBackspaceRoundedIcon />
680
+ </IconButton>
681
+
682
+ <img src={FTBName} alt='FTB Name' width={150} />
683
+ </div>
684
+ </Box>
685
+
686
+ {otpSuccessPopup && <BootstrapDialog
687
+ // onClose={() => { setOtpSuccessPopup(false) }}
688
+ aria-labelledby="customized-otp-success"
689
+ open={otpSuccessPopup}
690
+ >
691
+ <center style={{color:'#fff',padding:'14px',minWidth:'300px',maxWidth:'350px'}}>
692
+ <img src={FTBSuccess} alt="Payment success" style={{ marginLeft:'33px' }}/>
693
+ <Typography>Payment received</Typography>
694
+ <Typography variant='h6' component={'div'} style={{ color:'#a68206',fontWeight:'bold' }}>
695
+ USD {otpValidDetail?.usd}
696
+ </Typography>
697
+ <div style={{ lineHeight:2 }}>
698
+ Transaction ID: <b>{otpValidDetail?.transactionID}</b>
699
+ </div>
700
+ <div style={{ lineHeight:2 }}>
701
+ Receiver: <b>{otpValidDetail?.merchantName}</b>
702
+ </div>
703
+ <div style={{ lineHeight:2 }}>
704
+ {formatAMPM(otpValidDetail?.date || new Date())}
705
+ </div>
706
+
707
+ <Button
708
+ variant='outlined'
709
+ size='small'
710
+ onClick={() => {
711
+ setOtpSuccessPopup(false);
712
+ sessionStorage.removeItem("sessionid");
713
+ sessionStorage.removeItem("paymenttokenid");
714
+ sessionStorage.clear();
715
+ window.history.back();
716
+ }}
717
+ sx={{
718
+ borderRadius: '30px',
719
+ backgroundColor:'#0a4e9c',
720
+ color:'#a68206',
721
+ mt:2,
722
+ '&:active, &:focus, &:hover': {
723
+ backgroundColor:'#053e88',
724
+ }
725
+ }}
726
+ >
727
+ CLOSE
728
+ </Button>
729
+ </center>
730
+ </BootstrapDialog>}
731
+ </>);
732
+ }