@jimrising/easymerchantsdk-react-native 1.4.5 → 1.4.7

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.
Files changed (30) hide show
  1. package/README.md +217 -140
  2. package/android/build/.transforms/20e1216b87bd06eaab3c9e5c68d4267a/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkModule$1.dex +0 -0
  3. package/android/build/.transforms/20e1216b87bd06eaab3c9e5c68d4267a/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkModule$2.dex +0 -0
  4. package/android/build/.transforms/20e1216b87bd06eaab3c9e5c68d4267a/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkModule.dex +0 -0
  5. package/android/build/.transforms/e9a664a11ce12edf79cd87b1e07aa243/transformed/classes/classes_dex/classes.dex +0 -0
  6. package/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
  7. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule$1.class +0 -0
  8. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule$2.class +0 -0
  9. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule.class +0 -0
  10. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/RNEasymerchantsdkModule$1.class +0 -0
  11. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/RNEasymerchantsdkModule$2.class +0 -0
  12. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/RNEasymerchantsdkModule.class +0 -0
  13. package/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
  14. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/RNEasymerchantsdkModule$1.class.uniqueId2 +0 -0
  15. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/RNEasymerchantsdkModule$2.class.uniqueId0 +0 -0
  16. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/RNEasymerchantsdkModule.class.uniqueId3 +0 -0
  17. package/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
  18. package/android/build.gradle +1 -1
  19. package/android/src/main/java/com/reactlibrary/RNEasymerchantsdkModule.java +26 -79
  20. package/ios/Classes/EasyMerchantSdk.m +4 -0
  21. package/ios/Classes/EasyMerchantSdk.swift +8 -3
  22. package/ios/Models/Request.swift +31 -8
  23. package/ios/Pods/UserDefaults/UserStoreSingleton.swift +41 -15
  24. package/ios/Pods/ViewControllers/GrailPayVC.swift +2 -2
  25. package/ios/Pods/ViewControllers/OTPVerificationVC.swift +151 -111
  26. package/ios/Pods/ViewControllers/PaymentInformation/PaymentInfoVC.swift +861 -671
  27. package/ios/Pods/ViewControllers/ThreeDSecurePaymentDoneVC.swift +2 -2
  28. package/ios/easymerchantsdk.podspec +1 -1
  29. package/ios/easymerchantsdk.storyboard +124 -3
  30. package/package.json +1 -1
@@ -307,6 +307,9 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
307
307
  @IBOutlet weak var heightViewTblViewRecurring: NSLayoutConstraint!
308
308
  @IBOutlet weak var tblViewRecurring: UITableView!
309
309
 
310
+ @IBOutlet weak var colVwPaymentMethodHeight: NSLayoutConstraint!
311
+ @IBOutlet weak var topConColViewPaymentMethodView: NSLayoutConstraint!
312
+
310
313
  var chainInvoiceAddress: String?
311
314
  var lightningURI: String?
312
315
 
@@ -422,37 +425,6 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
422
425
  tapGesture.cancelsTouchesInView = false
423
426
  self.view.addGestureRecognizer(tapGesture)
424
427
 
425
- //// Check if billingInfoData is available
426
- // if let billingInfoData = request.billingInfoData,
427
- // let fieldSection = try? JSONDecoder().decode(FieldSection.self, from: billingInfoData) {
428
- //
429
- // let billingVisible = fieldSection.visibility.billing
430
- // let suffix = billingVisible ? " (Billing Info)" : " (Additional Info)"
431
- // let buttonText = (request?.submitButtonText?.isEmpty == false
432
- // ? request!.submitButtonText! + suffix
433
- // : "Next" + suffix)
434
- //
435
- // btnNext.setTitle(buttonText, for: .normal)
436
- // btnPayNowNewCardView.setTitle(buttonText, for: .normal)
437
- // btnPayNowNewAccountView.setTitle(buttonText, for: .normal)
438
- // btnPayNowSingleCard.setTitle(buttonText, for: .normal)
439
- // btnPayNowSingleAccountView.setTitle(buttonText, for: .normal)
440
- // } else {
441
- // let amountValue = request?.amount ?? 0
442
- // let amountText = String(format: "$%.2f", amountValue)
443
- // let submitText = request?.submitButtonText
444
- //
445
- // let defaultTitle = (submitText?.isEmpty == false)
446
- // ? "\(submitText!) (\(amountText))"
447
- // : "Pay Now (\(amountText))"
448
- //
449
- // btnNext.setTitle(defaultTitle, for: .normal)
450
- // btnPayNowNewCardView.setTitle(defaultTitle, for: .normal)
451
- // btnPayNowNewAccountView.setTitle(defaultTitle, for: .normal)
452
- // btnPayNowSingleCard.setTitle(defaultTitle, for: .normal)
453
- // btnPayNowSingleAccountView.setTitle(defaultTitle, for: .normal)
454
- // }
455
-
456
428
  if let billingInfoData = request.billingInfoData,
457
429
  let fieldSection = try? JSONDecoder().decode(FieldSection.self, from: billingInfoData) {
458
430
 
@@ -460,9 +432,9 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
460
432
  let additionalVisible = fieldSection.visibility.additional
461
433
  let submitText = request?.submitButtonText?.isEmpty == false ? request!.submitButtonText! : "Pay Now"
462
434
  let amountText = String(format: "$%.2f", request?.amount ?? 0)
463
-
435
+
464
436
  var buttonText: String
465
-
437
+
466
438
  if !billingVisible && !additionalVisible {
467
439
  // Both visibility false – show submitText with amount only
468
440
  buttonText = "\(submitText) (\(amountText))"
@@ -474,7 +446,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
474
446
  // Fallback
475
447
  buttonText = "\(submitText) (\(amountText))"
476
448
  }
477
-
449
+
478
450
  btnNext.setTitle(buttonText, for: .normal)
479
451
  btnPayNowNewCardView.setTitle(buttonText, for: .normal)
480
452
  btnPayNowNewAccountView.setTitle(buttonText, for: .normal)
@@ -485,7 +457,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
485
457
  let amountText = String(format: "$%.2f", request?.amount ?? 0)
486
458
  let submitText = request?.submitButtonText?.isEmpty == false ? request!.submitButtonText! : "Pay Now"
487
459
  let defaultTitle = "\(submitText) (\(amountText))"
488
-
460
+
489
461
  btnNext.setTitle(defaultTitle, for: .normal)
490
462
  btnPayNowNewCardView.setTitle(defaultTitle, for: .normal)
491
463
  btnPayNowNewAccountView.setTitle(defaultTitle, for: .normal)
@@ -493,6 +465,14 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
493
465
  btnPayNowSingleAccountView.setTitle(defaultTitle, for: .normal)
494
466
  }
495
467
 
468
+ lblEasyMerchantOne.text = "POWERED BY \(UserStoreSingleton.shared.companyName?.uppercased() ?? "")"
469
+ txtFieldEmailCardView.textField.text = request.email
470
+ cardNameTextField.textField.text = request.name
471
+ txtFieldNameOnCardNewCardView.text = request.name
472
+ txtFieldEmailAccountView.textField.text = request.email
473
+ txtFieldEmailGrailPayView.textField.text = request.email
474
+ txtFieldEmail.text = request.email
475
+
496
476
  emailView.isHidden = true
497
477
  OTPView.isHidden = true
498
478
 
@@ -550,6 +530,21 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
550
530
  }
551
531
 
552
532
  setupPlanTableView()
533
+
534
+ if let paymentMethods = request?.selectedPaymentMethods {
535
+ if paymentMethods.count <= 1 {
536
+ collVwPayment.isHidden = true
537
+ topConColViewPaymentMethodView.constant = 0
538
+ colVwPaymentMethodHeight.constant = 0
539
+ lblChosePaymentMethod.text = "Complete Your Payment"
540
+ } else {
541
+ collVwPayment.isHidden = false
542
+ topConColViewPaymentMethodView.constant = 16
543
+ colVwPaymentMethodHeight.constant = 70
544
+ lblChosePaymentMethod.text = "Chose Your Payment Method"
545
+ loadPaymentMethods()
546
+ }
547
+ }
553
548
  }
554
549
 
555
550
  //MARK: - View Wiil Appear
@@ -755,11 +750,6 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
755
750
  self.viewSingleSavedAccount.isHidden = true
756
751
  self.viewBankFields.isHidden = true
757
752
 
758
- // self.viewBtnShowSavedCards.isHidden = false
759
- // self.lblBtnShowSaveCard.text = "Show Saved Cards"
760
- // self.viewBtnShowSavedCardHeight.constant = 50
761
- // self.viewBtnShowSavedCardTopCon.constant = 20
762
-
763
753
  if request.saveCard == false {
764
754
  self.viewBtnShowSavedCards.isHidden = true
765
755
  self.viewBtnShowSavedCardHeight.constant = 0
@@ -873,18 +863,10 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
873
863
  }
874
864
  }
875
865
  else {
876
- // self.viewBankFields.isHidden = false
877
- // self.viewTermsAndConditions.isHidden = false
878
866
  self.grailPayBankLinkView.isHidden = true
879
867
  }
880
868
  }
881
869
  else {
882
- // self.viewBankFields.isHidden = false
883
- // self.viewBtnShowSavedCards.isHidden = false
884
- // self.lblBtnShowSaveCard.text = "Show Saved Accounts"
885
- // self.viewBtnShowSavedCardHeight.constant = 50
886
- // self.viewBtnShowSavedCardTopCon.constant = 20
887
-
888
870
  if request.saveAccount == false {
889
871
  self.viewBtnShowSavedCards.isHidden = true
890
872
  self.viewBtnShowSavedCardHeight.constant = 0
@@ -1667,28 +1649,9 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
1667
1649
  viewAccountTypeNewAccountView.layer.cornerRadius = 8
1668
1650
 
1669
1651
  viewAccountTypeNewAccountView.isHidden = true
1670
-
1671
- // tblViewRecurring.delegate = self
1672
- // tblViewRecurring.dataSource = self
1673
- // tblViewRecurring.showsVerticalScrollIndicator = false
1674
- // tblViewRecurring.showsHorizontalScrollIndicator = false
1675
- //
1676
- // viewTblViewRecurring.clipsToBounds = false
1677
- // viewTblViewRecurring.layer.shadowColor = UIColor.black.cgColor
1678
- // viewTblViewRecurring.layer.shadowOpacity = 0.3
1679
- // viewTblViewRecurring.layer.shadowOffset = CGSize(width: 0, height: 2)
1680
- // viewTblViewRecurring.layer.shadowRadius = 4
1681
- // viewTblViewRecurring.layer.cornerRadius = 8
1682
- // viewTblViewRecurring.layer.cornerRadius = 8
1683
- //
1684
- // viewTblViewRecurring.isHidden = true
1685
1652
  }
1686
1653
 
1687
1654
  @IBAction func actionBtnChosePlanCardField(_ sender: UIButton) {
1688
- // UIView.animate(withDuration: 0.3) {
1689
- // self.viewTblViewRecurring.isHidden.toggle()
1690
- // }
1691
-
1692
1655
  guard let plans = request?.recurringIntervals, !plans.isEmpty else {
1693
1656
  print("No recurring intervals available.")
1694
1657
  return
@@ -1930,58 +1893,9 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
1930
1893
  }
1931
1894
  }
1932
1895
 
1933
- // Redirect based on billing visibility
1934
- // if fieldSection.visibility.billing {
1935
- // // Instantiate BillingInfoVC and pass the selected card data and CVV text
1936
- // let billingInfoVC = UIStoryboard(name: "easymerchantsdk", bundle: .easyPayBundle).instantiateViewController(withIdentifier: "BillingInfoVC") as! BillingInfoVC
1937
- //
1938
- // billingInfoVC.isFrom = "SavedCards"
1939
- // billingInfoVC.selectedCard = self.selectedCard // Passing the selected card data
1940
- // billingInfoVC.cvvText = cvvText // Passing the CVV text
1941
- // billingInfoVC.amount = Int(self.request.amount ?? 0)
1942
- // billingInfoVC.selectedPaymentMethod = self.selectedPaymentMethod
1943
- //
1944
- // if let billingInfoData = self.request.billingInfoData {
1945
- // billingInfoVC.billingInfoData = billingInfoData
1946
- // }
1947
- //
1948
- // billingInfoVC.request = self.request
1949
- // billingInfoVC.chosenPlan = self.txtFieldSelectPlanSingleSavedCard.text
1950
- // billingInfoVC.startDate = self.txtFieldSelectDateSingleSavedCard.text
1951
- //
1952
- // billingInfoVC.billingInfo = fieldSection.billing
1953
- // billingInfoVC.additionalInfo = fieldSection.additional
1954
- // billingInfoVC.visibility = fieldSection.visibility
1955
- //
1956
- // // Navigate to BillingInfoVC
1957
- // self.navigationController?.pushViewController(billingInfoVC, animated: true)
1958
- // }
1959
- // else {
1960
- // let additionalInfoVC = UIStoryboard(name: "easymerchantsdk", bundle: .easyPayBundle).instantiateViewController(withIdentifier: "AdditionalInfoVC") as! AdditionalInfoVC
1961
- // additionalInfoVC.isFrom = "SavedCards"
1962
- // additionalInfoVC.selectedCard = self.selectedCard // Passing the selected card data
1963
- // additionalInfoVC.cvvText = cvvText // Passing the CVV text
1964
- // additionalInfoVC.amount = Int(self.request.amount ?? 0)
1965
- // additionalInfoVC.selectedPaymentMethod = self.selectedPaymentMethod
1966
- //
1967
- // if let billingInfoData = self.request.billingInfoData {
1968
- // additionalInfoVC.billingInfoData = billingInfoData
1969
- // }
1970
- //
1971
- // additionalInfoVC.request = self.request
1972
- // additionalInfoVC.chosenPlan = self.txtFieldSelectPlanSingleSavedCard.text
1973
- // additionalInfoVC.startDate = self.txtFieldSelectDateSingleSavedCard.text
1974
- //
1975
- // additionalInfoVC.billingInfo = fieldSection.billing
1976
- // additionalInfoVC.additionalInfo = fieldSection.additional
1977
- // additionalInfoVC.visibility = fieldSection.visibility
1978
- //
1979
- // self.navigationController?.pushViewController(additionalInfoVC, animated: true)
1980
- // }
1981
-
1982
1896
  let showBilling = fieldSection.visibility.billing
1983
1897
  let showAdditional = fieldSection.visibility.additional
1984
-
1898
+
1985
1899
  if !showBilling && !showAdditional {
1986
1900
  self.paymentIntentFromShowCardApi()
1987
1901
  }
@@ -2033,7 +1947,6 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
2033
1947
 
2034
1948
  self.navigationController?.pushViewController(additionalInfoVC, animated: true)
2035
1949
  }
2036
-
2037
1950
  }
2038
1951
  }
2039
1952
  catch {
@@ -2066,7 +1979,6 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
2066
1979
  }
2067
1980
  }
2068
1981
  }
2069
-
2070
1982
  // All validations passed, call the API
2071
1983
  paymentIntentFromShowSavedCardApi()
2072
1984
  }
@@ -2186,67 +2098,6 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
2186
2098
  }
2187
2099
  }
2188
2100
 
2189
- // Redirect based on billing visibility
2190
- // if fieldSection.visibility.billing {
2191
- // // Instantiate BillingInfoVC and pass the card details
2192
- // let billingInfoVC = UIStoryboard(name: "easymerchantsdk", bundle: .easyPayBundle).instantiateViewController(withIdentifier: "BillingInfoVC") as! BillingInfoVC
2193
- //
2194
- // // Pass the card details
2195
- // billingInfoVC.cardNumber = cardNumber
2196
- // billingInfoVC.expiryDate = expiryDate
2197
- // billingInfoVC.cvv = cvv
2198
- // billingInfoVC.nameOnCard = nameOnCard
2199
- // billingInfoVC.isSavedNewCard = self.isSavedNewCardForFuture
2200
- //
2201
- // billingInfoVC.isFrom = "AddNewCard"
2202
- // billingInfoVC.amount = Int(self.request.amount ?? 0)
2203
- // billingInfoVC.selectedPaymentMethod = self.selectedPaymentMethod
2204
- //
2205
- // if let billingInfoData = self.request.billingInfoData {
2206
- // billingInfoVC.billingInfoData = billingInfoData
2207
- // }
2208
- //
2209
- // billingInfoVC.request = self.request
2210
- // billingInfoVC.chosenPlan = self.txtFieldSelectPlanNewCardView.text
2211
- // billingInfoVC.startDate = self.txtFieldSelectDateNewCardView.text
2212
- //
2213
- // billingInfoVC.billingInfo = fieldSection.billing
2214
- // billingInfoVC.additionalInfo = fieldSection.additional
2215
- // billingInfoVC.visibility = fieldSection.visibility
2216
- //
2217
- // // Navigate to BillingInfoVC
2218
- // self.navigationController?.pushViewController(billingInfoVC, animated: true)
2219
- // }
2220
- // else {
2221
- // let additionalInfoVC = UIStoryboard(name: "easymerchantsdk", bundle: .easyPayBundle).instantiateViewController(withIdentifier: "AdditionalInfoVC") as! AdditionalInfoVC
2222
- //
2223
- // // Pass the card details
2224
- // additionalInfoVC.cardNumber = cardNumber
2225
- // additionalInfoVC.expiryDate = expiryDate
2226
- // additionalInfoVC.cvv = cvv
2227
- // additionalInfoVC.nameOnCard = nameOnCard
2228
- // additionalInfoVC.isSavedNewCard = self.isSavedNewCardForFuture
2229
- //
2230
- // additionalInfoVC.isFrom = "AddNewCard"
2231
- // additionalInfoVC.amount = Int(self.request.amount ?? 0)
2232
- // additionalInfoVC.selectedPaymentMethod = self.selectedPaymentMethod
2233
- //
2234
- // if let billingInfoData = self.request.billingInfoData {
2235
- // additionalInfoVC.billingInfoData = billingInfoData
2236
- // }
2237
- //
2238
- // additionalInfoVC.request = self.request
2239
- // additionalInfoVC.chosenPlan = self.txtFieldSelectPlanNewCardView.text
2240
- // additionalInfoVC.startDate = self.txtFieldSelectDateNewCardView.text
2241
- //
2242
- // additionalInfoVC.billingInfo = fieldSection.billing
2243
- // additionalInfoVC.additionalInfo = fieldSection.additional
2244
- // additionalInfoVC.visibility = fieldSection.visibility
2245
- //
2246
- // self.navigationController?.pushViewController(additionalInfoVC, animated: true)
2247
- // }
2248
-
2249
-
2250
2101
  let showBilling = fieldSection.visibility.billing
2251
2102
  let showAdditional = fieldSection.visibility.additional
2252
2103
 
@@ -2766,52 +2617,12 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
2766
2617
  let jsonDict = json as? [String: Any], !jsonDict.isEmpty {
2767
2618
  print("Billing Info Data: \(jsonDict)")
2768
2619
 
2769
- // Redirect based on billing visibility
2770
- // if fieldSection.visibility.billing {
2771
- // let vc = easymerchantsdk.instantiateViewController(withIdentifier: "BillingInfoVC") as! BillingInfoVC
2772
- // vc.billingInfoData = billingInfoData
2773
- // vc.request = self.request
2774
- // vc.chosenPlan = self.txtFieldChosePlanGrailPayBankView.text
2775
- // vc.startDate = self.txtFieldSelectDateGrailPayBankView.text
2776
- // vc.selectedPaymentMethod = "GrailPay"
2777
- // vc.isSavedForFuture = self.isSavedForFuture
2778
- // vc.grailPayAccountID = self.grailPayAccountID
2779
- // vc.selectedGrailPayAccountType = self.selectedGrailPayAccountType
2780
- // vc.selectedGrailPayAccountName = self.selectedGrailPayAccountName
2781
- // vc.amount = self.amount
2782
- // vc.billingInfo = fieldSection.billing
2783
- // vc.additionalInfo = fieldSection.additional
2784
- // vc.visibility = fieldSection.visibility
2785
- // vc.easyPayDelegate = self.easyPayDelegate
2786
- // vc.userEmail = self.txtFieldEmailGrailPayView.text
2787
- // self.navigationController?.pushViewController(vc, animated: true)
2788
- // }
2789
- // else {
2790
- // let vc = easymerchantsdk.instantiateViewController(withIdentifier: "AdditionalInfoVC") as! AdditionalInfoVC
2791
- // vc.billingInfoData = billingInfoData
2792
- // vc.request = self.request
2793
- // vc.chosenPlan = self.txtFieldChosePlanGrailPayBankView.text
2794
- // vc.startDate = self.txtFieldSelectDateGrailPayBankView.text
2795
- // vc.selectedPaymentMethod = "GrailPay"
2796
- // vc.isSavedForFuture = self.isSavedForFuture
2797
- // vc.grailPayAccountID = self.grailPayAccountID
2798
- // vc.selectedGrailPayAccountType = self.selectedGrailPayAccountType
2799
- // vc.selectedGrailPayAccountName = self.selectedGrailPayAccountName
2800
- // vc.amount = self.amount
2801
- // vc.billingInfo = fieldSection.billing
2802
- // vc.additionalInfo = fieldSection.additional
2803
- // vc.visibility = fieldSection.visibility
2804
- // vc.easyPayDelegate = self.easyPayDelegate
2805
- // vc.userEmail = self.txtFieldEmailGrailPayView.text
2806
- // self.navigationController?.pushViewController(vc, animated: true)
2807
- // }
2808
-
2809
2620
  let showBilling = fieldSection.visibility.billing
2810
2621
  let showAdditional = fieldSection.visibility.additional
2811
-
2622
+
2812
2623
  if !showBilling && !showAdditional {
2813
2624
  // Navigate directly to EmailVerificationVC
2814
- // let vc = easymerchantsdk.instantiateViewController(withIdentifier: "EmailVerificationVC") as! EmailVerificationVC
2625
+ // let vc = easymerchantsdk.instantiateViewController(withIdentifier: "EmailVerificationVC") as! EmailVerificationVC
2815
2626
  let vc = easymerchantsdk.instantiateViewController(withIdentifier: "OTPVerificationVC") as! OTPVerificationVC
2816
2627
  vc.easyPayDelegate = self.easyPayDelegate
2817
2628
  vc.grailPayAccountID = self.grailPayAccountID
@@ -2871,7 +2682,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
2871
2682
  vc.userEmail = self.txtFieldEmailGrailPayView.text
2872
2683
  self.navigationController?.pushViewController(vc, animated: true)
2873
2684
  }
2874
-
2685
+
2875
2686
  }
2876
2687
  }
2877
2688
  }
@@ -2882,7 +2693,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
2882
2693
  else {
2883
2694
  //If billing info is nil
2884
2695
  // Navigate to EmailVerificationVC directly
2885
- // let vc = easymerchantsdk.instantiateViewController(withIdentifier: "EmailVerificationVC") as! EmailVerificationVC
2696
+ // let vc = easymerchantsdk.instantiateViewController(withIdentifier: "EmailVerificationVC") as! EmailVerificationVC
2886
2697
  let vc = easymerchantsdk.instantiateViewController(withIdentifier: "OTPVerificationVC") as! OTPVerificationVC
2887
2698
  vc.easyPayDelegate = self.easyPayDelegate
2888
2699
  vc.grailPayAccountID = self.grailPayAccountID
@@ -2910,50 +2721,9 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
2910
2721
  let jsonDict = json as? [String: Any], !jsonDict.isEmpty {
2911
2722
  print("Billing Info Data: \(jsonDict)")
2912
2723
 
2913
- // Redirect based on billing visibility
2914
- // if fieldSection.visibility.billing {
2915
- // let vc = easymerchantsdk.instantiateViewController(withIdentifier: "BillingInfoVC") as! BillingInfoVC
2916
- // vc.billingInfoData = billingInfoData
2917
- // vc.request = self.request
2918
- // vc.chosenPlan = self.txtFieldChosePlanGrailPayBankView.text
2919
- // vc.startDate = self.txtFieldSelectDateGrailPayBankView.text
2920
- // vc.selectedPaymentMethod = "GrailPay"
2921
- // vc.isSavedForFuture = self.isSavedForFuture
2922
- // vc.grailPayAccountID = self.grailPayAccountID
2923
- // vc.selectedGrailPayAccountType = self.selectedGrailPayAccountType
2924
- // vc.selectedGrailPayAccountName = self.selectedGrailPayAccountName
2925
- // vc.amount = self.amount
2926
- // vc.billingInfo = fieldSection.billing
2927
- // vc.additionalInfo = fieldSection.additional
2928
- // vc.visibility = fieldSection.visibility
2929
- // vc.easyPayDelegate = self.easyPayDelegate
2930
- // vc.userEmail = self.txtFieldEmailGrailPayView.text
2931
- // self.navigationController?.pushViewController(vc, animated: true)
2932
- // }
2933
- // else {
2934
- // let vc = easymerchantsdk.instantiateViewController(withIdentifier: "AdditionalInfoVC") as! AdditionalInfoVC
2935
- // vc.billingInfoData = billingInfoData
2936
- // vc.request = self.request
2937
- // vc.chosenPlan = self.txtFieldChosePlanGrailPayBankView.text
2938
- // vc.startDate = self.txtFieldSelectDateGrailPayBankView.text
2939
- // vc.selectedPaymentMethod = "GrailPay"
2940
- // vc.isSavedForFuture = self.isSavedForFuture
2941
- // vc.grailPayAccountID = self.grailPayAccountID
2942
- // vc.selectedGrailPayAccountType = self.selectedGrailPayAccountType
2943
- // vc.selectedGrailPayAccountName = self.selectedGrailPayAccountName
2944
- // vc.amount = self.amount
2945
- // vc.billingInfo = fieldSection.billing
2946
- // vc.additionalInfo = fieldSection.additional
2947
- // vc.visibility = fieldSection.visibility
2948
- // vc.easyPayDelegate = self.easyPayDelegate
2949
- // vc.userEmail = self.txtFieldEmailGrailPayView.text
2950
- // self.navigationController?.pushViewController(vc, animated: true)
2951
- // }
2952
-
2953
-
2954
2724
  let showBilling = fieldSection.visibility.billing
2955
2725
  let showAdditional = fieldSection.visibility.additional
2956
-
2726
+
2957
2727
  if !showBilling && !showAdditional {
2958
2728
  self.grailPayAccountChargeApi()
2959
2729
  }
@@ -3051,48 +2821,9 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
3051
2821
  let jsonDict = json as? [String: Any], !jsonDict.isEmpty {
3052
2822
  print("Billing Info Data: \(jsonDict)")
3053
2823
 
3054
- // Redirect based on billing visibility
3055
- // if fieldSection.visibility.billing {
3056
- // let vc = easymerchantsdk.instantiateViewController(withIdentifier: "BillingInfoVC") as! BillingInfoVC
3057
- // vc.billingInfoData = billingInfoData
3058
- // vc.request = self.request
3059
- // vc.chosenPlan = self.txtFieldChosePlanNewGrailPayBankView.text
3060
- // vc.startDate = self.txtFieldSelectDateNewGrailPayBankView.text
3061
- // vc.selectedPaymentMethod = "NewGrailPayAccount"
3062
- // vc.isSavedForFuture = self.isSavedForFuture
3063
- // vc.grailPayAccountID = self.newGrailPayAccountID
3064
- // vc.selectedGrailPayAccountType = self.selectedNewGrailPayAccountType
3065
- // vc.selectedGrailPayAccountName = self.selectedNewGrailPayAccountName
3066
- // vc.amount = self.amount
3067
- // vc.billingInfo = fieldSection.billing
3068
- // vc.additionalInfo = fieldSection.additional
3069
- // vc.visibility = fieldSection.visibility
3070
- // vc.easyPayDelegate = self.easyPayDelegate
3071
- // self.navigationController?.pushViewController(vc, animated: true)
3072
- // }
3073
- // else {
3074
- // let vc = easymerchantsdk.instantiateViewController(withIdentifier: "AdditionalInfoVC") as! AdditionalInfoVC
3075
- // vc.billingInfoData = billingInfoData
3076
- // vc.request = self.request
3077
- // vc.chosenPlan = self.txtFieldChosePlanNewGrailPayBankView.text
3078
- // vc.startDate = self.txtFieldSelectDateNewGrailPayBankView.text
3079
- // vc.selectedPaymentMethod = "NewGrailPayAccount"
3080
- // vc.isSavedForFuture = self.isSavedForFuture
3081
- // vc.grailPayAccountID = self.newGrailPayAccountID
3082
- // vc.selectedGrailPayAccountType = self.selectedNewGrailPayAccountType
3083
- // vc.selectedGrailPayAccountName = self.selectedNewGrailPayAccountName
3084
- // vc.amount = self.amount
3085
- // vc.billingInfo = fieldSection.billing
3086
- // vc.additionalInfo = fieldSection.additional
3087
- // vc.visibility = fieldSection.visibility
3088
- // vc.easyPayDelegate = self.easyPayDelegate
3089
- // self.navigationController?.pushViewController(vc, animated: true)
3090
- // }
3091
-
3092
-
3093
2824
  let showBilling = fieldSection.visibility.billing
3094
2825
  let showAdditional = fieldSection.visibility.additional
3095
-
2826
+
3096
2827
  if !showBilling && !showAdditional {
3097
2828
  self.grailPayNewAccountChargeApi()
3098
2829
  }
@@ -3156,47 +2887,9 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
3156
2887
  let jsonDict = json as? [String: Any], !jsonDict.isEmpty {
3157
2888
  print("Billing Info Data: \(jsonDict)")
3158
2889
 
3159
- // Redirect based on billing visibility
3160
- // if fieldSection.visibility.billing {
3161
- // let vc = easymerchantsdk.instantiateViewController(withIdentifier: "BillingInfoVC") as! BillingInfoVC
3162
- // vc.billingInfoData = billingInfoData
3163
- // vc.request = self.request
3164
- // vc.chosenPlan = self.txtFieldChosePlanNewGrailPayBankView.text
3165
- // vc.startDate = self.txtFieldSelectDateNewGrailPayBankView.text
3166
- // vc.selectedPaymentMethod = "NewGrailPayAccount"
3167
- // vc.isSavedForFuture = self.isSavedForFuture
3168
- // vc.grailPayAccountID = self.newGrailPayAccountID
3169
- // vc.selectedGrailPayAccountType = self.selectedNewGrailPayAccountType
3170
- // vc.selectedGrailPayAccountName = self.selectedNewGrailPayAccountName
3171
- // vc.amount = self.amount
3172
- // vc.billingInfo = fieldSection.billing
3173
- // vc.additionalInfo = fieldSection.additional
3174
- // vc.visibility = fieldSection.visibility
3175
- // vc.easyPayDelegate = self.easyPayDelegate
3176
- // self.navigationController?.pushViewController(vc, animated: true)
3177
- // }
3178
- // else {
3179
- // let vc = easymerchantsdk.instantiateViewController(withIdentifier: "AdditionalInfoVC") as! AdditionalInfoVC
3180
- // vc.billingInfoData = billingInfoData
3181
- // vc.request = self.request
3182
- // vc.chosenPlan = self.txtFieldChosePlanNewGrailPayBankView.text
3183
- // vc.startDate = self.txtFieldSelectDateNewGrailPayBankView.text
3184
- // vc.selectedPaymentMethod = "NewGrailPayAccount"
3185
- // vc.isSavedForFuture = self.isSavedForFuture
3186
- // vc.grailPayAccountID = self.newGrailPayAccountID
3187
- // vc.selectedGrailPayAccountType = self.selectedNewGrailPayAccountType
3188
- // vc.selectedGrailPayAccountName = self.selectedNewGrailPayAccountName
3189
- // vc.amount = self.amount
3190
- // vc.billingInfo = fieldSection.billing
3191
- // vc.additionalInfo = fieldSection.additional
3192
- // vc.visibility = fieldSection.visibility
3193
- // vc.easyPayDelegate = self.easyPayDelegate
3194
- // self.navigationController?.pushViewController(vc, animated: true)
3195
- // }
3196
-
3197
2890
  let showBilling = fieldSection.visibility.billing
3198
2891
  let showAdditional = fieldSection.visibility.additional
3199
-
2892
+
3200
2893
  if !showBilling && !showAdditional {
3201
2894
  self.grailPayNewAccountChargeApi()
3202
2895
  }
@@ -3376,68 +3069,16 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
3376
3069
  "email": UserStoreSingleton.shared.merchantEmail ?? ""
3377
3070
  ]
3378
3071
 
3379
- // if let billingInfoData = request.billingInfoData {
3380
- // do {
3381
- // let fieldSection = try JSONDecoder().decode(FieldSection.self, from: billingInfoData)
3382
- //
3383
- // // Process Billing Info if available and contains any non-empty value
3384
- // let billing = fieldSection.billing.filter { !($0.value.trimmingCharacters(in: .whitespaces).isEmpty) }
3385
- // if !billing.isEmpty {
3386
- // var billingDict: [String: Any] = [:]
3387
- // billing.forEach { billingDict[$0.name] = $0.value }
3388
- //
3389
- // if let address = billingDict["address"] as? String { params["address"] = address }
3390
- // if let country = billingDict["country"] as? String { params["country"] = country }
3391
- // if let state = billingDict["state"] as? String { params["state"] = state }
3392
- // if let city = billingDict["city"] as? String { params["city"] = city }
3393
- // if let postalCode = billingDict["postal_code"] as? String { params["zip"] = postalCode }
3394
- // }
3395
- //
3396
- // // Process Additional Info if available and contains any non-empty value
3397
- // let additional = fieldSection.additional.filter { !($0.value.trimmingCharacters(in: .whitespaces).isEmpty) }
3398
- // if !additional.isEmpty {
3399
- // var additionalDict: [String: Any] = [:]
3400
- // additional.forEach { additionalDict[$0.name] = $0.value }
3401
- //
3402
- // if let desc = additionalDict["description"] as? String {
3403
- // params["description"] = desc
3404
- // }
3405
- //
3406
- // if let phone = additionalDict["phone_number"] as? String {
3407
- // params["phone_number"] = phone
3408
- // }
3409
- // if let email = additionalDict["email"] as? String {
3410
- // params["email"] = email
3411
- // }
3412
- // if let name = additionalDict["name"] as? String {
3413
- // params["name"] = name
3414
- // }
3415
- // }
3416
- //
3417
- // // Set default description only if not already set
3418
- // if params["description"] == nil {
3419
- // params["description"] = "Hosted payment checkout"
3420
- // }
3421
- //
3422
- // } catch {
3423
- // print("Failed to decode FieldSection: \(error)")
3424
- // params["description"] = "Hosted payment checkout"
3425
- // }
3426
- // } else {
3427
- // params["description"] = "Hosted payment checkout"
3428
- // }
3429
-
3430
-
3431
3072
  if let billingInfoData = request.billingInfoData {
3432
3073
  do {
3433
3074
  let fieldSection = try JSONDecoder().decode(FieldSection.self, from: billingInfoData)
3434
-
3075
+
3435
3076
  // Billing Info
3436
3077
  let billing = fieldSection.billing
3437
3078
  if !billing.isEmpty {
3438
3079
  var billingDict: [String: Any] = [:]
3439
3080
  billing.forEach { billingDict[$0.name] = $0.value }
3440
-
3081
+
3441
3082
  if let address = billingDict["address"] as? String, !address.isEmpty {
3442
3083
  params["address"] = address
3443
3084
  }
@@ -3454,19 +3095,19 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
3454
3095
  params["zip"] = postalCode
3455
3096
  }
3456
3097
  }
3457
-
3098
+
3458
3099
  // Additional Info
3459
3100
  let additional = fieldSection.additional
3460
3101
  if !additional.isEmpty {
3461
3102
  var additionalDict: [String: Any] = [:]
3462
3103
  additional.forEach { additionalDict[$0.name] = $0.value }
3463
-
3104
+
3464
3105
  if let desc = additionalDict["description"] as? String, !desc.isEmpty {
3465
3106
  params["description"] = desc
3466
3107
  } else {
3467
3108
  params["description"] = "Hosted payment checkout"
3468
3109
  }
3469
-
3110
+
3470
3111
  if let phone = additionalDict["phone_number"] as? String, !phone.isEmpty {
3471
3112
  params["phone_number"] = phone
3472
3113
  }
@@ -3480,7 +3121,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
3480
3121
  // If no description in additional info, set default
3481
3122
  params["description"] = "Hosted payment checkout"
3482
3123
  }
3483
-
3124
+
3484
3125
  } catch {
3485
3126
  print("Failed to decode FieldSection: \(error)")
3486
3127
  params["description"] = "Hosted payment checkout"
@@ -3644,13 +3285,13 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
3644
3285
  if let billingInfoData = request.billingInfoData {
3645
3286
  do {
3646
3287
  let fieldSection = try JSONDecoder().decode(FieldSection.self, from: billingInfoData)
3647
-
3288
+
3648
3289
  // Billing Info
3649
3290
  let billing = fieldSection.billing
3650
3291
  if !billing.isEmpty {
3651
3292
  var billingDict: [String: Any] = [:]
3652
3293
  billing.forEach { billingDict[$0.name] = $0.value }
3653
-
3294
+
3654
3295
  if let address = billingDict["address"] as? String, !address.isEmpty {
3655
3296
  params["address"] = address
3656
3297
  }
@@ -3667,19 +3308,19 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
3667
3308
  params["zip"] = postalCode
3668
3309
  }
3669
3310
  }
3670
-
3311
+
3671
3312
  // Additional Info
3672
3313
  let additional = fieldSection.additional
3673
3314
  if !additional.isEmpty {
3674
3315
  var additionalDict: [String: Any] = [:]
3675
3316
  additional.forEach { additionalDict[$0.name] = $0.value }
3676
-
3317
+
3677
3318
  if let desc = additionalDict["description"] as? String, !desc.isEmpty {
3678
3319
  params["description"] = desc
3679
3320
  } else {
3680
3321
  params["description"] = "Hosted payment checkout"
3681
3322
  }
3682
-
3323
+
3683
3324
  if let phone = additionalDict["phone_number"] as? String, !phone.isEmpty {
3684
3325
  params["phone_number"] = phone
3685
3326
  }
@@ -3693,7 +3334,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
3693
3334
  // If no description in additional info, set default
3694
3335
  params["description"] = "Hosted payment checkout"
3695
3336
  }
3696
-
3337
+
3697
3338
  } catch {
3698
3339
  print("Failed to decode FieldSection: \(error)")
3699
3340
  params["description"] = "Hosted payment checkout"
@@ -3774,31 +3415,6 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
3774
3415
  // Pass the selected payment method
3775
3416
  paymentDoneVC.selectedPaymentMethod = self.selectedPaymentMethod
3776
3417
  paymentDoneVC.easyPayDelegate = self.easyPayDelegate
3777
- // // Pass billingInfo and additionalInfo
3778
- // if let billingData = self.request.billingInfoData,
3779
- // let billingInfoDict = try? JSONSerialization.jsonObject(with: billingData, options: []) as? [String: Any] {
3780
- //
3781
- // // Extract main billing fields
3782
- // let cleanBillingInfo: [String: Any] = [
3783
- // "postal_code": billingInfoDict["postal_code"] ?? "",
3784
- // "country": billingInfoDict["country"] ?? "",
3785
- // "city": billingInfoDict["city"] ?? "",
3786
- // "address": billingInfoDict["address"] ?? "",
3787
- // "state": billingInfoDict["state"] ?? ""
3788
- // ]
3789
- // paymentDoneVC.billingInfo = cleanBillingInfo
3790
- //
3791
- // // Extract additional_info
3792
- // if let additional = billingInfoDict["additional_info"] as? [String: Any] {
3793
- // let cleanAdditionalInfo: [String: Any] = [
3794
- // "email": additional["email"] ?? "",
3795
- // "phone_number": additional["phone_number"] ?? "",
3796
- // "name": additional["name"] ?? "",
3797
- // "country_code": additional["country_code"] ?? ""
3798
- // ]
3799
- // paymentDoneVC.additionalInfo = cleanAdditionalInfo
3800
- // }
3801
- // }
3802
3418
 
3803
3419
  // Pass billing info and additional info if available
3804
3420
  if let billingInfoData = self.request.billingInfoData,
@@ -3877,13 +3493,13 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
3877
3493
  if let billingInfoData = request.billingInfoData {
3878
3494
  do {
3879
3495
  let fieldSection = try JSONDecoder().decode(FieldSection.self, from: billingInfoData)
3880
-
3496
+
3881
3497
  // Billing Info
3882
3498
  let billing = fieldSection.billing
3883
3499
  if !billing.isEmpty {
3884
3500
  var billingDict: [String: Any] = [:]
3885
3501
  billing.forEach { billingDict[$0.name] = $0.value }
3886
-
3502
+
3887
3503
  if let address = billingDict["address"] as? String, !address.isEmpty {
3888
3504
  params["address"] = address
3889
3505
  }
@@ -3900,19 +3516,19 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
3900
3516
  params["zip"] = postalCode
3901
3517
  }
3902
3518
  }
3903
-
3519
+
3904
3520
  // Additional Info
3905
3521
  let additional = fieldSection.additional
3906
3522
  if !additional.isEmpty {
3907
3523
  var additionalDict: [String: Any] = [:]
3908
3524
  additional.forEach { additionalDict[$0.name] = $0.value }
3909
-
3525
+
3910
3526
  if let desc = additionalDict["description"] as? String, !desc.isEmpty {
3911
3527
  params["description"] = desc
3912
3528
  } else {
3913
3529
  params["description"] = "Hosted payment checkout"
3914
3530
  }
3915
-
3531
+
3916
3532
  if let phone = additionalDict["phone_number"] as? String, !phone.isEmpty {
3917
3533
  params["phone_number"] = phone
3918
3534
  }
@@ -3926,7 +3542,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
3926
3542
  // If no description in additional info, set default
3927
3543
  params["description"] = "Hosted payment checkout"
3928
3544
  }
3929
-
3545
+
3930
3546
  } catch {
3931
3547
  print("Failed to decode FieldSection: \(error)")
3932
3548
  params["description"] = "Hosted payment checkout"
@@ -4132,51 +3748,9 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
4132
3748
  }
4133
3749
  }
4134
3750
 
4135
- // // Redirect based on billing visibility
4136
- // if fieldSection.visibility.billing {
4137
- // let vc = easymerchantsdk.instantiateViewController(withIdentifier: "BillingInfoVC") as! BillingInfoVC
4138
- // vc.cardNumber = cardNumber
4139
- // vc.expiryDate = expiryDate
4140
- // vc.cvv = cvv
4141
- // vc.nameOnCard = cardName
4142
- // vc.selectedPaymentMethod = self.selectedPaymentMethod
4143
- // vc.isSavedForFuture = self.isSavedForFuture
4144
- // vc.request = self.request
4145
- // vc.chosenPlan = self.txtFieldChosePlanCard.text
4146
- // vc.startDate = self.txtFieldStartDateCard.text
4147
- // vc.userEmail = self.txtFieldEmailCardView.text
4148
- // vc.amount = self.amount
4149
- // vc.billingInfoData = billingInfoData
4150
- // vc.billingInfo = fieldSection.billing
4151
- // vc.additionalInfo = fieldSection.additional
4152
- // vc.visibility = fieldSection.visibility
4153
- // vc.easyPayDelegate = self.easyPayDelegate
4154
- // self.navigationController?.pushViewController(vc, animated: true)
4155
- // } else {
4156
- // let vc = easymerchantsdk.instantiateViewController(withIdentifier: "AdditionalInfoVC") as! AdditionalInfoVC
4157
- // vc.billingInfoData = billingInfoData
4158
- // vc.cardNumber = cardNumber
4159
- // vc.expiryDate = expiryDate
4160
- // vc.cvv = cvv
4161
- // vc.nameOnCard = cardName
4162
- // vc.selectedPaymentMethod = self.selectedPaymentMethod
4163
- // vc.isSavedForFuture = self.isSavedForFuture
4164
- // vc.request = self.request
4165
- // vc.chosenPlan = self.txtFieldChosePlanCard.text
4166
- // vc.startDate = self.txtFieldStartDateCard.text
4167
- // vc.userEmail = self.txtFieldEmailCardView.text
4168
- // vc.billingInfo = fieldSection.billing
4169
- // vc.additionalInfo = fieldSection.additional
4170
- // vc.amount = self.amount
4171
- // vc.visibility = fieldSection.visibility
4172
- // vc.easyPayDelegate = self.easyPayDelegate
4173
- // self.navigationController?.pushViewController(vc, animated: true)
4174
- // }
4175
-
4176
-
4177
3751
  let showBilling = fieldSection.visibility.billing
4178
3752
  let showAdditional = fieldSection.visibility.additional
4179
-
3753
+
4180
3754
  if !showBilling && !showAdditional {
4181
3755
  if self.isSavedForFuture {
4182
3756
  self.navigateCardDataToEmailVerificationVC()
@@ -4289,9 +3863,18 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
4289
3863
  }
4290
3864
  }
4291
3865
 
4292
- // Redirect based on billing visibility
4293
- if fieldSection.visibility.billing {
4294
- // Proceed to BillingInfoVC
3866
+ let showBilling = fieldSection.visibility.billing
3867
+ let showAdditional = fieldSection.visibility.additional
3868
+
3869
+ if !showBilling && !showAdditional {
3870
+ if self.isSavedForFuture {
3871
+ self.navigateBankDataToEmailVerificationVC()
3872
+ } else {
3873
+ self.accountBankChargeApi()
3874
+ }
3875
+ }
3876
+ else if showBilling {
3877
+ // Push to BillingInfoVC
4295
3878
  let vc = easymerchantsdk.instantiateViewController(withIdentifier: "BillingInfoVC") as! BillingInfoVC
4296
3879
  vc.accountName = self.txtFieldAccountName.text
4297
3880
  vc.routingNumber = self.txtFieldRoutingNumber.text
@@ -4314,6 +3897,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
4314
3897
  self.navigationController?.pushViewController(vc, animated: true)
4315
3898
  }
4316
3899
  else {
3900
+ // Push to AdditionalInfoVC
4317
3901
  let vc = easymerchantsdk.instantiateViewController(withIdentifier: "AdditionalInfoVC") as! AdditionalInfoVC
4318
3902
  vc.accountName = self.txtFieldAccountName.text
4319
3903
  vc.routingNumber = self.txtFieldRoutingNumber.text
@@ -4517,7 +4101,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
4517
4101
 
4518
4102
  // Function to navigate to EmailVerificationVC
4519
4103
  func navigateCardDataToEmailVerificationVC() {
4520
- // if let emailVerificationVC = storyboard?.instantiateViewController(withIdentifier: "EmailVerificationVC") as? EmailVerificationVC {
4104
+ // if let emailVerificationVC = storyboard?.instantiateViewController(withIdentifier: "EmailVerificationVC") as? EmailVerificationVC {
4521
4105
  if let emailVerificationVC = storyboard?.instantiateViewController(withIdentifier: "OTPVerificationVC") as? OTPVerificationVC {
4522
4106
  if let billingInfoData = request.billingInfoData {
4523
4107
  do {
@@ -4549,9 +4133,10 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
4549
4133
  self.navigationController?.pushViewController(emailVerificationVC, animated: true)
4550
4134
  }
4551
4135
  }
4552
-
4136
+
4553
4137
  func navigateBankDataToEmailVerificationVC() {
4554
- if let emailVerificationVC = storyboard?.instantiateViewController(withIdentifier: "EmailVerificationVC") as? EmailVerificationVC {
4138
+ // if let emailVerificationVC = storyboard?.instantiateViewController(withIdentifier: "EmailVerificationVC") as? EmailVerificationVC {
4139
+ if let emailVerificationVC = storyboard?.instantiateViewController(withIdentifier: "OTPVerificationVC") as? OTPVerificationVC {
4555
4140
  if let billingInfoData = request.billingInfoData {
4556
4141
  do {
4557
4142
  let fieldSection = try JSONDecoder().decode(FieldSection.self, from: billingInfoData)
@@ -4600,10 +4185,6 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
4600
4185
  if selectedPaymentMethod == "Card" {
4601
4186
  self.viewSingleSavedAccount.isHidden = true
4602
4187
  self.viewBankFields.isHidden = true
4603
- // self.viewBtnShowSavedCards.isHidden = false
4604
- // self.lblBtnShowSaveCard.text = "Show Saved Cards"
4605
- // self.viewBtnShowSavedCardHeight.constant = 50
4606
- // self.viewBtnShowSavedCardTopCon.constant = 20
4607
4188
 
4608
4189
  if request.saveCard == false {
4609
4190
  self.viewBtnShowSavedCards.isHidden = true
@@ -4632,10 +4213,6 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
4632
4213
  }
4633
4214
  else if selectedPaymentMethod == "Bank" {
4634
4215
  self.viewBankFields.isHidden = false
4635
- // self.viewBtnShowSavedCards.isHidden = false
4636
- // self.lblBtnShowSaveCard.text = "Show Saved Accounts"
4637
- // self.viewBtnShowSavedCardHeight.constant = 50
4638
- // self.viewBtnShowSavedCardTopCon.constant = 20
4639
4216
 
4640
4217
  if request.saveAccount == false {
4641
4218
  self.viewBtnShowSavedCards.isHidden = true
@@ -4823,50 +4400,15 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
4823
4400
  return
4824
4401
  }
4825
4402
 
4826
- // // Redirect based on billing visibility
4827
- // if fieldSection.visibility.billing {
4828
- // // Proceed with the Pay Now action
4829
- // let vc = easymerchantsdk.instantiateViewController(withIdentifier: "BillingInfoVC") as! BillingInfoVC
4830
- // // Pass the customer_id and account_id to BillingInfoVC
4831
- // vc.customerID = self.selectedbankAccounts?.customer_id
4832
- // vc.accountID = self.selectedbankAccounts?.account_id
4833
- // vc.billingInfoData = billingInfoData
4834
- // vc.isFrom = "SavedBank"
4835
- // vc.selectedPaymentMethod = "Bank"
4836
- // vc.chosenPlan = self.txtFieldSelectPlanSingleSavedBankView.text
4837
- // vc.startDate = self.txtFieldSelectDateSingleSavedBankView.text
4838
- // vc.request = self.request
4839
- // vc.amount = self.amount
4840
- // vc.billingInfo = fieldSection.billing
4841
- // vc.additionalInfo = fieldSection.additional
4842
- // vc.visibility = fieldSection.visibility
4843
- // vc.easyPayDelegate = self.easyPayDelegate
4844
- // self.navigationController?.pushViewController(vc, animated: true)
4845
- // }
4846
- // else {
4847
- // let vc = easymerchantsdk.instantiateViewController(withIdentifier: "AdditionalInfoVC") as! AdditionalInfoVC
4848
- // vc.customerID = self.selectedbankAccounts?.customer_id
4849
- // vc.accountID = self.selectedbankAccounts?.account_id
4850
- // vc.billingInfoData = billingInfoData
4851
- // vc.isFrom = "SavedBank"
4852
- // vc.selectedPaymentMethod = "Bank"
4853
- // vc.chosenPlan = self.txtFieldSelectPlanSingleSavedBankView.text
4854
- // vc.startDate = self.txtFieldSelectDateSingleSavedBankView.text
4855
- // vc.request = self.request
4856
- // vc.amount = self.amount
4857
- // vc.billingInfo = fieldSection.billing
4858
- // vc.additionalInfo = fieldSection.additional
4859
- // vc.visibility = fieldSection.visibility
4860
- // vc.easyPayDelegate = self.easyPayDelegate
4861
- // self.navigationController?.pushViewController(vc, animated: true)
4862
- // }
4863
-
4864
-
4865
4403
  let showBilling = fieldSection.visibility.billing
4866
4404
  let showAdditional = fieldSection.visibility.additional
4867
-
4405
+
4868
4406
  if !showBilling && !showAdditional {
4869
- self.grailPayAaccountChargeSingleSavedAccountApi()
4407
+ if self.request.authenticatedACH == true {
4408
+ self.grailPayAaccountChargeSingleSavedAccountApi()
4409
+ } else {
4410
+ self.accountBankChargeSavedBankAccountApi()
4411
+ }
4870
4412
  }
4871
4413
  else if showBilling {
4872
4414
  // Push to BillingInfoVC
@@ -5015,9 +4557,14 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
5015
4557
  let isSavedNewAccount = self.isSavedNewAccount
5016
4558
  let isFromValue = isSavedNewAccount ? "AddNewAccountWithSave" : "AddNewAccountWithoutSave"
5017
4559
 
5018
- // Redirect based on billing visibility
5019
- if fieldSection.visibility.billing {
5020
- // Proceed with the Pay Now action
4560
+ let showBilling = fieldSection.visibility.billing
4561
+ let showAdditional = fieldSection.visibility.additional
4562
+
4563
+ if !showBilling && !showAdditional {
4564
+ self.accountBankChargeAddNewAccountApi()
4565
+ }
4566
+ else if showBilling {
4567
+ // Push to BillingInfoVC
5021
4568
  let vc = easymerchantsdk.instantiateViewController(withIdentifier: "BillingInfoVC") as! BillingInfoVC
5022
4569
  vc.accountName = accountName
5023
4570
  vc.routingNumber = routingNumber
@@ -5040,6 +4587,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
5040
4587
  self.navigationController?.pushViewController(vc, animated: true)
5041
4588
  }
5042
4589
  else {
4590
+ // Push to AdditionalInfoVC
5043
4591
  let vc = easymerchantsdk.instantiateViewController(withIdentifier: "AdditionalInfoVC") as! AdditionalInfoVC
5044
4592
  vc.accountName = accountName
5045
4593
  vc.routingNumber = routingNumber
@@ -5867,13 +5415,13 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
5867
5415
  if let billingInfoData = request.billingInfoData {
5868
5416
  do {
5869
5417
  let fieldSection = try JSONDecoder().decode(FieldSection.self, from: billingInfoData)
5870
-
5418
+
5871
5419
  // Billing Info
5872
5420
  let billing = fieldSection.billing
5873
5421
  if !billing.isEmpty {
5874
5422
  var billingDict: [String: Any] = [:]
5875
5423
  billing.forEach { billingDict[$0.name] = $0.value }
5876
-
5424
+
5877
5425
  if let address = billingDict["address"] as? String, !address.isEmpty {
5878
5426
  params["address"] = address
5879
5427
  }
@@ -5890,19 +5438,19 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
5890
5438
  params["zip"] = postalCode
5891
5439
  }
5892
5440
  }
5893
-
5441
+
5894
5442
  // Additional Info
5895
5443
  let additional = fieldSection.additional
5896
5444
  if !additional.isEmpty {
5897
5445
  var additionalDict: [String: Any] = [:]
5898
5446
  additional.forEach { additionalDict[$0.name] = $0.value }
5899
-
5447
+
5900
5448
  if let desc = additionalDict["description"] as? String, !desc.isEmpty {
5901
5449
  params["description"] = desc
5902
5450
  } else {
5903
5451
  params["description"] = "Hosted payment checkout"
5904
5452
  }
5905
-
5453
+
5906
5454
  if let phone = additionalDict["phone_number"] as? String, !phone.isEmpty {
5907
5455
  params["phone_number"] = phone
5908
5456
  }
@@ -5916,7 +5464,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
5916
5464
  // If no description in additional info, set default
5917
5465
  params["description"] = "Hosted payment checkout"
5918
5466
  }
5919
-
5467
+
5920
5468
  } catch {
5921
5469
  print("Failed to decode FieldSection: \(error)")
5922
5470
  params["description"] = "Hosted payment checkout"
@@ -6007,7 +5555,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
6007
5555
  var billingDict: [String: Any] = [:]
6008
5556
  filteredBilling.forEach { billingDict[$0.name] = $0.value }
6009
5557
  paymentDoneVC.billingInfo = billingDict
6010
-
5558
+
6011
5559
  // Filter additional info: only include non-empty values
6012
5560
  let filteredAdditional = fieldSection.additional.filter { !($0.value.trimmingCharacters(in: .whitespaces).isEmpty) }
6013
5561
  paymentDoneVC.additionalInfoData = filteredAdditional
@@ -6234,13 +5782,13 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
6234
5782
  if let billingInfoData = request.billingInfoData {
6235
5783
  do {
6236
5784
  let fieldSection = try JSONDecoder().decode(FieldSection.self, from: billingInfoData)
6237
-
5785
+
6238
5786
  // Billing Info
6239
5787
  let billing = fieldSection.billing
6240
5788
  if !billing.isEmpty {
6241
5789
  var billingDict: [String: Any] = [:]
6242
5790
  billing.forEach { billingDict[$0.name] = $0.value }
6243
-
5791
+
6244
5792
  if let address = billingDict["address"] as? String, !address.isEmpty {
6245
5793
  params["address"] = address
6246
5794
  }
@@ -6257,19 +5805,19 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
6257
5805
  params["zip"] = postalCode
6258
5806
  }
6259
5807
  }
6260
-
5808
+
6261
5809
  // Additional Info
6262
5810
  let additional = fieldSection.additional
6263
5811
  if !additional.isEmpty {
6264
5812
  var additionalDict: [String: Any] = [:]
6265
5813
  additional.forEach { additionalDict[$0.name] = $0.value }
6266
-
5814
+
6267
5815
  if let desc = additionalDict["description"] as? String, !desc.isEmpty {
6268
5816
  params["description"] = desc
6269
5817
  } else {
6270
5818
  params["description"] = "Hosted payment checkout"
6271
5819
  }
6272
-
5820
+
6273
5821
  if let phone = additionalDict["phone_number"] as? String, !phone.isEmpty {
6274
5822
  params["phone_number"] = phone
6275
5823
  }
@@ -6283,7 +5831,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
6283
5831
  // If no description in additional info, set default
6284
5832
  params["description"] = "Hosted payment checkout"
6285
5833
  }
6286
-
5834
+
6287
5835
  } catch {
6288
5836
  print("Failed to decode FieldSection: \(error)")
6289
5837
  params["description"] = "Hosted payment checkout"
@@ -6371,7 +5919,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
6371
5919
  var billingDict: [String: Any] = [:]
6372
5920
  filteredBilling.forEach { billingDict[$0.name] = $0.value }
6373
5921
  paymentDoneVC.billingInfo = billingDict
6374
-
5922
+
6375
5923
  // Filter additional info: only include non-empty values
6376
5924
  let filteredAdditional = fieldSection.additional.filter { !($0.value.trimmingCharacters(in: .whitespaces).isEmpty) }
6377
5925
  paymentDoneVC.additionalInfoData = filteredAdditional
@@ -6698,13 +6246,13 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
6698
6246
  if let billingInfoData = request.billingInfoData {
6699
6247
  do {
6700
6248
  let fieldSection = try JSONDecoder().decode(FieldSection.self, from: billingInfoData)
6701
-
6249
+
6702
6250
  // Billing Info
6703
6251
  let billing = fieldSection.billing
6704
6252
  if !billing.isEmpty {
6705
6253
  var billingDict: [String: Any] = [:]
6706
6254
  billing.forEach { billingDict[$0.name] = $0.value }
6707
-
6255
+
6708
6256
  if let address = billingDict["address"] as? String, !address.isEmpty {
6709
6257
  params["address"] = address
6710
6258
  }
@@ -6721,19 +6269,19 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
6721
6269
  params["zip"] = postalCode
6722
6270
  }
6723
6271
  }
6724
-
6272
+
6725
6273
  // Additional Info
6726
6274
  let additional = fieldSection.additional
6727
6275
  if !additional.isEmpty {
6728
6276
  var additionalDict: [String: Any] = [:]
6729
6277
  additional.forEach { additionalDict[$0.name] = $0.value }
6730
-
6278
+
6731
6279
  if let desc = additionalDict["description"] as? String, !desc.isEmpty {
6732
6280
  params["description"] = desc
6733
6281
  } else {
6734
6282
  params["description"] = "Hosted payment checkout"
6735
6283
  }
6736
-
6284
+
6737
6285
  if let phone = additionalDict["phone_number"] as? String, !phone.isEmpty {
6738
6286
  params["phone_number"] = phone
6739
6287
  }
@@ -6747,7 +6295,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
6747
6295
  // If no description in additional info, set default
6748
6296
  params["description"] = "Hosted payment checkout"
6749
6297
  }
6750
-
6298
+
6751
6299
  } catch {
6752
6300
  print("Failed to decode FieldSection: \(error)")
6753
6301
  params["description"] = "Hosted payment checkout"
@@ -6845,7 +6393,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
6845
6393
  var billingDict: [String: Any] = [:]
6846
6394
  filteredBilling.forEach { billingDict[$0.name] = $0.value }
6847
6395
  paymentDoneVC.billingInfo = billingDict
6848
-
6396
+
6849
6397
  // Filter additional info: only include non-empty values
6850
6398
  let filteredAdditional = fieldSection.additional.filter { !($0.value.trimmingCharacters(in: .whitespaces).isEmpty) }
6851
6399
  paymentDoneVC.additionalInfoData = filteredAdditional
@@ -7042,11 +6590,12 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
7042
6590
  task.resume()
7043
6591
  }
7044
6592
 
7045
- //MARK: - Delete Cards Api.
6593
+ // MARK: - Delete Card API
7046
6594
  func deleteCardApi(cardID: String, at index: Int) {
7047
6595
  showLoadingIndicator()
7048
6596
 
7049
- let fullURL = EnvironmentConfig.baseURL + EnvironmentConfig.Endpoints.getCards.path()+"/\(cardID)"
6597
+ let endpoint = EnvironmentConfig.Endpoints.getCards.path()
6598
+ let fullURL = EnvironmentConfig.baseURL + "\(endpoint)/\(cardID)"
7050
6599
 
7051
6600
  guard let serviceURL = URL(string: fullURL) else {
7052
6601
  print("Invalid URL")
@@ -7058,68 +6607,70 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
7058
6607
  request.httpMethod = "DELETE"
7059
6608
  request.addValue("application/json", forHTTPHeaderField: "Content-Type")
7060
6609
 
7061
- let token = UserStoreSingleton.shared.customerToken
7062
- print("Setting customerToken header: \(token ?? "None")")
7063
- request.addValue(token ?? "", forHTTPHeaderField: "Customer-Token")
6610
+ // Add Customer-Token
6611
+ if let token = UserStoreSingleton.shared.customerToken {
6612
+ request.addValue(token, forHTTPHeaderField: "Customer-Token")
6613
+ } else {
6614
+ print("Customer-Token is nil")
6615
+ }
7064
6616
 
7065
6617
  // Add API headers
7066
- if let apiKey = EnvironmentConfig.apiKey,
7067
- let apiSecret = EnvironmentConfig.apiSecret {
6618
+ if let apiKey = EnvironmentConfig.apiKey {
7068
6619
  request.addValue(apiKey, forHTTPHeaderField: "x-api-key")
6620
+ }
6621
+ if let apiSecret = EnvironmentConfig.apiSecret {
7069
6622
  request.addValue(apiSecret, forHTTPHeaderField: "x-api-secret")
7070
6623
  }
7071
6624
 
7072
6625
  let session = URLSession.shared
7073
- let task = session.dataTask(with: request) { [weak self] (serviceData, serviceResponse, error) in
6626
+ let task = session.dataTask(with: request) { [weak self] data, response, error in
7074
6627
  guard let self = self else { return }
7075
6628
 
7076
6629
  DispatchQueue.main.async {
7077
- self.hideLoadingIndicator() // Stop loader when response is received
6630
+ self.hideLoadingIndicator()
7078
6631
  }
7079
6632
 
7080
6633
  if let error = error {
7081
6634
  DispatchQueue.main.async {
7082
- self.presentPaymentErrorVC(errorMessage: error.localizedDescription)
6635
+ self.presentPaymentErrorVC(errorMessage: "Request failed: \(error.localizedDescription)")
7083
6636
  }
7084
6637
  return
7085
6638
  }
7086
6639
 
7087
- guard let httpResponse = serviceResponse as? HTTPURLResponse else {
6640
+ guard let httpResponse = response as? HTTPURLResponse else {
7088
6641
  DispatchQueue.main.async {
7089
- self.presentPaymentErrorVC(errorMessage: "Invalid response")
6642
+ self.presentPaymentErrorVC(errorMessage: "Invalid server response")
7090
6643
  }
7091
6644
  return
7092
6645
  }
7093
6646
 
7094
- if httpResponse.statusCode == 200 || httpResponse.statusCode == 201 {
7095
-
7096
- if let data = serviceData {
6647
+ if (200...299).contains(httpResponse.statusCode) {
6648
+ if let data = data {
7097
6649
  do {
7098
- // Try to parse the data as JSON
7099
- if let jsonResponse = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
7100
- let message = jsonResponse["message"] as? String {
6650
+ if let json = try JSONSerialization.jsonObject(with: data) as? [String: Any],
6651
+ let message = json["message"] as? String {
7101
6652
  DispatchQueue.main.async {
7102
6653
  self.showToast(message: message)
6654
+ // Optionally, remove the card from list at `index`
7103
6655
  }
7104
6656
  }
7105
- } catch let jsonError {
7106
- print("Error parsing JSON response: \(jsonError.localizedDescription)")
6657
+ } catch {
6658
+ print("JSON parsing error: \(error)")
7107
6659
  }
7108
- } else {
7109
- print("No data received.")
7110
6660
  }
7111
6661
  } else {
7112
6662
  DispatchQueue.main.async {
7113
- if let data = serviceData,
7114
- let responseObj = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
7115
- let message = responseObj["message"] as? String {
6663
+ if let data = data,
6664
+ let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
6665
+ let message = json["message"] as? String {
7116
6666
  self.presentPaymentErrorVC(errorMessage: message)
7117
6667
  } else {
7118
- self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
6668
+ self.presentPaymentErrorVC(errorMessage: "Failed with status: \(httpResponse.statusCode)")
7119
6669
  }
7120
6670
  }
7121
6671
  }
7122
6672
  }
6673
+
7123
6674
  task.resume()
7124
6675
  }
7125
6676
 
@@ -7438,10 +6989,9 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
7438
6989
  task.resume()
7439
6990
  }
7440
6991
 
7441
- //MARK: - Banking Account Charge Api from Regular saved bank account if Billing info is nil
7442
- func accountChargeSavedBankAccountApi() {
6992
+ //MARK: - Banking Account Charge Api If Billing info is availalbe but their visibility is false
6993
+ func accountBankChargeApi() {
7443
6994
  showLoadingIndicator()
7444
-
7445
6995
  let fullURL = EnvironmentConfig.baseURL + EnvironmentConfig.Endpoints.achCharge.path()
7446
6996
 
7447
6997
  guard let serviceURL = URL(string: fullURL) else {
@@ -7466,41 +7016,635 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
7466
7016
  }
7467
7017
 
7468
7018
  var params: [String: Any] = [
7469
- "account_id": selectedbankAccounts?.account_id ?? "",
7470
- "customer": selectedbankAccounts?.customer_id ?? "",
7471
- "payment_method": "ach",
7472
- "description": "Test Description",
7019
+ "name": txtFieldAccountName.text ?? "",
7020
+ "email": "test@gmail.com",
7021
+ "description": "TestDescription",
7473
7022
  "currency": "usd",
7023
+ "account_type": txtFieldAccountType.text?.lowercased() ?? "",
7024
+ "routing_number": txtFieldRoutingNumber.text?.replacingOccurrences(of: " ", with: "") ?? "",
7025
+ "account_number": txtFieldAccountNumber.text?.replacingOccurrences(of: " ", with: "") ?? "",
7026
+ "payment_mode": "auth_and_capture",
7027
+ "payment_intent": UserStoreSingleton.shared.paymentIntent ?? "",
7028
+ "levelIndicator": 1,
7474
7029
  ]
7475
7030
 
7476
- // Add these if recurring is enabled
7477
- if let req = request, req.is_recurring == true {
7478
- if let recurringType = req.recurringStartDateType, recurringType == .custom {
7479
- // Only send start_date if type is .custom and field is not empty
7480
- if let startDateText = txtFieldSelectDateSingleSavedBankView?.text, !startDateText.isEmpty {
7481
- let inputFormatter = DateFormatter()
7482
- inputFormatter.dateFormat = "dd/MM/yyyy"
7483
-
7484
- let outputFormatter = DateFormatter()
7485
- outputFormatter.dateFormat = "MM/dd/yyyy"
7031
+ if let billingInfoData = request.billingInfoData {
7032
+ do {
7033
+ let fieldSection = try JSONDecoder().decode(FieldSection.self, from: billingInfoData)
7034
+
7035
+ // Billing Info
7036
+ let billing = fieldSection.billing
7037
+ if !billing.isEmpty {
7038
+ var billingDict: [String: Any] = [:]
7039
+ billing.forEach { billingDict[$0.name] = $0.value }
7486
7040
 
7487
- if let date = inputFormatter.date(from: startDateText) {
7488
- let apiFormattedDate = outputFormatter.string(from: date)
7489
- params["start_date"] = apiFormattedDate
7490
- } else {
7491
- print("Invalid date format in startDateText")
7041
+ if let address = billingDict["address"] as? String, !address.isEmpty {
7042
+ params["address"] = address
7492
7043
  }
7493
- }
7494
- }
7495
-
7496
- params["interval"] = txtFieldSelectPlanSingleSavedBankView.text.lowercased()
7497
- }
7498
-
7499
- print(params)
7500
-
7501
- do {
7502
- let jsonData = try JSONSerialization.data(withJSONObject: params, options: .prettyPrinted)
7503
- uRLRequest.httpBody = jsonData
7044
+ if let country = billingDict["country"] as? String, !country.isEmpty {
7045
+ params["country"] = country
7046
+ }
7047
+ if let state = billingDict["state"] as? String, !state.isEmpty {
7048
+ params["state"] = state
7049
+ }
7050
+ if let city = billingDict["city"] as? String, !city.isEmpty {
7051
+ params["city"] = city
7052
+ }
7053
+ if let postalCode = billingDict["postal_code"] as? String, !postalCode.isEmpty {
7054
+ params["zip"] = postalCode
7055
+ }
7056
+ }
7057
+
7058
+ // Additional Info
7059
+ let additional = fieldSection.additional
7060
+ if !additional.isEmpty {
7061
+ var additionalDict: [String: Any] = [:]
7062
+ additional.forEach { additionalDict[$0.name] = $0.value }
7063
+
7064
+ if let desc = additionalDict["description"] as? String, !desc.isEmpty {
7065
+ params["description"] = desc
7066
+ } else {
7067
+ params["description"] = "Hosted payment checkout"
7068
+ }
7069
+
7070
+ if let phone = additionalDict["phone_number"] as? String, !phone.isEmpty {
7071
+ params["phone_number"] = phone
7072
+ }
7073
+ if let email = additionalDict["email"] as? String, !email.isEmpty {
7074
+ params["email"] = email
7075
+ }
7076
+ if let name = additionalDict["name"] as? String, !name.isEmpty {
7077
+ params["name"] = name
7078
+ }
7079
+ } else {
7080
+ // If no description in additional info, set default
7081
+ params["description"] = "Hosted payment checkout"
7082
+ }
7083
+
7084
+ } catch {
7085
+ print("Failed to decode FieldSection: \(error)")
7086
+ params["description"] = "Hosted payment checkout"
7087
+ }
7088
+ } else {
7089
+ // Fallback if billingInfoData is missing
7090
+ params["description"] = "Hosted payment checkout"
7091
+ }
7092
+
7093
+ // Add these if recurring is enabled
7094
+ if let req = request, req.is_recurring == true {
7095
+ if let recurringType = req.recurringStartDateType, recurringType == .custom {
7096
+ // Only send start_date if type is .custom and field is not empty
7097
+ if let startDateText = txtFieldSelectDateViewBankFields?.text, !startDateText.isEmpty {
7098
+ let inputFormatter = DateFormatter()
7099
+ inputFormatter.dateFormat = "dd/MM/yyyy"
7100
+
7101
+ let outputFormatter = DateFormatter()
7102
+ outputFormatter.dateFormat = "MM/dd/yyyy"
7103
+
7104
+ if let date = inputFormatter.date(from: startDateText) {
7105
+ let apiFormattedDate = outputFormatter.string(from: date)
7106
+ params["start_date"] = apiFormattedDate
7107
+ } else {
7108
+ print("Invalid date format in startDateText")
7109
+ }
7110
+ }
7111
+ }
7112
+
7113
+ params["interval"] = txtFieldSelectPlanViewBankFields.text.lowercased()
7114
+ }
7115
+
7116
+ do {
7117
+ let jsonData = try JSONSerialization.data(withJSONObject: params, options: .prettyPrinted)
7118
+ uRLRequest.httpBody = jsonData
7119
+ if let jsonString = String(data: jsonData, encoding: .utf8) {
7120
+ print("JSON Payload: \(jsonString)")
7121
+ }
7122
+ } catch let error {
7123
+ print("Error creating JSON data: \(error)")
7124
+ hideLoadingIndicator()
7125
+ return
7126
+ }
7127
+
7128
+ let session = URLSession.shared
7129
+ let task = session.dataTask(with: uRLRequest) { (serviceData, serviceResponse, error) in
7130
+
7131
+ DispatchQueue.main.async {
7132
+ self.hideLoadingIndicator() // Stop loader when response is received
7133
+ }
7134
+
7135
+ if let error = error {
7136
+ print("Error: \(error.localizedDescription)")
7137
+ return
7138
+ }
7139
+
7140
+ guard let httpResponse = serviceResponse as? HTTPURLResponse else {
7141
+ print("Invalid response")
7142
+ return
7143
+ }
7144
+
7145
+ if httpResponse.statusCode == 200 || httpResponse.statusCode == 201 {
7146
+ if let data = serviceData {
7147
+ do {
7148
+ if let responseObject = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
7149
+ print("Response Data: \(responseObject)")
7150
+
7151
+ // Check if status is 0 and handle the error
7152
+ if let status = responseObject["status"] as? Int, status == 0 {
7153
+ let errorMessage = responseObject["message"] as? String ?? "Unknown error"
7154
+ self.presentPaymentErrorVC(errorMessage: errorMessage)
7155
+ } else {
7156
+ DispatchQueue.main.async {
7157
+ if let paymentDoneVC = self.storyboard?.instantiateViewController(withIdentifier: "PaymentDoneVC") as? PaymentDoneVC {
7158
+ paymentDoneVC.chargeData = responseObject
7159
+ // Pass the selected payment method
7160
+ paymentDoneVC.selectedPaymentMethod = self.selectedPaymentMethod
7161
+ paymentDoneVC.easyPayDelegate = self.easyPayDelegate
7162
+ // Pass billing info and additional info if available
7163
+ if let billingInfoData = self.request.billingInfoData,
7164
+ let fieldSection = try? JSONDecoder().decode(FieldSection.self, from: billingInfoData) {
7165
+
7166
+ // Filter billing info: only include non-empty values
7167
+ let filteredBilling = fieldSection.billing.filter { !($0.value.trimmingCharacters(in: .whitespaces).isEmpty) }
7168
+ paymentDoneVC.billingInfoData = filteredBilling
7169
+ var billingDict: [String: Any] = [:]
7170
+ filteredBilling.forEach { billingDict[$0.name] = $0.value }
7171
+ paymentDoneVC.billingInfo = billingDict
7172
+
7173
+ // Filter additional info: only include non-empty values
7174
+ let filteredAdditional = fieldSection.additional.filter { !($0.value.trimmingCharacters(in: .whitespaces).isEmpty) }
7175
+ paymentDoneVC.additionalInfoData = filteredAdditional
7176
+ var additionalDict: [String: Any] = [:]
7177
+ filteredAdditional.forEach { additionalDict[$0.name] = $0.value }
7178
+ paymentDoneVC.additionalInfo = additionalDict
7179
+ }
7180
+ self.navigationController?.pushViewController(paymentDoneVC, animated: true)
7181
+ }
7182
+ }
7183
+ }
7184
+ } else {
7185
+ self.presentPaymentErrorVC(errorMessage: "Invalid JSON format")
7186
+ }
7187
+ } catch let jsonError {
7188
+ self.presentPaymentErrorVC(errorMessage: "Error parsing JSON: \(jsonError)")
7189
+ }
7190
+ } else {
7191
+ self.presentPaymentErrorVC(errorMessage: "No data received")
7192
+ }
7193
+ } else {
7194
+ if let data = serviceData,
7195
+ let responseObj = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
7196
+ let message = responseObj["message"] as? String {
7197
+ self.presentPaymentErrorVC(errorMessage: message)
7198
+ } else {
7199
+ self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
7200
+ }
7201
+ }
7202
+ }
7203
+ task.resume()
7204
+ }
7205
+
7206
+ //MARK: - Banking Account Charge Api from Regular saved bank account if Billing info is nil
7207
+ func accountChargeSavedBankAccountApi() {
7208
+ showLoadingIndicator()
7209
+
7210
+ let fullURL = EnvironmentConfig.baseURL + EnvironmentConfig.Endpoints.achCharge.path()
7211
+
7212
+ guard let serviceURL = URL(string: fullURL) else {
7213
+ print("Invalid URL")
7214
+ hideLoadingIndicator()
7215
+ return
7216
+ }
7217
+
7218
+ var uRLRequest = URLRequest(url: serviceURL)
7219
+ uRLRequest.httpMethod = "POST"
7220
+ uRLRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
7221
+
7222
+ let token = UserStoreSingleton.shared.clientToken
7223
+ print("Setting clientToken header: \(token ?? "None")")
7224
+ uRLRequest.addValue(token ?? "", forHTTPHeaderField: "Client-Token")
7225
+
7226
+ // Add API headers
7227
+ if let apiKey = EnvironmentConfig.apiKey,
7228
+ let apiSecret = EnvironmentConfig.apiSecret {
7229
+ uRLRequest.addValue(apiKey, forHTTPHeaderField: "x-api-key")
7230
+ uRLRequest.addValue(apiSecret, forHTTPHeaderField: "x-api-secret")
7231
+ }
7232
+
7233
+ var params: [String: Any] = [
7234
+ "account_id": selectedbankAccounts?.account_id ?? "",
7235
+ "customer": selectedbankAccounts?.customer_id ?? "",
7236
+ "payment_method": "ach",
7237
+ "description": "Test Description",
7238
+ "currency": "usd",
7239
+ ]
7240
+
7241
+ // Add these if recurring is enabled
7242
+ if let req = request, req.is_recurring == true {
7243
+ if let recurringType = req.recurringStartDateType, recurringType == .custom {
7244
+ // Only send start_date if type is .custom and field is not empty
7245
+ if let startDateText = txtFieldSelectDateSingleSavedBankView?.text, !startDateText.isEmpty {
7246
+ let inputFormatter = DateFormatter()
7247
+ inputFormatter.dateFormat = "dd/MM/yyyy"
7248
+
7249
+ let outputFormatter = DateFormatter()
7250
+ outputFormatter.dateFormat = "MM/dd/yyyy"
7251
+
7252
+ if let date = inputFormatter.date(from: startDateText) {
7253
+ let apiFormattedDate = outputFormatter.string(from: date)
7254
+ params["start_date"] = apiFormattedDate
7255
+ } else {
7256
+ print("Invalid date format in startDateText")
7257
+ }
7258
+ }
7259
+ }
7260
+
7261
+ params["interval"] = txtFieldSelectPlanSingleSavedBankView.text.lowercased()
7262
+ }
7263
+
7264
+ print(params)
7265
+
7266
+ do {
7267
+ let jsonData = try JSONSerialization.data(withJSONObject: params, options: .prettyPrinted)
7268
+ uRLRequest.httpBody = jsonData
7269
+ if let jsonString = String(data: jsonData, encoding: .utf8) {
7270
+ print("JSON Payload: \(jsonString)")
7271
+ }
7272
+ } catch let error {
7273
+ print("Error creating JSON data: \(error)")
7274
+ hideLoadingIndicator()
7275
+ return
7276
+ }
7277
+
7278
+ let session = URLSession.shared
7279
+ let task = session.dataTask(with: uRLRequest) { (serviceData, serviceResponse, error) in
7280
+
7281
+ DispatchQueue.main.async {
7282
+ self.hideLoadingIndicator() // Stop loader when response is received
7283
+ }
7284
+
7285
+ if let error = error {
7286
+ print("Error: \(error.localizedDescription)")
7287
+ return
7288
+ }
7289
+
7290
+ guard let httpResponse = serviceResponse as? HTTPURLResponse else {
7291
+ print("Invalid response")
7292
+ return
7293
+ }
7294
+
7295
+ if httpResponse.statusCode == 200 || httpResponse.statusCode == 201 {
7296
+ if let data = serviceData {
7297
+ do {
7298
+ if let responseObject = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
7299
+ print("Response Data: \(responseObject)")
7300
+
7301
+ // Check if status is 0 and handle the error
7302
+ if let status = responseObject["status"] as? Int, status == 0 {
7303
+ let errorMessage = responseObject["message"] as? String ?? "Unknown error"
7304
+ self.presentPaymentErrorVC(errorMessage: errorMessage)
7305
+ } else {
7306
+ DispatchQueue.main.async {
7307
+ if let paymentDoneVC = self.storyboard?.instantiateViewController(withIdentifier: "PaymentDoneVC") as? PaymentDoneVC {
7308
+ paymentDoneVC.chargeData = responseObject
7309
+ // Pass the selected payment method
7310
+ paymentDoneVC.selectedPaymentMethod = self.selectedPaymentMethod
7311
+ paymentDoneVC.easyPayDelegate = self.easyPayDelegate
7312
+ // Pass billingInfo and additionalInfo
7313
+ if let billingData = self.request.billingInfoData,
7314
+ let billingInfoDict = try? JSONSerialization.jsonObject(with: billingData, options: []) as? [String: Any] {
7315
+
7316
+ // Extract main billing fields
7317
+ let cleanBillingInfo: [String: Any] = [
7318
+ "postal_code": billingInfoDict["postal_code"] ?? "",
7319
+ "country": billingInfoDict["country"] ?? "",
7320
+ "city": billingInfoDict["city"] ?? "",
7321
+ "address": billingInfoDict["address"] ?? "",
7322
+ "state": billingInfoDict["state"] ?? ""
7323
+ ]
7324
+ paymentDoneVC.billingInfo = cleanBillingInfo
7325
+
7326
+ // Extract additional_info
7327
+ if let additional = billingInfoDict["additional_info"] as? [String: Any] {
7328
+ let cleanAdditionalInfo: [String: Any] = [
7329
+ "email": additional["email"] ?? "",
7330
+ "phone_number": additional["phone_number"] ?? "",
7331
+ "name": additional["name"] ?? "",
7332
+ "country_code": additional["country_code"] ?? ""
7333
+ ]
7334
+ paymentDoneVC.additionalInfo = cleanAdditionalInfo
7335
+ }
7336
+ }
7337
+ self.navigationController?.pushViewController(paymentDoneVC, animated: true)
7338
+ }
7339
+ }
7340
+ }
7341
+ } else {
7342
+ self.presentPaymentErrorVC(errorMessage: "Invalid JSON format")
7343
+ }
7344
+ } catch let jsonError {
7345
+ self.presentPaymentErrorVC(errorMessage: "Error parsing JSON: \(jsonError)")
7346
+ }
7347
+ } else {
7348
+ self.presentPaymentErrorVC(errorMessage: "No data received")
7349
+ }
7350
+ } else {
7351
+ if let data = serviceData,
7352
+ let responseObj = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
7353
+ let message = responseObj["message"] as? String {
7354
+ self.presentPaymentErrorVC(errorMessage: message)
7355
+ } else {
7356
+ self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
7357
+ }
7358
+ }
7359
+ }
7360
+ task.resume()
7361
+ }
7362
+
7363
+ //MARK: - Banking Account Charge Api from Regular saved bank account if Billing info is available but their visibility is false
7364
+ func accountBankChargeSavedBankAccountApi() {
7365
+ showLoadingIndicator()
7366
+
7367
+ let fullURL = EnvironmentConfig.baseURL + EnvironmentConfig.Endpoints.achCharge.path()
7368
+
7369
+ guard let serviceURL = URL(string: fullURL) else {
7370
+ print("Invalid URL")
7371
+ hideLoadingIndicator()
7372
+ return
7373
+ }
7374
+
7375
+ var uRLRequest = URLRequest(url: serviceURL)
7376
+ uRLRequest.httpMethod = "POST"
7377
+ uRLRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
7378
+
7379
+ let token = UserStoreSingleton.shared.clientToken
7380
+ print("Setting clientToken header: \(token ?? "None")")
7381
+ uRLRequest.addValue(token ?? "", forHTTPHeaderField: "Client-Token")
7382
+
7383
+ // Add API headers
7384
+ if let apiKey = EnvironmentConfig.apiKey,
7385
+ let apiSecret = EnvironmentConfig.apiSecret {
7386
+ uRLRequest.addValue(apiKey, forHTTPHeaderField: "x-api-key")
7387
+ uRLRequest.addValue(apiSecret, forHTTPHeaderField: "x-api-secret")
7388
+ }
7389
+
7390
+ var params: [String: Any] = [
7391
+ "account_id": selectedbankAccounts?.account_id ?? "",
7392
+ "customer": selectedbankAccounts?.customer_id ?? "",
7393
+ "payment_method": "ach",
7394
+ "description": "Test Description",
7395
+ "currency": "usd",
7396
+ ]
7397
+
7398
+ if let billingInfoData = request.billingInfoData {
7399
+ do {
7400
+ let fieldSection = try JSONDecoder().decode(FieldSection.self, from: billingInfoData)
7401
+
7402
+ // Billing Info
7403
+ let billing = fieldSection.billing
7404
+ if !billing.isEmpty {
7405
+ var billingDict: [String: Any] = [:]
7406
+ billing.forEach { billingDict[$0.name] = $0.value }
7407
+
7408
+ if let address = billingDict["address"] as? String, !address.isEmpty {
7409
+ params["address"] = address
7410
+ }
7411
+ if let country = billingDict["country"] as? String, !country.isEmpty {
7412
+ params["country"] = country
7413
+ }
7414
+ if let state = billingDict["state"] as? String, !state.isEmpty {
7415
+ params["state"] = state
7416
+ }
7417
+ if let city = billingDict["city"] as? String, !city.isEmpty {
7418
+ params["city"] = city
7419
+ }
7420
+ if let postalCode = billingDict["postal_code"] as? String, !postalCode.isEmpty {
7421
+ params["zip"] = postalCode
7422
+ }
7423
+ }
7424
+
7425
+ // Additional Info
7426
+ let additional = fieldSection.additional
7427
+ if !additional.isEmpty {
7428
+ var additionalDict: [String: Any] = [:]
7429
+ additional.forEach { additionalDict[$0.name] = $0.value }
7430
+
7431
+ if let desc = additionalDict["description"] as? String, !desc.isEmpty {
7432
+ params["description"] = desc
7433
+ } else {
7434
+ params["description"] = "Hosted payment checkout"
7435
+ }
7436
+
7437
+ if let phone = additionalDict["phone_number"] as? String, !phone.isEmpty {
7438
+ params["phone_number"] = phone
7439
+ }
7440
+ if let email = additionalDict["email"] as? String, !email.isEmpty {
7441
+ params["email"] = email
7442
+ }
7443
+ if let name = additionalDict["name"] as? String, !name.isEmpty {
7444
+ params["name"] = name
7445
+ }
7446
+ } else {
7447
+ // If no description in additional info, set default
7448
+ params["description"] = "Hosted payment checkout"
7449
+ }
7450
+
7451
+ } catch {
7452
+ print("Failed to decode FieldSection: \(error)")
7453
+ params["description"] = "Hosted payment checkout"
7454
+ }
7455
+ } else {
7456
+ // Fallback if billingInfoData is missing
7457
+ params["description"] = "Hosted payment checkout"
7458
+ }
7459
+
7460
+ // Add these if recurring is enabled
7461
+ if let req = request, req.is_recurring == true {
7462
+ if let recurringType = req.recurringStartDateType, recurringType == .custom {
7463
+ // Only send start_date if type is .custom and field is not empty
7464
+ if let startDateText = txtFieldSelectDateSingleSavedBankView?.text, !startDateText.isEmpty {
7465
+ let inputFormatter = DateFormatter()
7466
+ inputFormatter.dateFormat = "dd/MM/yyyy"
7467
+
7468
+ let outputFormatter = DateFormatter()
7469
+ outputFormatter.dateFormat = "MM/dd/yyyy"
7470
+
7471
+ if let date = inputFormatter.date(from: startDateText) {
7472
+ let apiFormattedDate = outputFormatter.string(from: date)
7473
+ params["start_date"] = apiFormattedDate
7474
+ } else {
7475
+ print("Invalid date format in startDateText")
7476
+ }
7477
+ }
7478
+ }
7479
+
7480
+ params["interval"] = txtFieldSelectPlanSingleSavedBankView.text.lowercased()
7481
+ }
7482
+
7483
+ print(params)
7484
+
7485
+ do {
7486
+ let jsonData = try JSONSerialization.data(withJSONObject: params, options: .prettyPrinted)
7487
+ uRLRequest.httpBody = jsonData
7488
+ if let jsonString = String(data: jsonData, encoding: .utf8) {
7489
+ print("JSON Payload: \(jsonString)")
7490
+ }
7491
+ } catch let error {
7492
+ print("Error creating JSON data: \(error)")
7493
+ hideLoadingIndicator()
7494
+ return
7495
+ }
7496
+
7497
+ let session = URLSession.shared
7498
+ let task = session.dataTask(with: uRLRequest) { (serviceData, serviceResponse, error) in
7499
+
7500
+ DispatchQueue.main.async {
7501
+ self.hideLoadingIndicator() // Stop loader when response is received
7502
+ }
7503
+
7504
+ if let error = error {
7505
+ print("Error: \(error.localizedDescription)")
7506
+ return
7507
+ }
7508
+
7509
+ guard let httpResponse = serviceResponse as? HTTPURLResponse else {
7510
+ print("Invalid response")
7511
+ return
7512
+ }
7513
+
7514
+ if httpResponse.statusCode == 200 || httpResponse.statusCode == 201 {
7515
+ if let data = serviceData {
7516
+ do {
7517
+ if let responseObject = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
7518
+ print("Response Data: \(responseObject)")
7519
+
7520
+ // Check if status is 0 and handle the error
7521
+ if let status = responseObject["status"] as? Int, status == 0 {
7522
+ let errorMessage = responseObject["message"] as? String ?? "Unknown error"
7523
+ self.presentPaymentErrorVC(errorMessage: errorMessage)
7524
+ } else {
7525
+ DispatchQueue.main.async {
7526
+ if let paymentDoneVC = self.storyboard?.instantiateViewController(withIdentifier: "PaymentDoneVC") as? PaymentDoneVC {
7527
+ paymentDoneVC.chargeData = responseObject
7528
+ // Pass the selected payment method
7529
+ paymentDoneVC.selectedPaymentMethod = self.selectedPaymentMethod
7530
+ paymentDoneVC.easyPayDelegate = self.easyPayDelegate
7531
+ // Pass billing info and additional info if available
7532
+ if let billingInfoData = self.request.billingInfoData,
7533
+ let fieldSection = try? JSONDecoder().decode(FieldSection.self, from: billingInfoData) {
7534
+
7535
+ // Filter billing info: only include non-empty values
7536
+ let filteredBilling = fieldSection.billing.filter { !($0.value.trimmingCharacters(in: .whitespaces).isEmpty) }
7537
+ paymentDoneVC.billingInfoData = filteredBilling
7538
+ var billingDict: [String: Any] = [:]
7539
+ filteredBilling.forEach { billingDict[$0.name] = $0.value }
7540
+ paymentDoneVC.billingInfo = billingDict
7541
+
7542
+ // Filter additional info: only include non-empty values
7543
+ let filteredAdditional = fieldSection.additional.filter { !($0.value.trimmingCharacters(in: .whitespaces).isEmpty) }
7544
+ paymentDoneVC.additionalInfoData = filteredAdditional
7545
+ var additionalDict: [String: Any] = [:]
7546
+ filteredAdditional.forEach { additionalDict[$0.name] = $0.value }
7547
+ paymentDoneVC.additionalInfo = additionalDict
7548
+ }
7549
+ self.navigationController?.pushViewController(paymentDoneVC, animated: true)
7550
+ }
7551
+ }
7552
+ }
7553
+ } else {
7554
+ self.presentPaymentErrorVC(errorMessage: "Invalid JSON format")
7555
+ }
7556
+ } catch let jsonError {
7557
+ self.presentPaymentErrorVC(errorMessage: "Error parsing JSON: \(jsonError)")
7558
+ }
7559
+ } else {
7560
+ self.presentPaymentErrorVC(errorMessage: "No data received")
7561
+ }
7562
+ } else {
7563
+ if let data = serviceData,
7564
+ let responseObj = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
7565
+ let message = responseObj["message"] as? String {
7566
+ self.presentPaymentErrorVC(errorMessage: message)
7567
+ } else {
7568
+ self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
7569
+ }
7570
+ }
7571
+ }
7572
+ task.resume()
7573
+ }
7574
+
7575
+ //MARK: - Banking Account Charge Api from add new account if billing info is nil and user not saved the account
7576
+ func accountChargeAddNewAccountApi() {
7577
+ showLoadingIndicator()
7578
+
7579
+ let fullURL = EnvironmentConfig.baseURL + EnvironmentConfig.Endpoints.achCharge.path()
7580
+
7581
+ guard let serviceURL = URL(string: fullURL) else {
7582
+ print("Invalid URL")
7583
+ hideLoadingIndicator()
7584
+ return
7585
+ }
7586
+
7587
+ var uRLRequest = URLRequest(url: serviceURL)
7588
+ uRLRequest.httpMethod = "POST"
7589
+ uRLRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
7590
+
7591
+ let token = UserStoreSingleton.shared.clientToken
7592
+ print("Setting clientToken header: \(token ?? "None")")
7593
+ uRLRequest.addValue(token ?? "", forHTTPHeaderField: "Client-Token")
7594
+
7595
+ // Add API headers
7596
+ if let apiKey = EnvironmentConfig.apiKey,
7597
+ let apiSecret = EnvironmentConfig.apiSecret {
7598
+ uRLRequest.addValue(apiKey, forHTTPHeaderField: "x-api-key")
7599
+ uRLRequest.addValue(apiSecret, forHTTPHeaderField: "x-api-secret")
7600
+ }
7601
+
7602
+ let accountName = txtFieldAccountNameNewAccountView.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
7603
+ let routingNumber = txtFieldRoutingNumberNewAccountView.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
7604
+ let accountType = txtFieldAccountTypeNewAccountView.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
7605
+ let accountNumber = txtFieldAccountNumberNewAccountView.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
7606
+
7607
+ var params: [String: Any] = [
7608
+ "name": accountName,
7609
+ "email": UserStoreSingleton.shared.verificationEmail ?? "",
7610
+ "description": "Test Description",
7611
+ "currency": "usd",
7612
+ "account_type": accountType.lowercased(),
7613
+ "routing_number": routingNumber,
7614
+ "account_number": accountNumber,
7615
+ "payment_mode": "auth_and_capture",
7616
+ "payment_intent": UserStoreSingleton.shared.paymentIntent ?? "",
7617
+ "levelIndicator": 1,
7618
+ ]
7619
+
7620
+ // Add these if recurring is enabled
7621
+ if let req = request, req.is_recurring == true {
7622
+ if let recurringType = req.recurringStartDateType, recurringType == .custom {
7623
+ // Only send start_date if type is .custom and field is not empty
7624
+ if let startDateText = txtFieldSelectDateNewAccountView?.text, !startDateText.isEmpty {
7625
+ let inputFormatter = DateFormatter()
7626
+ inputFormatter.dateFormat = "dd/MM/yyyy"
7627
+
7628
+ let outputFormatter = DateFormatter()
7629
+ outputFormatter.dateFormat = "MM/dd/yyyy"
7630
+
7631
+ if let date = inputFormatter.date(from: startDateText) {
7632
+ let apiFormattedDate = outputFormatter.string(from: date)
7633
+ params["start_date"] = apiFormattedDate
7634
+ } else {
7635
+ print("Invalid date format in startDateText")
7636
+ }
7637
+ }
7638
+ }
7639
+
7640
+ params["interval"] = txtFieldSelectPlanNewAccountView.text.lowercased()
7641
+ }
7642
+
7643
+ print(params)
7644
+
7645
+ do {
7646
+ let jsonData = try JSONSerialization.data(withJSONObject: params, options: .prettyPrinted)
7647
+ uRLRequest.httpBody = jsonData
7504
7648
  if let jsonString = String(data: jsonData, encoding: .utf8) {
7505
7649
  print("JSON Payload: \(jsonString)")
7506
7650
  }
@@ -7595,8 +7739,8 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
7595
7739
  task.resume()
7596
7740
  }
7597
7741
 
7598
- //MARK: - Banking Account Charge Api from add new account if billing info is nil and user not saved the account
7599
- func accountChargeAddNewAccountApi() {
7742
+ //MARK: - Banking Account Charge Api from add new account if billing info is available but their visibilty is false
7743
+ func accountBankChargeAddNewAccountApi() {
7600
7744
  showLoadingIndicator()
7601
7745
 
7602
7746
  let fullURL = EnvironmentConfig.baseURL + EnvironmentConfig.Endpoints.achCharge.path()
@@ -7640,6 +7784,68 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
7640
7784
  "levelIndicator": 1,
7641
7785
  ]
7642
7786
 
7787
+ if let billingInfoData = request.billingInfoData {
7788
+ do {
7789
+ let fieldSection = try JSONDecoder().decode(FieldSection.self, from: billingInfoData)
7790
+
7791
+ // Billing Info
7792
+ let billing = fieldSection.billing
7793
+ if !billing.isEmpty {
7794
+ var billingDict: [String: Any] = [:]
7795
+ billing.forEach { billingDict[$0.name] = $0.value }
7796
+
7797
+ if let address = billingDict["address"] as? String, !address.isEmpty {
7798
+ params["address"] = address
7799
+ }
7800
+ if let country = billingDict["country"] as? String, !country.isEmpty {
7801
+ params["country"] = country
7802
+ }
7803
+ if let state = billingDict["state"] as? String, !state.isEmpty {
7804
+ params["state"] = state
7805
+ }
7806
+ if let city = billingDict["city"] as? String, !city.isEmpty {
7807
+ params["city"] = city
7808
+ }
7809
+ if let postalCode = billingDict["postal_code"] as? String, !postalCode.isEmpty {
7810
+ params["zip"] = postalCode
7811
+ }
7812
+ }
7813
+
7814
+ // Additional Info
7815
+ let additional = fieldSection.additional
7816
+ if !additional.isEmpty {
7817
+ var additionalDict: [String: Any] = [:]
7818
+ additional.forEach { additionalDict[$0.name] = $0.value }
7819
+
7820
+ if let desc = additionalDict["description"] as? String, !desc.isEmpty {
7821
+ params["description"] = desc
7822
+ } else {
7823
+ params["description"] = "Hosted payment checkout"
7824
+ }
7825
+
7826
+ if let phone = additionalDict["phone_number"] as? String, !phone.isEmpty {
7827
+ params["phone_number"] = phone
7828
+ }
7829
+ if let email = additionalDict["email"] as? String, !email.isEmpty {
7830
+ params["email"] = email
7831
+ }
7832
+ if let name = additionalDict["name"] as? String, !name.isEmpty {
7833
+ params["name"] = name
7834
+ }
7835
+ } else {
7836
+ // If no description in additional info, set default
7837
+ params["description"] = "Hosted payment checkout"
7838
+ }
7839
+
7840
+ } catch {
7841
+ print("Failed to decode FieldSection: \(error)")
7842
+ params["description"] = "Hosted payment checkout"
7843
+ }
7844
+ } else {
7845
+ // Fallback if billingInfoData is missing
7846
+ params["description"] = "Hosted payment checkout"
7847
+ }
7848
+
7643
7849
  // Add these if recurring is enabled
7644
7850
  if let req = request, req.is_recurring == true {
7645
7851
  if let recurringType = req.recurringStartDateType, recurringType == .custom {
@@ -7711,30 +7917,23 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
7711
7917
  // Pass the selected payment method
7712
7918
  paymentDoneVC.selectedPaymentMethod = self.selectedPaymentMethod
7713
7919
  paymentDoneVC.easyPayDelegate = self.easyPayDelegate
7714
- // Pass billingInfo and additionalInfo
7715
- if let billingData = self.request.billingInfoData,
7716
- let billingInfoDict = try? JSONSerialization.jsonObject(with: billingData, options: []) as? [String: Any] {
7920
+ // Pass billing info and additional info if available
7921
+ if let billingInfoData = self.request.billingInfoData,
7922
+ let fieldSection = try? JSONDecoder().decode(FieldSection.self, from: billingInfoData) {
7717
7923
 
7718
- // Extract main billing fields
7719
- let cleanBillingInfo: [String: Any] = [
7720
- "postal_code": billingInfoDict["postal_code"] ?? "",
7721
- "country": billingInfoDict["country"] ?? "",
7722
- "city": billingInfoDict["city"] ?? "",
7723
- "address": billingInfoDict["address"] ?? "",
7724
- "state": billingInfoDict["state"] ?? ""
7725
- ]
7726
- paymentDoneVC.billingInfo = cleanBillingInfo
7924
+ // Filter billing info: only include non-empty values
7925
+ let filteredBilling = fieldSection.billing.filter { !($0.value.trimmingCharacters(in: .whitespaces).isEmpty) }
7926
+ paymentDoneVC.billingInfoData = filteredBilling
7927
+ var billingDict: [String: Any] = [:]
7928
+ filteredBilling.forEach { billingDict[$0.name] = $0.value }
7929
+ paymentDoneVC.billingInfo = billingDict
7727
7930
 
7728
- // Extract additional_info
7729
- if let additional = billingInfoDict["additional_info"] as? [String: Any] {
7730
- let cleanAdditionalInfo: [String: Any] = [
7731
- "email": additional["email"] ?? "",
7732
- "phone_number": additional["phone_number"] ?? "",
7733
- "name": additional["name"] ?? "",
7734
- "country_code": additional["country_code"] ?? ""
7735
- ]
7736
- paymentDoneVC.additionalInfo = cleanAdditionalInfo
7737
- }
7931
+ // Filter additional info: only include non-empty values
7932
+ let filteredAdditional = fieldSection.additional.filter { !($0.value.trimmingCharacters(in: .whitespaces).isEmpty) }
7933
+ paymentDoneVC.additionalInfoData = filteredAdditional
7934
+ var additionalDict: [String: Any] = [:]
7935
+ filteredAdditional.forEach { additionalDict[$0.name] = $0.value }
7936
+ paymentDoneVC.additionalInfo = additionalDict
7738
7937
  }
7739
7938
  self.navigationController?.pushViewController(paymentDoneVC, animated: true)
7740
7939
  }
@@ -8265,7 +8464,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
8265
8464
 
8266
8465
  var params: [String: Any] = [
8267
8466
  "name": cardNameTextField.text,
8268
- "email": UserStoreSingleton.shared.merchantEmail ?? "",
8467
+ "email": txtFieldEmailCardView.text,
8269
8468
  "card_number": cardNumberTextField.text.replacingOccurrences(of: " ", with: ""),
8270
8469
  "cardholder_name": cardNameTextField.text,
8271
8470
  "exp_month": cardExpiryTextField.text.components(separatedBy: "/").first ?? "",
@@ -8280,13 +8479,13 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
8280
8479
  if let billingInfoData = request.billingInfoData {
8281
8480
  do {
8282
8481
  let fieldSection = try JSONDecoder().decode(FieldSection.self, from: billingInfoData)
8283
-
8482
+
8284
8483
  // Billing Info
8285
8484
  let billing = fieldSection.billing
8286
8485
  if !billing.isEmpty {
8287
8486
  var billingDict: [String: Any] = [:]
8288
8487
  billing.forEach { billingDict[$0.name] = $0.value }
8289
-
8488
+
8290
8489
  if let address = billingDict["address"] as? String, !address.isEmpty {
8291
8490
  params["address"] = address
8292
8491
  }
@@ -8303,19 +8502,19 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
8303
8502
  params["zip"] = postalCode
8304
8503
  }
8305
8504
  }
8306
-
8505
+
8307
8506
  // Additional Info
8308
8507
  let additional = fieldSection.additional
8309
8508
  if !additional.isEmpty {
8310
8509
  var additionalDict: [String: Any] = [:]
8311
8510
  additional.forEach { additionalDict[$0.name] = $0.value }
8312
-
8511
+
8313
8512
  if let desc = additionalDict["description"] as? String, !desc.isEmpty {
8314
8513
  params["description"] = desc
8315
8514
  } else {
8316
8515
  params["description"] = "Hosted payment checkout"
8317
8516
  }
8318
-
8517
+
8319
8518
  if let phone = additionalDict["phone_number"] as? String, !phone.isEmpty {
8320
8519
  params["phone_number"] = phone
8321
8520
  }
@@ -8329,7 +8528,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
8329
8528
  // If no description in additional info, set default
8330
8529
  params["description"] = "Hosted payment checkout"
8331
8530
  }
8332
-
8531
+
8333
8532
  } catch {
8334
8533
  print("Failed to decode FieldSection: \(error)")
8335
8534
  params["description"] = "Hosted payment checkout"
@@ -8422,7 +8621,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
8422
8621
  var billingDict: [String: Any] = [:]
8423
8622
  filteredBilling.forEach { billingDict[$0.name] = $0.value }
8424
8623
  paymentDoneVC.billingInfo = billingDict
8425
-
8624
+
8426
8625
  // Filter additional info: only include non-empty values
8427
8626
  let filteredAdditional = fieldSection.additional.filter { !($0.value.trimmingCharacters(in: .whitespaces).isEmpty) }
8428
8627
  paymentDoneVC.additionalInfoData = filteredAdditional
@@ -8572,13 +8771,13 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
8572
8771
  if let billingInfoData = request.billingInfoData {
8573
8772
  do {
8574
8773
  let fieldSection = try JSONDecoder().decode(FieldSection.self, from: billingInfoData)
8575
-
8774
+
8576
8775
  // Billing Info
8577
8776
  let billing = fieldSection.billing
8578
8777
  if !billing.isEmpty {
8579
8778
  var billingDict: [String: Any] = [:]
8580
8779
  billing.forEach { billingDict[$0.name] = $0.value }
8581
-
8780
+
8582
8781
  if let address = billingDict["address"] as? String, !address.isEmpty {
8583
8782
  params["address"] = address
8584
8783
  }
@@ -8595,19 +8794,19 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
8595
8794
  params["zip"] = postalCode
8596
8795
  }
8597
8796
  }
8598
-
8797
+
8599
8798
  // Additional Info
8600
8799
  let additional = fieldSection.additional
8601
8800
  if !additional.isEmpty {
8602
8801
  var additionalDict: [String: Any] = [:]
8603
8802
  additional.forEach { additionalDict[$0.name] = $0.value }
8604
-
8803
+
8605
8804
  if let desc = additionalDict["description"] as? String, !desc.isEmpty {
8606
8805
  params["description"] = desc
8607
8806
  } else {
8608
8807
  params["description"] = "Hosted payment checkout"
8609
8808
  }
8610
-
8809
+
8611
8810
  if let phone = additionalDict["phone_number"] as? String, !phone.isEmpty {
8612
8811
  params["phone_number"] = phone
8613
8812
  }
@@ -8621,7 +8820,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
8621
8820
  // If no description in additional info, set default
8622
8821
  params["description"] = "Hosted payment checkout"
8623
8822
  }
8624
-
8823
+
8625
8824
  } catch {
8626
8825
  print("Failed to decode FieldSection: \(error)")
8627
8826
  params["description"] = "Hosted payment checkout"
@@ -8712,7 +8911,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
8712
8911
  var billingDict: [String: Any] = [:]
8713
8912
  filteredBilling.forEach { billingDict[$0.name] = $0.value }
8714
8913
  paymentDoneVC.billingInfo = billingDict
8715
-
8914
+
8716
8915
  // Filter additional info: only include non-empty values
8717
8916
  let filteredAdditional = fieldSection.additional.filter { !($0.value.trimmingCharacters(in: .whitespaces).isEmpty) }
8718
8917
  paymentDoneVC.additionalInfoData = filteredAdditional
@@ -8846,10 +9045,6 @@ extension PaymentInfoVC: UICollectionViewDelegate, UICollectionViewDataSource, U
8846
9045
  if UserStoreSingleton.shared.isLoggedIn == false {
8847
9046
  self.viewSingleSavedAccount.isHidden = true
8848
9047
  self.viewBankFields.isHidden = true
8849
- // self.viewBtnShowSavedCards.isHidden = false
8850
- // self.lblBtnShowSaveCard.text = "Show Saved Cards"
8851
- // self.viewBtnShowSavedCardHeight.constant = 50
8852
- // self.viewBtnShowSavedCardTopCon.constant = 20
8853
9048
 
8854
9049
  if request.saveCard == false {
8855
9050
  self.viewBtnShowSavedCards.isHidden = true
@@ -8931,11 +9126,6 @@ extension PaymentInfoVC: UICollectionViewDelegate, UICollectionViewDataSource, U
8931
9126
 
8932
9127
  case "Bank":
8933
9128
  if UserStoreSingleton.shared.isLoggedIn == false {
8934
- // self.viewBankFields.isHidden = false
8935
- // self.viewBtnShowSavedCards.isHidden = false
8936
- // self.lblBtnShowSaveCard.text = "Show Saved Accounts"
8937
- // self.viewBtnShowSavedCardHeight.constant = 50
8938
- // self.viewBtnShowSavedCardTopCon.constant = 20
8939
9129
 
8940
9130
  if request.saveAccount == false {
8941
9131
  self.viewBtnShowSavedCards.isHidden = true
@@ -10158,7 +10348,7 @@ extension PaymentInfoVC: UITextFieldDelegate {
10158
10348
 
10159
10349
  }
10160
10350
 
10161
- //MARK: - BlinkCard
10351
+ ////MARK: - BlinkCard
10162
10352
  //extension PaymentInfoVC: MBCBlinkCardOverlayViewControllerDelegate {
10163
10353
  // func blinkCardOverlayViewControllerDidFinishScanning(_ blinkCardOverlayViewController: MBCBlinkCardOverlayViewController, state: MBCRecognizerResultState) {
10164
10354
  // /** This is done on background thread */
@@ -10213,7 +10403,7 @@ extension PaymentInfoVC: UITextFieldDelegate {
10213
10403
  // }
10214
10404
  //
10215
10405
  //}
10216
-
10406
+ //
10217
10407
  //extension PaymentInfoVC: CustomOverlayDelegate {
10218
10408
  // func didFinishScanningCard(cardNumber: String, expiryDate: String, cvv: String, nameOnCard: String) {
10219
10409
  // // Update the text fields with scanned details