@jimrising/easymerchantsdk-react-native 1.3.3 → 1.3.4

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.
@@ -66,10 +66,16 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
66
66
  @IBOutlet private var cardExpiryTextField: TextFieldStackView!
67
67
  @IBOutlet private var cardCvvTextField: TextFieldStackView!
68
68
  @IBOutlet private var cardNameTextField: TextFieldStackView!
69
+ @IBOutlet weak var txtFieldChosePlanCard: TextFieldStackView!
70
+ @IBOutlet weak var txtFieldStartDateCard: TextFieldStackView!
69
71
  @IBOutlet weak var viewTextFieldCardNumber: UIView!
70
72
  @IBOutlet weak var viewTxtFieldExpiryDate: UIView!
71
73
  @IBOutlet weak var viewTxtFieldCVV: UIView!
72
74
  @IBOutlet weak var viewTxtFieldNameOnCard: UIView!
75
+ @IBOutlet weak var viewTxtFieldChosePlanCard: UIView!
76
+ @IBOutlet weak var viewTxtFieldStartDateCard: UIView!
77
+ @IBOutlet weak var imgViewChosePlanCardDropIcon: UIImageView!
78
+ @IBOutlet weak var imgViewCalenderIconCard: UIImageView!
73
79
 
74
80
  @IBOutlet weak var btnScanCard: UIButton!
75
81
 
@@ -100,7 +106,6 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
100
106
 
101
107
  //Single Saved Card
102
108
  @IBOutlet weak var viewSingleSavedCard: UIView!
103
- @IBOutlet weak var viewSingleSavedCardHeight: NSLayoutConstraint!
104
109
  @IBOutlet weak var viewTxtFieldCVVSingleCard: TextFieldStackView!
105
110
  @IBOutlet weak var txtFieldCVVSingleSavedCard: UITextField!
106
111
  @IBOutlet weak var viewTxtFieldCVVSingleSavedCard: UIView!
@@ -119,6 +124,9 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
119
124
  @IBOutlet weak var tblViewSavedCardsList: UITableView!
120
125
  @IBOutlet weak var tblViewSavedCardListHeight: NSLayoutConstraint!
121
126
 
127
+ @IBOutlet weak var txtFieldSelectPlanSingleSavedCard: TextFieldStackView!
128
+ @IBOutlet weak var txtFieldSelectDateSingleSavedCard: TextFieldStackView!
129
+
122
130
  //Update Card
123
131
  @IBOutlet weak var btnSelectUpdateCardView: UIButton!
124
132
  @IBOutlet weak var imgViewCardUpdateCardView: UIImageView!
@@ -144,6 +152,9 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
144
152
  @IBOutlet weak var viewtxtFieldNameOnCardNewCardView: UIView!
145
153
  @IBOutlet weak var btnPayNowNewCardView: FilledButton!
146
154
  @IBOutlet weak var btnSavedCardForFutureNewCardView: CheckboxButton!
155
+ @IBOutlet weak var txtFieldSelectPlanNewCardView: TextFieldStackView!
156
+ @IBOutlet weak var txtFieldSelectDateNewCardView: TextFieldStackView!
157
+ @IBOutlet weak var heightViewNewCardFields: NSLayoutConstraint!
147
158
 
148
159
  //Bank
149
160
  @IBOutlet weak var viewBankFields: UIView!
@@ -163,6 +174,10 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
163
174
  @IBOutlet weak var btnCheckSavedAccountForFuture: UIButton!
164
175
  @IBOutlet weak var txtFieldConfirmBankAccount: UITextField!
165
176
  @IBOutlet weak var viewTextFieldConfirmAccount: UIView!
177
+ @IBOutlet weak var txtFieldSelectPlanViewBankFields: TextFieldStackView!
178
+ @IBOutlet weak var txtFieldSelectDateViewBankFields: TextFieldStackView!
179
+
180
+ @IBOutlet weak var heightViewBankFields: NSLayoutConstraint!
166
181
 
167
182
  //GrailPay
168
183
  @IBOutlet weak var grailPayBankLinkView: UIView!
@@ -211,13 +226,14 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
211
226
  @IBOutlet weak var lblAccountNumberSingleAccountView: UILabel!
212
227
  @IBOutlet weak var lblAccountTypeSingleAccountView: UILabel!
213
228
  @IBOutlet weak var btnPayNowSingleAccountView: FilledButton!
214
- // @IBOutlet weak var viewSingleAccountViewHeight: NSLayoutConstraint!
215
229
  @IBOutlet weak var viewChangedAccount: UIView!
216
230
  @IBOutlet weak var tblViewSavedBankAccounts: UITableView!
217
231
  @IBOutlet weak var tblViewSavedBankAccountsHeight: NSLayoutConstraint!
218
232
  @IBOutlet weak var bankIconImgView: UIImageView!
219
233
  @IBOutlet weak var btnChangeSingleAccountView: UIButton!
220
234
  @IBOutlet weak var viewSingelBankAccount: UIView!
235
+ @IBOutlet weak var txtFieldSelectPlanSingleSavedBankView: TextFieldStackView!
236
+ @IBOutlet weak var txtFieldSelectDateSingleSavedBankView: TextFieldStackView!
221
237
 
222
238
  //New Bank
223
239
  @IBOutlet weak var viewNewBankAccount: UIView!
@@ -236,6 +252,11 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
236
252
  @IBOutlet weak var lblSavedNewAccountForFuture: UILabel!
237
253
  @IBOutlet weak var txtFieldConfirmAccountNewAccountView: UITextField!
238
254
  @IBOutlet weak var viewTxtFieldConfirmNewAccountView: UIView!
255
+ @IBOutlet weak var txtFieldSelectPlanNewAccountView: TextFieldStackView!
256
+ @IBOutlet weak var txtFieldSelectDateNewAccountView: TextFieldStackView!
257
+
258
+ @IBOutlet weak var heightViewNewAccountFields: NSLayoutConstraint!
259
+ @IBOutlet weak var heightSubViewNewAccountFields: NSLayoutConstraint!
239
260
 
240
261
  //Crypto
241
262
  @IBOutlet weak var viewCrypto: UIView!
@@ -264,6 +285,10 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
264
285
  @IBOutlet weak var btnLogout: UIButton!
265
286
  @IBOutlet weak var settingsView: UIView!
266
287
 
288
+ @IBOutlet weak var viewTblViewRecurring: UIView!
289
+ @IBOutlet weak var heightViewTblViewRecurring: NSLayoutConstraint!
290
+ @IBOutlet weak var tblViewRecurring: UITableView!
291
+
267
292
  var chainInvoiceAddress: String?
268
293
  var lightningURI: String?
269
294
 
@@ -320,7 +345,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
320
345
  var isFrom = String()
321
346
 
322
347
  //Blink Card
323
- // var blinkCardRecognizer: MBCBlinkCardRecognizer!
348
+ // var blinkCardRecognizer: MBCBlinkCardRecognizer!
324
349
 
325
350
  // Variables for Card Scanning Data Back
326
351
  var cardNumber: String?
@@ -353,6 +378,10 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
353
378
  var selectedNewGrailPayAccountName: String?
354
379
  var grailPayNewAccountCustomerID: String?
355
380
 
381
+ // let planOptions = ["Weekly", "Monthly"]
382
+
383
+ var startDatePickerHandler: DatePickerHandler?
384
+
356
385
  //MARK: - View Did Load
357
386
  override func viewDidLoad() {
358
387
  super.viewDidLoad()
@@ -379,7 +408,6 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
379
408
  if let billingInfoData = request.billingInfoData,
380
409
  let json = try? JSONSerialization.jsonObject(with: billingInfoData, options: []),
381
410
  let jsonDict = json as? [String: Any], !jsonDict.isEmpty {
382
-
383
411
  // If `submitButtonText` is not empty, use it; otherwise, default to "Next (Billing Info)"
384
412
  let buttonText = (request?.submitButtonText?.isEmpty == false ? request!.submitButtonText! + " (Billing Info)" : "Next (Billing Info)")
385
413
 
@@ -389,7 +417,8 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
389
417
  btnPayNowSingleCard.setTitle(buttonText, for: .normal)
390
418
  btnPayNowSingleAccountView.setTitle(buttonText, for: .normal)
391
419
  } else {
392
- let amountText = String(format: "$%.2f", amount ?? 0)
420
+ let amountValue = request?.amount ?? 0
421
+ let amountText = String(format: "$%.2f", amountValue)
393
422
  let submitText = request?.submitButtonText
394
423
 
395
424
  let defaultTitle = (submitText?.isEmpty == false)
@@ -434,36 +463,6 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
434
463
 
435
464
  viewChangedAccount.isHidden = true
436
465
 
437
- tblViewAccountTypes.delegate = self
438
- tblViewAccountTypes.dataSource = self
439
- tblViewAccountTypes.showsVerticalScrollIndicator = false
440
- tblViewAccountTypes.showsHorizontalScrollIndicator = false
441
-
442
- viewAccountType.clipsToBounds = false
443
- viewAccountType.layer.shadowColor = UIColor.black.cgColor
444
- viewAccountType.layer.shadowOpacity = 0.3
445
- viewAccountType.layer.shadowOffset = CGSize(width: 0, height: 2)
446
- viewAccountType.layer.shadowRadius = 4
447
- viewAccountType.layer.cornerRadius = 8
448
- viewAccountType.layer.cornerRadius = 8
449
-
450
- viewAccountType.isHidden = true
451
-
452
- tblViewAccountTypeNewAccountView.delegate = self
453
- tblViewAccountTypeNewAccountView.dataSource = self
454
- tblViewAccountTypeNewAccountView.showsVerticalScrollIndicator = false
455
- tblViewAccountTypeNewAccountView.showsHorizontalScrollIndicator = false
456
-
457
- viewAccountTypeNewAccountView.clipsToBounds = false
458
- viewAccountTypeNewAccountView.layer.shadowColor = UIColor.black.cgColor
459
- viewAccountTypeNewAccountView.layer.shadowOpacity = 0.3
460
- viewAccountTypeNewAccountView.layer.shadowOffset = CGSize(width: 0, height: 2)
461
- viewAccountTypeNewAccountView.layer.shadowRadius = 4
462
- viewAccountTypeNewAccountView.layer.cornerRadius = 8
463
- viewAccountTypeNewAccountView.layer.cornerRadius = 8
464
-
465
- viewAccountTypeNewAccountView.isHidden = true
466
-
467
466
  // Generate and set the QR code image
468
467
  qrImageView.image = generateQRCode(from: "CryptoQR")
469
468
 
@@ -489,6 +488,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
489
488
  btnSettings.isHidden = true
490
489
  }
491
490
 
491
+ setupPlanTableView()
492
492
  }
493
493
 
494
494
  //MARK: - View Wiil Appear
@@ -524,12 +524,47 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
524
524
 
525
525
  viewTxtFieldCVVSingleCard.isHidden = true
526
526
  btnPayNowSingleCard.isHidden = true
527
- viewSingleSavedCardHeight.constant = 60
528
527
 
529
528
  self.viewCrypto.isHidden = true
530
529
 
531
- // self.viewAddNewGrailPayAccount.isHidden = true
532
- // self.viewAbandonGrailPayNewAccountView.isHidden = true
530
+ if request.enableRecurring == true {
531
+ self.txtFieldChosePlanCard.isHidden = false
532
+ self.txtFieldStartDateCard.isHidden = false
533
+ self.txtFieldSelectPlanSingleSavedCard.isHidden = false
534
+ self.txtFieldSelectDateSingleSavedCard.isHidden = false
535
+ self.txtFieldSelectPlanNewCardView.isHidden = false
536
+ self.txtFieldSelectDateNewCardView.isHidden = false
537
+ self.txtFieldSelectPlanViewBankFields.isHidden = false
538
+ self.txtFieldSelectDateViewBankFields.isHidden = false
539
+ self.txtFieldSelectPlanSingleSavedBankView.isHidden = false
540
+ self.txtFieldSelectDateSingleSavedBankView.isHidden = false
541
+ self.txtFieldSelectPlanNewAccountView.isHidden = false
542
+ self.txtFieldSelectDateNewAccountView.isHidden = false
543
+
544
+ self.heightViewBankFields.constant = 696
545
+ self.heightViewNewCardFields.constant = 624
546
+ self.heightViewNewAccountFields.constant = 808
547
+ self.heightSubViewNewAccountFields.constant = 738
548
+ }
549
+ else {
550
+ self.txtFieldChosePlanCard.isHidden = true
551
+ self.txtFieldStartDateCard.isHidden = true
552
+ self.txtFieldSelectPlanSingleSavedCard.isHidden = true
553
+ self.txtFieldSelectDateSingleSavedCard.isHidden = true
554
+ self.txtFieldSelectPlanNewCardView.isHidden = true
555
+ self.txtFieldSelectDateNewCardView.isHidden = true
556
+ self.txtFieldSelectPlanViewBankFields.isHidden = true
557
+ self.txtFieldSelectDateViewBankFields.isHidden = true
558
+ self.txtFieldSelectPlanSingleSavedBankView.isHidden = true
559
+ self.txtFieldSelectDateSingleSavedBankView.isHidden = true
560
+ self.txtFieldSelectPlanNewAccountView.isHidden = true
561
+ self.txtFieldSelectDateNewAccountView.isHidden = true
562
+
563
+ self.heightViewBankFields.constant = 506
564
+ self.heightViewNewCardFields.constant = 434
565
+ self.heightViewNewAccountFields.constant = 628
566
+ self.heightSubViewNewAccountFields.constant = 558
567
+ }
533
568
 
534
569
  if selectedPaymentMethod == "Card" {
535
570
  self.grailPayBankLinkView.isHidden = true
@@ -562,7 +597,6 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
562
597
 
563
598
  self.viewTxtFieldCVVSingleCard.isHidden = true
564
599
  self.btnPayNowSingleCard.isHidden = true
565
- self.viewSingleSavedCardHeight.constant = 60
566
600
  self.btnNext.isHidden = true
567
601
  self.btnNextHeight.constant = 0
568
602
  self.btnNextTopCon.constant = 8
@@ -575,17 +609,25 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
575
609
  if isSelectForPay {
576
610
  viewTxtFieldCVVSingleCard.isHidden = false
577
611
  btnPayNowSingleCard.isHidden = false
578
- viewSingleSavedCardHeight.constant = 220
579
612
  btnNext.isHidden = true
580
613
  btnNextHeight.constant = 0
581
614
  btnNextTopCon.constant = 0
615
+ if request.enableRecurring == true {
616
+ txtFieldSelectPlanSingleSavedCard.isHidden = false
617
+ txtFieldSelectDateSingleSavedCard.isHidden = false
618
+ }
619
+ else {
620
+ txtFieldSelectPlanSingleSavedCard.isHidden = true
621
+ txtFieldSelectDateSingleSavedCard.isHidden = true
622
+ }
582
623
  } else {
583
624
  viewTxtFieldCVVSingleCard.isHidden = true
584
625
  btnPayNowSingleCard.isHidden = true
585
- viewSingleSavedCardHeight.constant = 60
586
626
  btnNext.isHidden = true
587
627
  btnNextHeight.constant = 0
588
628
  btnNextTopCon.constant = 8
629
+ txtFieldSelectPlanSingleSavedCard.isHidden = true
630
+ txtFieldSelectDateSingleSavedCard.isHidden = true
589
631
  }
590
632
  }
591
633
  }
@@ -645,14 +687,23 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
645
687
  if self.isSelectForPayBank {
646
688
  self.viewTermAndConditionsSingleAccountView.isHidden = false
647
689
  self.btnPayNowSingleAccountView.isHidden = false
648
- // self.viewSingleAccountViewHeight.constant = 170
690
+ if request.enableRecurring == true {
691
+ self.txtFieldSelectPlanSingleSavedBankView.isHidden = false
692
+ self.txtFieldSelectDateSingleSavedBankView.isHidden = false
693
+ }
694
+ else {
695
+ self.txtFieldSelectPlanSingleSavedBankView.isHidden = true
696
+ self.txtFieldSelectDateSingleSavedBankView.isHidden = true
697
+ }
649
698
  } else {
650
699
  self.viewTermAndConditionsSingleAccountView.isHidden = true
651
700
  self.btnPayNowSingleAccountView.isHidden = true
652
- // self.viewSingleAccountViewHeight.constant = 68
653
701
  self.btnNext.isHidden = true
654
702
  self.btnNextHeight.constant = 0
655
703
  self.btnNextTopCon.constant = 0
704
+
705
+ self.txtFieldSelectPlanSingleSavedBankView.isHidden = true
706
+ self.txtFieldSelectDateSingleSavedBankView.isHidden = true
656
707
  }
657
708
 
658
709
  if request?.authenticatedACH == true {
@@ -683,8 +734,8 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
683
734
  }
684
735
  }
685
736
  else {
686
- self.viewBankFields.isHidden = false
687
- self.viewTermsAndConditions.isHidden = false
737
+ // self.viewBankFields.isHidden = false
738
+ // self.viewTermsAndConditions.isHidden = false
688
739
  self.grailPayBankLinkView.isHidden = true
689
740
  }
690
741
  }
@@ -746,6 +797,10 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
746
797
  viewContainerBackground.backgroundColor = uiColor
747
798
  viewAccountType.backgroundColor = uiColor
748
799
  tblViewAccountTypes.backgroundColor = uiColor
800
+ viewAccountTypeNewAccountView.backgroundColor = uiColor
801
+ tblViewAccountTypeNewAccountView.backgroundColor = uiColor
802
+ // viewTblViewRecurring.backgroundColor = uiColor
803
+ // tblViewRecurring.backgroundColor = uiColor
749
804
  }
750
805
 
751
806
  if let bodyBackGroundColor = UserStoreSingleton.shared.body_bg_col,
@@ -907,6 +962,9 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
907
962
  lblGrailPayAgreeTo.textColor = placeholderColor
908
963
  lblGrailPayNewAccountSaveForFuture.textColor = placeholderColor
909
964
  lblIagreeGrailPayNewAccountView.textColor = placeholderColor
965
+
966
+ imgViewChosePlanCardDropIcon.tintColor = placeholderColor
967
+ imgViewCalenderIconCard.tintColor = placeholderColor
910
968
  }
911
969
 
912
970
  if let primaryFontColor = UserStoreSingleton.shared.primary_font_col,
@@ -999,9 +1057,9 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
999
1057
  subLblSavedInfoOTPView.font = UIFont.systemFont(ofSize: fontSize)
1000
1058
  subLblChangeCard.font = UIFont.systemFont(ofSize: fontSize)
1001
1059
  subLblUpdateCard.font = UIFont.systemFont(ofSize: fontSize)
1002
- lblCreateNewCard.font = UIFont.systemFont(ofSize: fontSize)
1060
+ lblCreateNewCard.font = UIFont.systemFont(ofSize: fontSize, weight: .semibold)
1003
1061
  subLblChangeAccount.font = UIFont.systemFont(ofSize: fontSize)
1004
- lblCreateNewAccount.font = UIFont.systemFont(ofSize: fontSize)
1062
+ lblCreateNewAccount.font = UIFont.systemFont(ofSize: fontSize, weight: .semibold)
1005
1063
  lblEasyMerchantOne.font = UIFont.systemFont(ofSize: fontSize)
1006
1064
  lblTimerCrypto.font = UIFont.systemFont(ofSize: fontSize)
1007
1065
  lblUntillPriceChange.font = UIFont.systemFont(ofSize: fontSize)
@@ -1395,6 +1453,141 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
1395
1453
  cryptoInfoTimer = nil
1396
1454
  }
1397
1455
 
1456
+ func setupPlanTableView() {
1457
+ tblViewAccountTypes.delegate = self
1458
+ tblViewAccountTypes.dataSource = self
1459
+ tblViewAccountTypes.showsVerticalScrollIndicator = false
1460
+ tblViewAccountTypes.showsHorizontalScrollIndicator = false
1461
+
1462
+ viewAccountType.clipsToBounds = false
1463
+ viewAccountType.layer.shadowColor = UIColor.black.cgColor
1464
+ viewAccountType.layer.shadowOpacity = 0.3
1465
+ viewAccountType.layer.shadowOffset = CGSize(width: 0, height: 2)
1466
+ viewAccountType.layer.shadowRadius = 4
1467
+ viewAccountType.layer.cornerRadius = 8
1468
+ viewAccountType.layer.cornerRadius = 8
1469
+
1470
+ viewAccountType.isHidden = true
1471
+
1472
+ tblViewAccountTypeNewAccountView.delegate = self
1473
+ tblViewAccountTypeNewAccountView.dataSource = self
1474
+ tblViewAccountTypeNewAccountView.showsVerticalScrollIndicator = false
1475
+ tblViewAccountTypeNewAccountView.showsHorizontalScrollIndicator = false
1476
+
1477
+ viewAccountTypeNewAccountView.clipsToBounds = false
1478
+ viewAccountTypeNewAccountView.layer.shadowColor = UIColor.black.cgColor
1479
+ viewAccountTypeNewAccountView.layer.shadowOpacity = 0.3
1480
+ viewAccountTypeNewAccountView.layer.shadowOffset = CGSize(width: 0, height: 2)
1481
+ viewAccountTypeNewAccountView.layer.shadowRadius = 4
1482
+ viewAccountTypeNewAccountView.layer.cornerRadius = 8
1483
+ viewAccountTypeNewAccountView.layer.cornerRadius = 8
1484
+
1485
+ viewAccountTypeNewAccountView.isHidden = true
1486
+
1487
+ // tblViewRecurring.delegate = self
1488
+ // tblViewRecurring.dataSource = self
1489
+ // tblViewRecurring.showsVerticalScrollIndicator = false
1490
+ // tblViewRecurring.showsHorizontalScrollIndicator = false
1491
+ //
1492
+ // viewTblViewRecurring.clipsToBounds = false
1493
+ // viewTblViewRecurring.layer.shadowColor = UIColor.black.cgColor
1494
+ // viewTblViewRecurring.layer.shadowOpacity = 0.3
1495
+ // viewTblViewRecurring.layer.shadowOffset = CGSize(width: 0, height: 2)
1496
+ // viewTblViewRecurring.layer.shadowRadius = 4
1497
+ // viewTblViewRecurring.layer.cornerRadius = 8
1498
+ // viewTblViewRecurring.layer.cornerRadius = 8
1499
+ //
1500
+ // viewTblViewRecurring.isHidden = true
1501
+ }
1502
+
1503
+ @IBAction func actionBtnChosePlanCardField(_ sender: UIButton) {
1504
+ // UIView.animate(withDuration: 0.3) {
1505
+ // self.viewTblViewRecurring.isHidden.toggle()
1506
+ // }
1507
+
1508
+ PlanSelector.presentPlanOptions(from: self, sourceView: sender) { selectedPlan in
1509
+ self.txtFieldChosePlanCard.text = selectedPlan
1510
+ }
1511
+ }
1512
+
1513
+ @IBAction func actionBtnStartDateCardField(_ sender: UIButton) {
1514
+ startDatePickerHandler = DatePickerHandler(textField: txtFieldStartDateCard.textField)
1515
+ startDatePickerHandler?.onDateSelected = { selectedDate in
1516
+
1517
+ }
1518
+ txtFieldStartDateCard.textField.becomeFirstResponder()
1519
+ }
1520
+
1521
+ @IBAction func actionBtnSelectPlanSingleSavedCard(_ sender: UIButton) {
1522
+ PlanSelector.presentPlanOptions(from: self, sourceView: sender) { selectedPlan in
1523
+ self.txtFieldSelectPlanSingleSavedCard.text = selectedPlan
1524
+ }
1525
+ }
1526
+
1527
+ @IBAction func actionBtnSelectDateSingleSavedCard(_ sender: UIButton) {
1528
+ startDatePickerHandler = DatePickerHandler(textField: txtFieldSelectDateSingleSavedCard.textField)
1529
+ startDatePickerHandler?.onDateSelected = { selectedDate in
1530
+
1531
+ }
1532
+ txtFieldSelectDateSingleSavedCard.textField.becomeFirstResponder()
1533
+ }
1534
+
1535
+ @IBAction func actionBtnSelectPlanNewCardView(_ sender: UIButton) {
1536
+ PlanSelector.presentPlanOptions(from: self, sourceView: sender) { selectedPlan in
1537
+ self.txtFieldSelectPlanNewCardView.text = selectedPlan
1538
+ }
1539
+ }
1540
+
1541
+ @IBAction func actionBtnSelectDateNewCardView(_ sender: UIButton) {
1542
+ startDatePickerHandler = DatePickerHandler(textField: txtFieldSelectDateNewCardView.textField)
1543
+ startDatePickerHandler?.onDateSelected = { selectedDate in
1544
+
1545
+ }
1546
+ txtFieldSelectDateNewCardView.textField.becomeFirstResponder()
1547
+ }
1548
+
1549
+ @IBAction func actionBtnSelectPlanViewBankFields(_ sender: UIButton) {
1550
+ PlanSelector.presentPlanOptions(from: self, sourceView: sender) { selectedPlan in
1551
+ self.txtFieldSelectPlanViewBankFields.text = selectedPlan
1552
+ }
1553
+ }
1554
+
1555
+ @IBAction func actionBtnSelectDateViewBankFields(_ sender: UIButton) {
1556
+ startDatePickerHandler = DatePickerHandler(textField: txtFieldSelectDateViewBankFields.textField)
1557
+ startDatePickerHandler?.onDateSelected = { selectedDate in
1558
+
1559
+ }
1560
+ txtFieldSelectDateViewBankFields.textField.becomeFirstResponder()
1561
+ }
1562
+
1563
+ @IBAction func actionBtnSelectPlanSingleSavedAccount(_ sender: UIButton) {
1564
+ PlanSelector.presentPlanOptions(from: self, sourceView: sender) { selectedPlan in
1565
+ self.txtFieldSelectPlanSingleSavedBankView.text = selectedPlan
1566
+ }
1567
+ }
1568
+
1569
+ @IBAction func actionBtnSelectDateSingleSavedAccount(_ sender: UIButton) {
1570
+ startDatePickerHandler = DatePickerHandler(textField: txtFieldSelectDateSingleSavedBankView.textField)
1571
+ startDatePickerHandler?.onDateSelected = { selectedDate in
1572
+
1573
+ }
1574
+ txtFieldSelectDateSingleSavedBankView.textField.becomeFirstResponder()
1575
+ }
1576
+
1577
+ @IBAction func actionBtnSelectPlanNewAccountView(_ sender: UIButton) {
1578
+ PlanSelector.presentPlanOptions(from: self, sourceView: sender) { selectedPlan in
1579
+ self.txtFieldSelectPlanNewAccountView.text = selectedPlan
1580
+ }
1581
+ }
1582
+
1583
+ @IBAction func actionBtnSelectDateNewAccountView(_ sender: UIButton) {
1584
+ startDatePickerHandler = DatePickerHandler(textField: txtFieldSelectDateNewAccountView.textField)
1585
+ startDatePickerHandler?.onDateSelected = { selectedDate in
1586
+
1587
+ }
1588
+ txtFieldSelectDateNewAccountView.textField.becomeFirstResponder()
1589
+ }
1590
+
1398
1591
  @IBAction func actionBtnClose(_ sender: UIButton) {
1399
1592
  UserStoreSingleton.shared.clearUserData()
1400
1593
  UserStoreSingleton.shared.isLoggedIn = false
@@ -1427,30 +1620,28 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
1427
1620
  }
1428
1621
 
1429
1622
  @IBAction func actionBtnSelectSingleSavedCard(_ sender: UIButton) {
1430
- // Toggle the boolean property
1623
+ // Toggle selection state
1431
1624
  isSelectForPay.toggle()
1432
- // Update the button image based on the state
1625
+
1626
+ // Update button image
1433
1627
  let imageName = isSelectForPay ? "circle.inset.filled" : "circle"
1434
1628
  sender.setImage(UIImage(systemName: imageName), for: .normal)
1435
- // Show or hide the view based on the state
1436
- if isSelectForPay {
1437
- viewTxtFieldCVVSingleCard.isHidden = false
1438
- btnPayNowSingleCard.isHidden = false
1439
- viewSingleSavedCardHeight.constant = 220
1440
- btnNext.isHidden = true
1441
- btnNextHeight.constant = 0
1442
- btnNextTopCon.constant = 0
1443
- if let firstCard = savedCards.first {
1444
- // Update the selectedCard to the firstCard or the card that is currently selected
1445
- selectedCard = firstCard
1446
- }
1447
- } else {
1448
- viewTxtFieldCVVSingleCard.isHidden = true
1449
- btnPayNowSingleCard.isHidden = true
1450
- viewSingleSavedCardHeight.constant = 60
1451
- btnNext.isHidden = true
1452
- btnNextHeight.constant = 0
1453
- btnNextTopCon.constant = 8
1629
+
1630
+ // Show/hide UI based on selection
1631
+ viewTxtFieldCVVSingleCard.isHidden = !isSelectForPay
1632
+ btnPayNowSingleCard.isHidden = !isSelectForPay
1633
+ btnNext.isHidden = true
1634
+ btnNextHeight.constant = 0
1635
+ btnNextTopCon.constant = isSelectForPay ? 0 : 8
1636
+
1637
+ // Handle recurring fields visibility
1638
+ let showRecurringFields = isSelectForPay && request.enableRecurring == true
1639
+ txtFieldSelectPlanSingleSavedCard.isHidden = !showRecurringFields
1640
+ txtFieldSelectDateSingleSavedCard.isHidden = !showRecurringFields
1641
+
1642
+ // Set selected card
1643
+ if isSelectForPay, let firstCard = savedCards.first {
1644
+ selectedCard = firstCard
1454
1645
  }
1455
1646
  }
1456
1647
 
@@ -1826,7 +2017,13 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
1826
2017
  print("❌ JSON Parsing Error: \(error)")
1827
2018
  }
1828
2019
  } else {
1829
- print("❌ HTTP Status Code: \(httpResponse.statusCode)")
2020
+ if let data = data,
2021
+ let responseObj = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
2022
+ let message = responseObj["message"] as? String {
2023
+ self.presentPaymentErrorVC(errorMessage: message)
2024
+ } else {
2025
+ self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
2026
+ }
1830
2027
  }
1831
2028
  }
1832
2029
 
@@ -1965,7 +2162,13 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
1965
2162
  print("❌ JSON Parsing Error: \(error)")
1966
2163
  }
1967
2164
  } else {
1968
- print("❌ HTTP Status Code: \(httpResponse.statusCode)")
2165
+ if let data = data,
2166
+ let responseObj = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
2167
+ let message = responseObj["message"] as? String {
2168
+ self.presentPaymentErrorVC(errorMessage: message)
2169
+ } else {
2170
+ self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
2171
+ }
1969
2172
  }
1970
2173
  }
1971
2174
 
@@ -2198,7 +2401,13 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
2198
2401
  self.presentPaymentErrorVC(errorMessage: "No data received")
2199
2402
  }
2200
2403
  } else {
2201
- self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
2404
+ if let data = serviceData,
2405
+ let responseObj = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
2406
+ let message = responseObj["message"] as? String {
2407
+ self.presentPaymentErrorVC(errorMessage: message)
2408
+ } else {
2409
+ self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
2410
+ }
2202
2411
  }
2203
2412
  }
2204
2413
  task.resume()
@@ -2300,7 +2509,13 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
2300
2509
  self.presentPaymentErrorVC(errorMessage: "No data received")
2301
2510
  }
2302
2511
  } else {
2303
- self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
2512
+ if let data = serviceData,
2513
+ let responseObj = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
2514
+ let message = responseObj["message"] as? String {
2515
+ self.presentPaymentErrorVC(errorMessage: message)
2516
+ } else {
2517
+ self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
2518
+ }
2304
2519
  }
2305
2520
  }
2306
2521
  task.resume()
@@ -2404,7 +2619,13 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
2404
2619
  self.presentPaymentErrorVC(errorMessage: "No data received")
2405
2620
  }
2406
2621
  } else {
2407
- self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
2622
+ if let data = serviceData,
2623
+ let responseObj = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
2624
+ let message = responseObj["message"] as? String {
2625
+ self.presentPaymentErrorVC(errorMessage: message)
2626
+ } else {
2627
+ self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
2628
+ }
2408
2629
  }
2409
2630
  }
2410
2631
  task.resume()
@@ -2506,7 +2727,13 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
2506
2727
  self.presentPaymentErrorVC(errorMessage: "No data received")
2507
2728
  }
2508
2729
  } else {
2509
- self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
2730
+ if let data = serviceData,
2731
+ let responseObj = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
2732
+ let message = responseObj["message"] as? String {
2733
+ self.presentPaymentErrorVC(errorMessage: message)
2734
+ } else {
2735
+ self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
2736
+ }
2510
2737
  }
2511
2738
  }
2512
2739
  task.resume()
@@ -2814,21 +3041,31 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
2814
3041
  @IBAction func actionBtnSelectSingleAccountView(_ sender: UIButton) {
2815
3042
  // Toggle the boolean property
2816
3043
  isSelectForPayBank.toggle()
2817
- // Update the button image based on the state
3044
+
3045
+ // Update the button image based on the toggle state
2818
3046
  let imageName = isSelectForPayBank ? "circle.inset.filled" : "circle"
2819
3047
  sender.setImage(UIImage(systemName: imageName), for: .normal)
2820
- // Show or hide the view based on the state
3048
+
3049
+ // Update UI based on selection
3050
+ viewTermAndConditionsSingleAccountView.isHidden = !isSelectForPayBank
3051
+ btnPayNowSingleAccountView.isHidden = !isSelectForPayBank
3052
+
2821
3053
  if isSelectForPayBank {
2822
- viewTermAndConditionsSingleAccountView.isHidden = false
2823
- btnPayNowSingleAccountView.isHidden = false
2824
- // viewSingleAccountViewHeight.constant = 170
3054
+ // Show or hide recurring plan fields based on request.enableRecurring
3055
+ if request?.enableRecurring == true {
3056
+ txtFieldSelectPlanSingleSavedBankView.isHidden = false
3057
+ txtFieldSelectDateSingleSavedBankView.isHidden = false
3058
+ } else {
3059
+ txtFieldSelectPlanSingleSavedBankView.isHidden = true
3060
+ txtFieldSelectDateSingleSavedBankView.isHidden = true
3061
+ }
2825
3062
  } else {
2826
- viewTermAndConditionsSingleAccountView.isHidden = true
2827
- btnPayNowSingleAccountView.isHidden = true
2828
- // viewSingleAccountViewHeight.constant = 68
3063
+ // Hide all related fields if not selected
2829
3064
  btnNext.isHidden = true
2830
3065
  btnNextHeight.constant = 0
2831
3066
  btnNextTopCon.constant = 0
3067
+ txtFieldSelectPlanSingleSavedBankView.isHidden = true
3068
+ txtFieldSelectDateSingleSavedBankView.isHidden = true
2832
3069
  }
2833
3070
  }
2834
3071
 
@@ -2847,6 +3084,11 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
2847
3084
 
2848
3085
  @IBAction func actionBtnPayNowSingleAccountView(_ sender: UIButton) {
2849
3086
  if request.authenticatedACH == true {
3087
+ // Check if the terms and conditions are agreed
3088
+ if !agreeTermsAndCondtition {
3089
+ showAlert(title: "Terms and Conditions", message: "Please agree to the terms and conditions")
3090
+ return
3091
+ }
2850
3092
  grailPayAaccountChargeSingleSavedAccountApi()
2851
3093
  } else {
2852
3094
  // Check if billingInfoData is not nil or empty
@@ -3040,11 +3282,9 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
3040
3282
  let primaryUIColor = UIColor(hex: primaryBtnBackGroundColor),
3041
3283
  let secondaryBtnBackgroundColor = UserStoreSingleton.shared.primary_btn_font_col,
3042
3284
  let secondaryUIColor = UIColor(hex: secondaryBtnBackgroundColor) {
3043
-
3044
3285
  // Set the selected state for OnChain button
3045
3286
  btnLightning.backgroundColor = primaryUIColor
3046
3287
  btnLightning.setTitleColor(secondaryUIColor, for: .normal)
3047
-
3048
3288
  // Reset the state for Lightning button
3049
3289
  btnOnChain.backgroundColor = .clear
3050
3290
  btnOnChain.setTitleColor(primaryUIColor, for: .normal)
@@ -3057,7 +3297,6 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
3057
3297
  btnOnChain.backgroundColor = .clear
3058
3298
  btnOnChain.setTitleColor(.systemBlue, for: .normal)
3059
3299
  }
3060
-
3061
3300
  // Generate QR code for Lightning URI
3062
3301
  if let uri = lightningURI {
3063
3302
  qrImageView.image = generateQRCode(from: uri)
@@ -3071,18 +3310,14 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
3071
3310
  print("No address to copy")
3072
3311
  return
3073
3312
  }
3074
-
3075
3313
  // Extract the actual BTC address from the label text
3076
3314
  let components = btcAddressText.components(separatedBy: "BTC Address: ")
3077
3315
  if components.count > 1 {
3078
3316
  let btcAddress = components[1]
3079
-
3080
3317
  // Copy the address to the clipboard
3081
3318
  UIPasteboard.general.string = btcAddress
3082
-
3083
3319
  // Print success message to the console
3084
3320
  print("Address copied to clipboard successfully: \(btcAddress)")
3085
-
3086
3321
  // Optionally, show a toast message to the user
3087
3322
  showToast(message: "BTC Address copied to clipboard")
3088
3323
  }
@@ -3230,19 +3465,19 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
3230
3465
  return
3231
3466
  }
3232
3467
 
3233
- var request = URLRequest(url: serviceURL)
3234
- request.httpMethod = "POST"
3235
- request.addValue("application/json", forHTTPHeaderField: "Content-Type")
3468
+ var urlRequest = URLRequest(url: serviceURL)
3469
+ urlRequest.httpMethod = "POST"
3470
+ urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
3236
3471
 
3237
3472
  let token = UserStoreSingleton.shared.clientToken
3238
3473
  print("Setting clientToken header: \(token ?? "None")")
3239
- request.addValue(token ?? "", forHTTPHeaderField: "Client-Token")
3474
+ urlRequest.addValue(token ?? "", forHTTPHeaderField: "Client-Token")
3240
3475
 
3241
3476
  // Add API headers
3242
3477
  if let apiKey = EnvironmentConfig.apiKey,
3243
3478
  let apiSecret = EnvironmentConfig.apiSecret {
3244
- request.addValue(apiKey, forHTTPHeaderField: "x-api-key")
3245
- request.addValue(apiSecret, forHTTPHeaderField: "x-api-secret")
3479
+ urlRequest.addValue(apiKey, forHTTPHeaderField: "x-api-key")
3480
+ urlRequest.addValue(apiSecret, forHTTPHeaderField: "x-api-secret")
3246
3481
  }
3247
3482
 
3248
3483
  // ✅ Safe access from main thread (assumes you call this from main thread)
@@ -3257,7 +3492,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
3257
3492
 
3258
3493
  do {
3259
3494
  let jsonData = try JSONSerialization.data(withJSONObject: params, options: .prettyPrinted)
3260
- request.httpBody = jsonData
3495
+ urlRequest.httpBody = jsonData
3261
3496
  if let jsonString = String(data: jsonData, encoding: .utf8) {
3262
3497
  print("JSON Payload: \(jsonString)")
3263
3498
  }
@@ -3267,7 +3502,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
3267
3502
  return
3268
3503
  }
3269
3504
 
3270
- let task = URLSession.shared.dataTask(with: request) { serviceData, serviceResponse, error in
3505
+ let task = URLSession.shared.dataTask(with: urlRequest) { serviceData, serviceResponse, error in
3271
3506
 
3272
3507
  DispatchQueue.main.async {
3273
3508
  self.hideLoadingIndicator()
@@ -3339,11 +3574,17 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
3339
3574
 
3340
3575
  self.viewTxtFieldCVVSingleCard.isHidden = true
3341
3576
  self.btnPayNowSingleCard.isHidden = true
3342
- self.viewSingleSavedCardHeight.constant = 60
3343
3577
  self.btnNext.isHidden = true
3344
3578
  self.btnNextHeight.constant = 0
3345
3579
  self.btnNextTopCon.constant = 8
3346
3580
  }
3581
+
3582
+ self.txtFieldSelectPlanSingleSavedCard.isHidden = true
3583
+ self.txtFieldSelectDateSingleSavedCard.isHidden = true
3584
+
3585
+ self.txtFieldSelectPlanSingleSavedBankView.isHidden = true
3586
+ self.txtFieldSelectDateSingleSavedBankView.isHidden = true
3587
+
3347
3588
  } else if self.selectedPaymentMethod == "Bank" {
3348
3589
  self.getShowBankAccountsApi()
3349
3590
  }
@@ -3357,59 +3598,78 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
3357
3598
  }
3358
3599
 
3359
3600
  } else {
3360
- print("HTTP Status Code: \(httpResponse.statusCode)")
3601
+ if let data = serviceData,
3602
+ let responseObj = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
3603
+ let message = responseObj["message"] as? String {
3604
+ self.presentPaymentErrorVC(errorMessage: message)
3605
+ } else {
3606
+ self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
3607
+ }
3361
3608
  }
3362
3609
  }
3363
3610
 
3364
3611
  task.resume()
3365
3612
  }
3366
3613
 
3367
- //MARK: - GET Show Cards API
3614
+ // MARK: - GET Show Cards API
3368
3615
  func getShowCardsApi() {
3369
3616
  showLoadingIndicator()
3370
-
3617
+
3371
3618
  let fullURL = EnvironmentConfig.baseURL + EnvironmentConfig.Endpoints.getCards.path()
3372
-
3619
+
3373
3620
  guard let serviceURL = URL(string: fullURL) else {
3374
- print("Invalid URL")
3621
+ print("Invalid URL: \(fullURL)")
3375
3622
  hideLoadingIndicator()
3376
3623
  return
3377
3624
  }
3378
-
3625
+
3379
3626
  var request = URLRequest(url: serviceURL)
3380
3627
  request.httpMethod = "GET"
3381
3628
  request.addValue("application/json", forHTTPHeaderField: "Content-Type")
3382
-
3629
+
3383
3630
  let token = UserStoreSingleton.shared.customerToken
3384
- print("Setting customerToken header: \(token ?? "None")")
3631
+ print("🔑 Setting customerToken header: \(token ?? "None")")
3385
3632
  request.addValue(token ?? "", forHTTPHeaderField: "Customer-Token")
3386
-
3633
+
3387
3634
  // Add API headers
3388
3635
  if let apiKey = EnvironmentConfig.apiKey,
3389
3636
  let apiSecret = EnvironmentConfig.apiSecret {
3390
3637
  request.addValue(apiKey, forHTTPHeaderField: "x-api-key")
3391
3638
  request.addValue(apiSecret, forHTTPHeaderField: "x-api-secret")
3392
3639
  }
3393
-
3640
+
3394
3641
  let session = URLSession.shared
3395
3642
  let task = session.dataTask(with: request) { [weak self] (data, response, error) in
3396
3643
  guard let self = self else { return }
3397
-
3644
+
3398
3645
  DispatchQueue.main.async {
3399
- self.hideLoadingIndicator() // Stop loader when response is received
3646
+ self.hideLoadingIndicator()
3400
3647
  }
3401
-
3648
+
3402
3649
  if let error = error {
3403
- print("Error: \(error.localizedDescription)")
3650
+ print("Error in getShowCardsApi: \(error.localizedDescription)")
3651
+ if let httpResponse = response as? HTTPURLResponse {
3652
+ print("📡 HTTP Status Code: \(httpResponse.statusCode)")
3653
+ }
3404
3654
  return
3405
3655
  }
3406
-
3407
- guard let data = data else { return }
3408
-
3656
+
3657
+ guard let data = data else {
3658
+ print("❌ No data received in getShowCardsApi.")
3659
+ return
3660
+ }
3661
+
3409
3662
  do {
3663
+ // Print raw JSON string for inspection
3664
+ if let rawJSON = String(data: data, encoding: .utf8) {
3665
+ print("📦 Raw JSON Response:\n\(rawJSON)")
3666
+ }
3667
+
3410
3668
  if let jsonResponse = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
3411
3669
  let cards = jsonResponse["Cards"] as? [[String: Any]] {
3412
-
3670
+
3671
+ print("✅ Parsed JSON Response:\n\(jsonResponse)")
3672
+
3413
3673
  // Map JSON response to CardModel array
3414
3674
  self.savedCards = cards.compactMap { cardDict in
3415
3675
  return CardModel(
@@ -3423,17 +3683,58 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
3423
3683
  )
3424
3684
  }
3425
3685
 
3686
+ print("💳 Saved Cards:")
3687
+ self.savedCards.forEach { card in
3688
+ print("""
3689
+ --------------------------
3690
+ Card Brand: \(card.cardBrandName)
3691
+ Card ID: \(card.cardId)
3692
+ Card Type: \(card.cardType)
3693
+ Last 4: ****\(card.ccLast4)
3694
+ Expiry: \(card.ccValidThru)
3695
+ Customer ID: \(card.customerId)
3696
+ Is Default: \(card.isDefault)
3697
+ --------------------------
3698
+ """)
3699
+ }
3700
+
3426
3701
  DispatchQueue.main.async {
3427
3702
  if let firstCard = self.savedCards.first {
3428
3703
  self.lblCardNumberSigleSavedCard.text = "****\(firstCard.ccLast4)"
3429
3704
  self.lblExpireDateSingelSavedCard.text = "Expiry: \(firstCard.ccValidThru)"
3430
3705
  }
3431
-
3706
+
3432
3707
  self.tblViewSavedCardsList.reloadData()
3708
+
3709
+ if self.isSelectForPay {
3710
+ self.viewTxtFieldCVVSingleCard.isHidden = false
3711
+ self.btnPayNowSingleCard.isHidden = false
3712
+ self.btnNext.isHidden = true
3713
+ self.btnNextHeight.constant = 0
3714
+ self.btnNextTopCon.constant = 0
3715
+
3716
+ if self.request.enableRecurring == true {
3717
+ self.txtFieldSelectPlanSingleSavedCard.isHidden = false
3718
+ self.txtFieldSelectDateSingleSavedCard.isHidden = false
3719
+ } else {
3720
+ self.txtFieldSelectPlanSingleSavedCard.isHidden = true
3721
+ self.txtFieldSelectDateSingleSavedCard.isHidden = true
3722
+ }
3723
+ } else {
3724
+ self.viewTxtFieldCVVSingleCard.isHidden = true
3725
+ self.btnPayNowSingleCard.isHidden = true
3726
+ self.btnNext.isHidden = true
3727
+ self.btnNextHeight.constant = 0
3728
+ self.btnNextTopCon.constant = 8
3729
+ self.txtFieldSelectPlanSingleSavedCard.isHidden = true
3730
+ self.txtFieldSelectDateSingleSavedCard.isHidden = true
3731
+ }
3433
3732
  }
3733
+ } else {
3734
+ print("⚠️ JSON structure unexpected or 'Cards' key missing")
3434
3735
  }
3435
3736
  } catch {
3436
- print("Failed to parse response: \(error.localizedDescription)")
3737
+ print(" JSON parsing failed: \(error.localizedDescription)")
3437
3738
  }
3438
3739
  }
3439
3740
  task.resume()
@@ -3538,91 +3839,100 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
3538
3839
  self.presentPaymentErrorVC(errorMessage: "No data received")
3539
3840
  }
3540
3841
  } else {
3541
- self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
3842
+ if let data = serviceData,
3843
+ let responseObj = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
3844
+ let message = responseObj["message"] as? String {
3845
+ self.presentPaymentErrorVC(errorMessage: message)
3846
+ } else {
3847
+ self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
3848
+ }
3542
3849
  }
3543
3850
  }
3544
3851
  task.resume()
3545
3852
  }
3546
3853
 
3547
- // MARK: - Credit Card Charge Api from Saved cards If Billing info is nil and if Logged in.
3854
+ // MARK: - Credit Card Charge API (Saved Cards, No Billing Info, Logged In)
3548
3855
  func paymentIntentFromShowSavedCardApi() {
3549
3856
  showLoadingIndicator()
3550
-
3857
+
3551
3858
  let fullURL = EnvironmentConfig.baseURL + EnvironmentConfig.Endpoints.creditCharges.path()
3552
-
3859
+
3553
3860
  guard let serviceURL = URL(string: fullURL) else {
3554
3861
  print("Invalid URL")
3555
3862
  hideLoadingIndicator()
3556
3863
  return
3557
3864
  }
3558
-
3865
+
3559
3866
  var request = URLRequest(url: serviceURL)
3560
3867
  request.httpMethod = "POST"
3561
3868
  request.addValue("application/json", forHTTPHeaderField: "Content-Type")
3562
-
3869
+
3870
+ // Add client token
3563
3871
  let token = UserStoreSingleton.shared.clientToken
3564
3872
  print("Setting clientToken header: \(token ?? "None")")
3565
3873
  request.addValue(token ?? "", forHTTPHeaderField: "Client-Token")
3566
-
3874
+
3567
3875
  // Add API headers
3568
3876
  if let apiKey = EnvironmentConfig.apiKey,
3569
3877
  let apiSecret = EnvironmentConfig.apiSecret {
3570
3878
  request.addValue(apiKey, forHTTPHeaderField: "x-api-key")
3571
3879
  request.addValue(apiSecret, forHTTPHeaderField: "x-api-secret")
3572
3880
  }
3573
-
3574
- // Prepare parameters for the API request
3881
+
3882
+ // Prepare parameters
3883
+ let email = UserStoreSingleton.shared.verificationEmail ?? ""
3884
+ let namePart = email.split(separator: "@").first.map(String.init) ?? ""
3885
+
3575
3886
  let params: [String: Any] = [
3576
- "name": UserStoreSingleton.shared.verificationEmail?.split(separator: "@").first ?? "",
3577
- "email": UserStoreSingleton.shared.verificationEmail ?? "",
3887
+ "name": namePart,
3888
+ "email": email,
3578
3889
  "description": "TestDescription",
3579
3890
  "currency": "usd",
3580
3891
  "payment_method": "card",
3581
3892
  "save_card": 0,
3582
- "customer": selectedCard?.customerId ?? "", // Use the selectedCard's customerId
3583
- "card_id": selectedCard?.cardId ?? "", // Use the selectedCard's cardId
3584
- "cvc": txtFieldCVVSingleSavedCard.text ?? "",
3893
+ "customer": selectedCard?.customerId ?? "",
3894
+ "card_id": selectedCard?.cardId ?? "",
3895
+ "cvc": txtFieldCVVSingleSavedCard.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "",
3585
3896
  "customer_id": selectedCard?.customerId ?? ""
3586
3897
  ]
3587
-
3588
- print(params)
3589
-
3898
+
3899
+ print("Request Params: \(params)")
3900
+
3590
3901
  do {
3591
3902
  let jsonData = try JSONSerialization.data(withJSONObject: params, options: .prettyPrinted)
3592
3903
  request.httpBody = jsonData
3904
+
3593
3905
  if let jsonString = String(data: jsonData, encoding: .utf8) {
3594
3906
  print("JSON Payload: \(jsonString)")
3595
3907
  }
3596
- } catch let error {
3908
+ } catch {
3597
3909
  print("Error creating JSON data: \(error)")
3598
3910
  hideLoadingIndicator()
3599
3911
  return
3600
3912
  }
3601
-
3602
- let session = URLSession.shared
3603
- let task = session.dataTask(with: request) { (serviceData, serviceResponse, error) in
3604
-
3913
+
3914
+ // API Call
3915
+ let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
3605
3916
  DispatchQueue.main.async {
3606
- self.hideLoadingIndicator() // Stop loader when response is received
3917
+ self.hideLoadingIndicator()
3607
3918
  }
3608
-
3919
+
3609
3920
  if let error = error {
3610
3921
  print("Error: \(error.localizedDescription)")
3611
3922
  return
3612
3923
  }
3613
-
3614
- guard let httpResponse = serviceResponse as? HTTPURLResponse else {
3924
+
3925
+ guard let httpResponse = response as? HTTPURLResponse else {
3615
3926
  print("Invalid response")
3616
3927
  return
3617
3928
  }
3618
-
3929
+
3619
3930
  if httpResponse.statusCode == 200 || httpResponse.statusCode == 201 {
3620
- if let data = serviceData {
3931
+ if let data = data {
3621
3932
  do {
3622
3933
  if let responseObject = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
3623
3934
  print("Response Data: \(responseObject)")
3624
-
3625
- // Check if status is 0 and handle the error
3935
+
3626
3936
  if let status = responseObject["status"] as? Int, status == 0 {
3627
3937
  let errorMessage = responseObject["message"] as? String ?? "Unknown error"
3628
3938
  self.presentPaymentErrorVC(errorMessage: errorMessage)
@@ -3639,14 +3949,20 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
3639
3949
  } else {
3640
3950
  self.presentPaymentErrorVC(errorMessage: "Invalid JSON format")
3641
3951
  }
3642
- } catch let jsonError {
3643
- self.presentPaymentErrorVC(errorMessage: "Error parsing JSON: \(jsonError)")
3952
+ } catch {
3953
+ self.presentPaymentErrorVC(errorMessage: "Error parsing JSON: \(error)")
3644
3954
  }
3645
3955
  } else {
3646
3956
  self.presentPaymentErrorVC(errorMessage: "No data received")
3647
3957
  }
3648
3958
  } else {
3649
- self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
3959
+ if let data = data,
3960
+ let responseObj = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
3961
+ let message = responseObj["message"] as? String {
3962
+ self.presentPaymentErrorVC(errorMessage: message)
3963
+ } else {
3964
+ self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
3965
+ }
3650
3966
  }
3651
3967
  }
3652
3968
  task.resume()
@@ -3818,7 +4134,13 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
3818
4134
  self.presentPaymentErrorVC(errorMessage: "No data received")
3819
4135
  }
3820
4136
  } else {
3821
- self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
4137
+ if let data = serviceData,
4138
+ let responseObj = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
4139
+ let message = responseObj["message"] as? String {
4140
+ self.presentPaymentErrorVC(errorMessage: message)
4141
+ } else {
4142
+ self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
4143
+ }
3822
4144
  }
3823
4145
  }
3824
4146
  task.resume()
@@ -3975,7 +4297,13 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
3975
4297
  self.presentPaymentErrorVC(errorMessage: "No data received")
3976
4298
  }
3977
4299
  } else {
3978
- self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
4300
+ if let data = serviceData,
4301
+ let responseObj = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
4302
+ let message = responseObj["message"] as? String {
4303
+ self.presentPaymentErrorVC(errorMessage: message)
4304
+ } else {
4305
+ self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
4306
+ }
3979
4307
  }
3980
4308
  }
3981
4309
  task.resume()
@@ -4049,7 +4377,13 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
4049
4377
  }
4050
4378
  } else {
4051
4379
  DispatchQueue.main.async {
4052
- self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
4380
+ if let data = serviceData,
4381
+ let responseObj = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
4382
+ let message = responseObj["message"] as? String {
4383
+ self.presentPaymentErrorVC(errorMessage: message)
4384
+ } else {
4385
+ self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
4386
+ }
4053
4387
  }
4054
4388
  }
4055
4389
  }
@@ -4169,17 +4503,30 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
4169
4503
  if self.isSelectForPayBank {
4170
4504
  self.viewTermAndConditionsSingleAccountView.isHidden = false
4171
4505
  self.btnPayNowSingleAccountView.isHidden = false
4172
- // self.viewSingleAccountViewHeight.constant = 170
4506
+
4507
+ if self.request.enableRecurring == true {
4508
+ self.txtFieldSelectPlanSingleSavedBankView.isHidden = false
4509
+ self.txtFieldSelectDateSingleSavedBankView.isHidden = false
4510
+ }
4511
+ else {
4512
+ self.txtFieldSelectPlanSingleSavedBankView.isHidden = true
4513
+ self.txtFieldSelectDateSingleSavedBankView.isHidden = true
4514
+ }
4173
4515
  } else {
4174
4516
  self.viewTermAndConditionsSingleAccountView.isHidden = true
4175
4517
  self.btnPayNowSingleAccountView.isHidden = true
4176
- // self.viewSingleAccountViewHeight.constant = 68
4177
4518
  self.btnNext.isHidden = true
4178
4519
  self.btnNextHeight.constant = 0
4179
4520
  self.btnNextTopCon.constant = 0
4521
+
4522
+ self.txtFieldSelectPlanSingleSavedBankView.isHidden = true
4523
+ self.txtFieldSelectDateSingleSavedBankView.isHidden = true
4180
4524
  }
4181
4525
 
4182
4526
  self.grailPayBankLinkView.isHidden = true
4527
+
4528
+ self.txtFieldSelectPlanSingleSavedCard.isHidden = true
4529
+ self.txtFieldSelectDateSingleSavedCard.isHidden = true
4183
4530
  }
4184
4531
  } else {
4185
4532
  print("Error from server: \(bankAccountModel.message ?? "Unknown error")")
@@ -4294,7 +4641,13 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
4294
4641
  self.presentPaymentErrorVC(errorMessage: "No data received")
4295
4642
  }
4296
4643
  } else {
4297
- self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
4644
+ if let data = serviceData,
4645
+ let responseObj = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
4646
+ let message = responseObj["message"] as? String {
4647
+ self.presentPaymentErrorVC(errorMessage: message)
4648
+ } else {
4649
+ self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
4650
+ }
4298
4651
  }
4299
4652
  }
4300
4653
  task.resume()
@@ -4397,7 +4750,13 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
4397
4750
  self.presentPaymentErrorVC(errorMessage: "No data received")
4398
4751
  }
4399
4752
  } else {
4400
- self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
4753
+ if let data = serviceData,
4754
+ let responseObj = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
4755
+ let message = responseObj["message"] as? String {
4756
+ self.presentPaymentErrorVC(errorMessage: message)
4757
+ } else {
4758
+ self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
4759
+ }
4401
4760
  }
4402
4761
  }
4403
4762
  task.resume()
@@ -4510,7 +4869,13 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
4510
4869
  self.presentPaymentErrorVC(errorMessage: "No data received")
4511
4870
  }
4512
4871
  } else {
4513
- self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
4872
+ if let data = serviceData,
4873
+ let responseObj = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
4874
+ let message = responseObj["message"] as? String {
4875
+ self.presentPaymentErrorVC(errorMessage: message)
4876
+ } else {
4877
+ self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
4878
+ }
4514
4879
  }
4515
4880
  }
4516
4881
  task.resume()
@@ -4633,7 +4998,13 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
4633
4998
  self.presentPaymentErrorVC(errorMessage: "No data received")
4634
4999
  }
4635
5000
  } else {
4636
- self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
5001
+ if let data = serviceData,
5002
+ let responseObj = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
5003
+ let message = responseObj["message"] as? String {
5004
+ self.presentPaymentErrorVC(errorMessage: message)
5005
+ } else {
5006
+ self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
5007
+ }
4637
5008
  }
4638
5009
  }
4639
5010
  task.resume()
@@ -4708,7 +5079,13 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
4708
5079
  }
4709
5080
  } else {
4710
5081
  DispatchQueue.main.async {
4711
- self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
5082
+ if let data = serviceData,
5083
+ let responseObj = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
5084
+ let message = responseObj["message"] as? String {
5085
+ self.presentPaymentErrorVC(errorMessage: message)
5086
+ } else {
5087
+ self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
5088
+ }
4712
5089
  }
4713
5090
  }
4714
5091
  }
@@ -4841,7 +5218,13 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
4841
5218
  self.presentPaymentErrorVC(errorMessage: "No data received")
4842
5219
  }
4843
5220
  } else {
4844
- self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
5221
+ if let data = serviceData,
5222
+ let responseObj = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
5223
+ let message = responseObj["message"] as? String {
5224
+ self.presentPaymentErrorVC(errorMessage: message)
5225
+ } else {
5226
+ self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
5227
+ }
4845
5228
  }
4846
5229
  }
4847
5230
  task.resume()
@@ -5056,6 +5439,30 @@ extension PaymentInfoVC: UICollectionViewDelegate, UICollectionViewDataSource, U
5056
5439
  self.viewCrypto.isHidden = true
5057
5440
  self.grailPayBankLinkView.isHidden = true
5058
5441
  self.viewAddNewGrailPayAccount.isHidden = true
5442
+
5443
+ if self.isSelectForPay {
5444
+ self.viewTxtFieldCVVSingleCard.isHidden = false
5445
+ self.btnPayNowSingleCard.isHidden = false
5446
+ self.btnNext.isHidden = true
5447
+ self.btnNextHeight.constant = 0
5448
+ self.btnNextTopCon.constant = 0
5449
+ if self.request.enableRecurring == true {
5450
+ self.txtFieldSelectPlanSingleSavedCard.isHidden = false
5451
+ self.txtFieldSelectDateSingleSavedCard.isHidden = false
5452
+ }
5453
+ else {
5454
+ self.txtFieldSelectPlanSingleSavedCard.isHidden = true
5455
+ self.txtFieldSelectDateSingleSavedCard.isHidden = true
5456
+ }
5457
+ } else {
5458
+ self.viewTxtFieldCVVSingleCard.isHidden = true
5459
+ self.btnPayNowSingleCard.isHidden = true
5460
+ self.btnNext.isHidden = true
5461
+ self.btnNextHeight.constant = 0
5462
+ self.btnNextTopCon.constant = 8
5463
+ self.txtFieldSelectPlanSingleSavedCard.isHidden = true
5464
+ self.txtFieldSelectDateSingleSavedCard.isHidden = true
5465
+ }
5059
5466
  }
5060
5467
 
5061
5468
  case "Bank":
@@ -5181,6 +5588,9 @@ extension PaymentInfoVC: UITableViewDelegate, UITableViewDataSource {
5181
5588
  else if tableView == tblViewAccountTypeNewAccountView {
5182
5589
  return arrAccountType.count
5183
5590
  }
5591
+ // else if tableView == tblViewRecurring {
5592
+ // return planOptions.count
5593
+ // }
5184
5594
  return 0
5185
5595
  }
5186
5596
 
@@ -5229,6 +5639,11 @@ extension PaymentInfoVC: UITableViewDelegate, UITableViewDataSource {
5229
5639
  cell.lblAccountType.text = arrAccountType[indexPath.row]
5230
5640
  return cell
5231
5641
  }
5642
+ // else if tableView == tblViewRecurring {
5643
+ // let cell = tableView.dequeueReusableCell(withIdentifier: "RecurringTVC", for: indexPath) as! RecurringTVC
5644
+ // cell.lblRecurringDuration.text = planOptions[indexPath.row]
5645
+ // return cell
5646
+ // }
5232
5647
 
5233
5648
  return UITableViewCell()
5234
5649
  }
@@ -5335,6 +5750,9 @@ extension PaymentInfoVC: UITableViewDelegate, UITableViewDataSource {
5335
5750
  else if tableView == tblViewAccountTypeNewAccountView {
5336
5751
  return 45
5337
5752
  }
5753
+ // else if tableView == tblViewRecurring {
5754
+ // return 45
5755
+ // }
5338
5756
  else {
5339
5757
  return 80
5340
5758
  }
@@ -5351,6 +5769,11 @@ extension PaymentInfoVC: UITableViewDelegate, UITableViewDataSource {
5351
5769
  txtFieldAccountTypeNewAccountView.text = selectedAccountType // Fill the selected account type into the text field
5352
5770
  viewAccountTypeNewAccountView.isHidden = true // Hide the table view after selection
5353
5771
  }
5772
+ // else if tableView == tblViewRecurring {
5773
+ // let selectedAccountType = planOptions[indexPath.row]
5774
+ // txtFieldChosePlanCard.text = selectedAccountType // Fill the selected account type into the text field
5775
+ // viewTblViewRecurring.isHidden = true
5776
+ // }
5354
5777
  }
5355
5778
 
5356
5779
  @objc func btnSelectCardTapped(_ sender: UIButton) {
@@ -5383,11 +5806,9 @@ extension PaymentInfoVC: UITableViewDelegate, UITableViewDataSource {
5383
5806
  if isSelectForPay {
5384
5807
  viewTxtFieldCVVSingleCard.isHidden = false
5385
5808
  btnPayNowSingleCard.isHidden = false
5386
- viewSingleSavedCardHeight.constant = 220
5387
5809
  } else {
5388
5810
  viewTxtFieldCVVSingleCard.isHidden = true
5389
5811
  btnPayNowSingleCard.isHidden = true
5390
- viewSingleSavedCardHeight.constant = 60
5391
5812
  }
5392
5813
  }
5393
5814
 
@@ -5515,10 +5936,8 @@ extension PaymentInfoVC: UITableViewDelegate, UITableViewDataSource {
5515
5936
  let index = sender.tag
5516
5937
  // Store the index of the previously selected card
5517
5938
  let previousSelectedIndex = selectedBankIndex
5518
-
5519
5939
  // Toggle the selection state: if the same card is selected, deselect it; otherwise, select the new one
5520
5940
  selectedBankIndex = (selectedBankIndex == index) ? nil : index
5521
-
5522
5941
  // Update the single card view
5523
5942
  if let selectedIndex = selectedBankIndex {
5524
5943
  updateSingleBankView(for: selectedIndex)
@@ -5527,12 +5946,10 @@ extension PaymentInfoVC: UITableViewDelegate, UITableViewDataSource {
5527
5946
  } else {
5528
5947
  viewSingleSavedAccount.isHidden = true
5529
5948
  }
5530
-
5531
5949
  // Reload the previously selected row to update its state
5532
5950
  if let previousIndex = previousSelectedIndex {
5533
5951
  tblViewSavedBankAccounts.reloadRows(at: [IndexPath(row: previousIndex, section: 0)], with: .automatic)
5534
5952
  }
5535
-
5536
5953
  // Reload the newly selected row to update its state
5537
5954
  tblViewSavedBankAccounts.reloadRows(at: [IndexPath(row: index, section: 0)], with: .automatic)
5538
5955
  }