@jimrising/easymerchantsdk-react-native 1.4.3 → 1.4.5

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.
@@ -363,7 +363,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
363
363
  var isFrom = String()
364
364
 
365
365
  //Blink Card
366
- // var blinkCardRecognizer: MBCBlinkCardRecognizer!
366
+ // var blinkCardRecognizer: MBCBlinkCardRecognizer!
367
367
 
368
368
  // Variables for Card Scanning Data Back
369
369
  var cardNumber: String?
@@ -1931,8 +1931,62 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
1931
1931
  }
1932
1932
 
1933
1933
  // Redirect based on billing visibility
1934
- if fieldSection.visibility.billing {
1935
- // Instantiate BillingInfoVC and pass the selected card data and CVV text
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
+ let showBilling = fieldSection.visibility.billing
1983
+ let showAdditional = fieldSection.visibility.additional
1984
+
1985
+ if !showBilling && !showAdditional {
1986
+ self.paymentIntentFromShowCardApi()
1987
+ }
1988
+ else if showBilling {
1989
+ // Push to BillingInfoVC
1936
1990
  let billingInfoVC = UIStoryboard(name: "easymerchantsdk", bundle: .easyPayBundle).instantiateViewController(withIdentifier: "BillingInfoVC") as! BillingInfoVC
1937
1991
 
1938
1992
  billingInfoVC.isFrom = "SavedCards"
@@ -1957,6 +2011,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
1957
2011
  self.navigationController?.pushViewController(billingInfoVC, animated: true)
1958
2012
  }
1959
2013
  else {
2014
+ // Push to AdditionalInfoVC
1960
2015
  let additionalInfoVC = UIStoryboard(name: "easymerchantsdk", bundle: .easyPayBundle).instantiateViewController(withIdentifier: "AdditionalInfoVC") as! AdditionalInfoVC
1961
2016
  additionalInfoVC.isFrom = "SavedCards"
1962
2017
  additionalInfoVC.selectedCard = self.selectedCard // Passing the selected card data
@@ -1978,6 +2033,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
1978
2033
 
1979
2034
  self.navigationController?.pushViewController(additionalInfoVC, animated: true)
1980
2035
  }
2036
+
1981
2037
  }
1982
2038
  }
1983
2039
  catch {
@@ -2193,9 +2249,13 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
2193
2249
 
2194
2250
  let showBilling = fieldSection.visibility.billing
2195
2251
  let showAdditional = fieldSection.visibility.additional
2196
-
2252
+
2197
2253
  if !showBilling && !showAdditional {
2198
- self.threeDSecurePaymentNewCardApi(customerId: UserStoreSingleton.shared.customerId ?? "")
2254
+ if self.request.secureAuthentication == true {
2255
+ self.threeDSecurePaymentNewCardApi(customerId: UserStoreSingleton.shared.customerId ?? "")
2256
+ } else {
2257
+ self.paymentIntentAddNewCardApi(customerId: UserStoreSingleton.shared.customerId)
2258
+ }
2199
2259
  }
2200
2260
  else if showBilling {
2201
2261
  // Push to BillingInfoVC
@@ -2751,7 +2811,8 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
2751
2811
 
2752
2812
  if !showBilling && !showAdditional {
2753
2813
  // Navigate directly to EmailVerificationVC
2754
- let vc = easymerchantsdk.instantiateViewController(withIdentifier: "EmailVerificationVC") as! EmailVerificationVC
2814
+ // let vc = easymerchantsdk.instantiateViewController(withIdentifier: "EmailVerificationVC") as! EmailVerificationVC
2815
+ let vc = easymerchantsdk.instantiateViewController(withIdentifier: "OTPVerificationVC") as! OTPVerificationVC
2755
2816
  vc.easyPayDelegate = self.easyPayDelegate
2756
2817
  vc.grailPayAccountID = self.grailPayAccountID
2757
2818
  vc.selectedGrailPayAccountType = self.selectedGrailPayAccountType
@@ -2766,6 +2827,8 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
2766
2827
  vc.billingInfo = fieldSection.billing
2767
2828
  vc.additionalInfo = fieldSection.additional
2768
2829
  vc.visibility = fieldSection.visibility
2830
+ vc.amount = self.amount
2831
+ vc.email = self.txtFieldEmailGrailPayView.text
2769
2832
  self.navigationController?.pushViewController(vc, animated: true)
2770
2833
  }
2771
2834
  else if showBilling {
@@ -2819,7 +2882,8 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
2819
2882
  else {
2820
2883
  //If billing info is nil
2821
2884
  // Navigate to EmailVerificationVC directly
2822
- let vc = easymerchantsdk.instantiateViewController(withIdentifier: "EmailVerificationVC") as! EmailVerificationVC
2885
+ // let vc = easymerchantsdk.instantiateViewController(withIdentifier: "EmailVerificationVC") as! EmailVerificationVC
2886
+ let vc = easymerchantsdk.instantiateViewController(withIdentifier: "OTPVerificationVC") as! OTPVerificationVC
2823
2887
  vc.easyPayDelegate = self.easyPayDelegate
2824
2888
  vc.grailPayAccountID = self.grailPayAccountID
2825
2889
  vc.selectedGrailPayAccountType = self.selectedGrailPayAccountType
@@ -2829,7 +2893,8 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
2829
2893
  vc.request = self.request
2830
2894
  vc.isSavedForFuture = self.isSavedForFuture
2831
2895
  vc.selectedPaymentMethod = "GrailPay"
2832
- vc.userEmail = self.txtFieldEmailGrailPayView.text
2896
+ vc.email = self.txtFieldEmailGrailPayView.text
2897
+ vc.amount = self.amount
2833
2898
  self.navigationController?.pushViewController(vc, animated: true)
2834
2899
  }
2835
2900
  } else {
@@ -4113,7 +4178,15 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
4113
4178
  let showAdditional = fieldSection.visibility.additional
4114
4179
 
4115
4180
  if !showBilling && !showAdditional {
4116
- self.threeDSecurePaymentApi()
4181
+ if self.isSavedForFuture {
4182
+ self.navigateCardDataToEmailVerificationVC()
4183
+ } else {
4184
+ if self.request.secureAuthentication == true {
4185
+ self.threeDSecurePaymentApi()
4186
+ } else {
4187
+ self.paymentIntentCardApi()
4188
+ }
4189
+ }
4117
4190
  }
4118
4191
  else if showBilling {
4119
4192
  // Push to BillingInfoVC
@@ -4444,7 +4517,8 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
4444
4517
 
4445
4518
  // Function to navigate to EmailVerificationVC
4446
4519
  func navigateCardDataToEmailVerificationVC() {
4447
- if let emailVerificationVC = storyboard?.instantiateViewController(withIdentifier: "EmailVerificationVC") as? EmailVerificationVC {
4520
+ // if let emailVerificationVC = storyboard?.instantiateViewController(withIdentifier: "EmailVerificationVC") as? EmailVerificationVC {
4521
+ if let emailVerificationVC = storyboard?.instantiateViewController(withIdentifier: "OTPVerificationVC") as? OTPVerificationVC {
4448
4522
  if let billingInfoData = request.billingInfoData {
4449
4523
  do {
4450
4524
  let fieldSection = try JSONDecoder().decode(FieldSection.self, from: billingInfoData)
@@ -4463,6 +4537,9 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
4463
4537
  emailVerificationVC.request = self.request
4464
4538
  emailVerificationVC.chosenPlan = self.txtFieldChosePlanCard.text
4465
4539
  emailVerificationVC.startDate = self.txtFieldStartDateCard.text
4540
+ emailVerificationVC.userEmail = self.txtFieldEmailCardView.text
4541
+ emailVerificationVC.email = self.txtFieldEmailCardView.text
4542
+ emailVerificationVC.amount = self.amount
4466
4543
  }
4467
4544
  catch {
4468
4545
  print("Failed to decode billingInfoData: \(error.localizedDescription)")
@@ -4472,7 +4549,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
4472
4549
  self.navigationController?.pushViewController(emailVerificationVC, animated: true)
4473
4550
  }
4474
4551
  }
4475
-
4552
+
4476
4553
  func navigateBankDataToEmailVerificationVC() {
4477
4554
  if let emailVerificationVC = storyboard?.instantiateViewController(withIdentifier: "EmailVerificationVC") as? EmailVerificationVC {
4478
4555
  if let billingInfoData = request.billingInfoData {
@@ -4493,6 +4570,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
4493
4570
  emailVerificationVC.chosenPlan = self.txtFieldSelectPlanViewBankFields.text
4494
4571
  emailVerificationVC.startDate = self.txtFieldSelectDateViewBankFields.text
4495
4572
  emailVerificationVC.request = self.request
4573
+ emailVerificationVC.userEmail = self.txtFieldEmailAccountView.text
4496
4574
  }
4497
4575
  catch {
4498
4576
  print("Failed to decode billingInfoData: \(error.localizedDescription)")
@@ -5755,6 +5833,214 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
5755
5833
  task.resume()
5756
5834
  }
5757
5835
 
5836
+ // MARK: - Credit Card Charge Api if billing info is available but visibility of billing and additinal is false
5837
+ func paymentIntentCardApi() {
5838
+ showLoadingIndicator()
5839
+
5840
+ let fullURL = EnvironmentConfig.baseURL + EnvironmentConfig.Endpoints.charges.path()
5841
+
5842
+ guard let serviceURL = URL(string: fullURL) else {
5843
+ print("Invalid URL")
5844
+ hideLoadingIndicator()
5845
+ return
5846
+ }
5847
+
5848
+ var urlRequest = URLRequest(url: serviceURL)
5849
+ urlRequest.httpMethod = "POST"
5850
+ urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
5851
+
5852
+ let token = UserStoreSingleton.shared.clientToken
5853
+ print("Setting clientToken header: \(token ?? "None")")
5854
+ urlRequest.addValue(token ?? "", forHTTPHeaderField: "Client-Token")
5855
+
5856
+ var params: [String: Any] = [
5857
+ "name": cardNameTextField.text,
5858
+ "email": UserStoreSingleton.shared.merchantEmail ?? "",
5859
+ "card_number": cardNumberTextField.text.replacingOccurrences(of: " ", with: ""),
5860
+ "cardholder_name": cardNameTextField.text,
5861
+ "exp_month": cardExpiryTextField.text.components(separatedBy: "/").first ?? "",
5862
+ "exp_year": cardExpiryTextField.text.components(separatedBy: "/").last ?? "",
5863
+ "cvc": cardCvvTextField.text,
5864
+ "currency": "usd"
5865
+ ]
5866
+
5867
+ if let billingInfoData = request.billingInfoData {
5868
+ do {
5869
+ let fieldSection = try JSONDecoder().decode(FieldSection.self, from: billingInfoData)
5870
+
5871
+ // Billing Info
5872
+ let billing = fieldSection.billing
5873
+ if !billing.isEmpty {
5874
+ var billingDict: [String: Any] = [:]
5875
+ billing.forEach { billingDict[$0.name] = $0.value }
5876
+
5877
+ if let address = billingDict["address"] as? String, !address.isEmpty {
5878
+ params["address"] = address
5879
+ }
5880
+ if let country = billingDict["country"] as? String, !country.isEmpty {
5881
+ params["country"] = country
5882
+ }
5883
+ if let state = billingDict["state"] as? String, !state.isEmpty {
5884
+ params["state"] = state
5885
+ }
5886
+ if let city = billingDict["city"] as? String, !city.isEmpty {
5887
+ params["city"] = city
5888
+ }
5889
+ if let postalCode = billingDict["postal_code"] as? String, !postalCode.isEmpty {
5890
+ params["zip"] = postalCode
5891
+ }
5892
+ }
5893
+
5894
+ // Additional Info
5895
+ let additional = fieldSection.additional
5896
+ if !additional.isEmpty {
5897
+ var additionalDict: [String: Any] = [:]
5898
+ additional.forEach { additionalDict[$0.name] = $0.value }
5899
+
5900
+ if let desc = additionalDict["description"] as? String, !desc.isEmpty {
5901
+ params["description"] = desc
5902
+ } else {
5903
+ params["description"] = "Hosted payment checkout"
5904
+ }
5905
+
5906
+ if let phone = additionalDict["phone_number"] as? String, !phone.isEmpty {
5907
+ params["phone_number"] = phone
5908
+ }
5909
+ if let email = additionalDict["email"] as? String, !email.isEmpty {
5910
+ params["email"] = email
5911
+ }
5912
+ if let name = additionalDict["name"] as? String, !name.isEmpty {
5913
+ params["name"] = name
5914
+ }
5915
+ } else {
5916
+ // If no description in additional info, set default
5917
+ params["description"] = "Hosted payment checkout"
5918
+ }
5919
+
5920
+ } catch {
5921
+ print("Failed to decode FieldSection: \(error)")
5922
+ params["description"] = "Hosted payment checkout"
5923
+ }
5924
+ } else {
5925
+ // Fallback if billingInfoData is missing
5926
+ params["description"] = "Hosted payment checkout"
5927
+ }
5928
+
5929
+ // Add these if recurring is enabled
5930
+ if let req = request, req.is_recurring == true {
5931
+ if let recurringType = req.recurringStartDateType, recurringType == .custom {
5932
+ // Only send start_date if type is .custom and field is not empty
5933
+ if let startDateText = txtFieldStartDateCard?.text, !startDateText.isEmpty {
5934
+ let inputFormatter = DateFormatter()
5935
+ inputFormatter.dateFormat = "dd/MM/yyyy"
5936
+
5937
+ let outputFormatter = DateFormatter()
5938
+ outputFormatter.dateFormat = "MM/dd/yyyy"
5939
+
5940
+ if let date = inputFormatter.date(from: startDateText) {
5941
+ let apiFormattedDate = outputFormatter.string(from: date)
5942
+ params["start_date"] = apiFormattedDate
5943
+ } else {
5944
+ print("Invalid date format in startDateText")
5945
+ }
5946
+ }
5947
+ }
5948
+
5949
+ params["interval"] = txtFieldChosePlanCard.text.lowercased()
5950
+ }
5951
+
5952
+ print(params)
5953
+
5954
+ do {
5955
+ let jsonData = try JSONSerialization.data(withJSONObject: params, options: .prettyPrinted)
5956
+ urlRequest.httpBody = jsonData
5957
+ if let jsonString = String(data: jsonData, encoding: .utf8) {
5958
+ print("JSON Payload: \(jsonString)")
5959
+ }
5960
+ } catch let error {
5961
+ print("Error creating JSON data: \(error)")
5962
+ hideLoadingIndicator()
5963
+ return
5964
+ }
5965
+
5966
+ let session = URLSession.shared
5967
+ let task = session.dataTask(with: urlRequest) { (serviceData, serviceResponse, error) in
5968
+
5969
+ DispatchQueue.main.async {
5970
+ self.hideLoadingIndicator()
5971
+ }
5972
+
5973
+ if let error = error {
5974
+ print("Error: \(error.localizedDescription)")
5975
+ self.presentPaymentErrorVC(errorMessage: error.localizedDescription)
5976
+ return
5977
+ }
5978
+
5979
+ guard let httpResponse = serviceResponse as? HTTPURLResponse else {
5980
+ print("Invalid response")
5981
+ self.presentPaymentErrorVC(errorMessage: "Invalid response from server.")
5982
+ return
5983
+ }
5984
+
5985
+ if httpResponse.statusCode == 200 || httpResponse.statusCode == 201 {
5986
+ if let data = serviceData {
5987
+ do {
5988
+ if let responseObject = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
5989
+ print("Response Data: \(responseObject)")
5990
+
5991
+ if let status = responseObject["status"] as? Int, status == 0 {
5992
+ let errorMessage = responseObject["message"] as? String ?? "Unknown error occurred."
5993
+ self.presentPaymentErrorVC(errorMessage: errorMessage)
5994
+ } else {
5995
+ DispatchQueue.main.async {
5996
+ if let paymentDoneVC = self.storyboard?.instantiateViewController(withIdentifier: "PaymentDoneVC") as? PaymentDoneVC {
5997
+ paymentDoneVC.chargeData = responseObject
5998
+ paymentDoneVC.selectedPaymentMethod = self.selectedPaymentMethod
5999
+ paymentDoneVC.easyPayDelegate = self.easyPayDelegate
6000
+ // Pass billing info and additional info if available
6001
+ if let billingInfoData = self.request.billingInfoData,
6002
+ let fieldSection = try? JSONDecoder().decode(FieldSection.self, from: billingInfoData) {
6003
+
6004
+ // Filter billing info: only include non-empty values
6005
+ let filteredBilling = fieldSection.billing.filter { !($0.value.trimmingCharacters(in: .whitespaces).isEmpty) }
6006
+ paymentDoneVC.billingInfoData = filteredBilling
6007
+ var billingDict: [String: Any] = [:]
6008
+ filteredBilling.forEach { billingDict[$0.name] = $0.value }
6009
+ paymentDoneVC.billingInfo = billingDict
6010
+
6011
+ // Filter additional info: only include non-empty values
6012
+ let filteredAdditional = fieldSection.additional.filter { !($0.value.trimmingCharacters(in: .whitespaces).isEmpty) }
6013
+ paymentDoneVC.additionalInfoData = filteredAdditional
6014
+ var additionalDict: [String: Any] = [:]
6015
+ filteredAdditional.forEach { additionalDict[$0.name] = $0.value }
6016
+ paymentDoneVC.additionalInfo = additionalDict
6017
+ }
6018
+ self.navigationController?.pushViewController(paymentDoneVC, animated: true)
6019
+ }
6020
+ }
6021
+ }
6022
+ } else {
6023
+ self.presentPaymentErrorVC(errorMessage: "Invalid JSON format")
6024
+ }
6025
+ } catch let jsonError {
6026
+ self.presentPaymentErrorVC(errorMessage: "Error parsing response: \(jsonError.localizedDescription)")
6027
+ }
6028
+ } else {
6029
+ self.presentPaymentErrorVC(errorMessage: "No data received from server.")
6030
+ }
6031
+ } else {
6032
+ if let data = serviceData,
6033
+ let responseObj = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
6034
+ let message = responseObj["message"] as? String {
6035
+ self.presentPaymentErrorVC(errorMessage: message)
6036
+ } else {
6037
+ self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
6038
+ }
6039
+ }
6040
+ }
6041
+ task.resume()
6042
+ }
6043
+
5758
6044
  // MARK: - Credit Card Charge API (Saved Cards, No Billing Info, Logged In)
5759
6045
  func paymentIntentFromShowSavedCardApi() {
5760
6046
  showLoadingIndicator()
@@ -5915,45 +6201,249 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
5915
6201
  task.resume()
5916
6202
  }
5917
6203
 
5918
- //MARK: - Credit Card Charge Api from Add new cards If Billing info is nil and Logged in.
5919
- func paymentIntentFromAddNewCardApi(customerId: String?) {
5920
- // Get the text fields from the selected cell and trim whitespace
5921
- let nameText = txtFieldNameOnCardNewCardView.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
5922
- let cvvText = txtFieldCVVNewCardView.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
5923
- let cardNumberText = (txtFieldCardNumberNewCardView.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "").replacingOccurrences(of: " ", with: "")
5924
- let expiryText = txtFieldExpiryDateNewCardView.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
6204
+ //MARK: - Credit Card Charge Api from Saved cards if Billing info exist but not go to billing and additonal page
6205
+ func paymentIntentFromShowCardApi() {
6206
+ showLoadingIndicator()
5925
6207
 
6208
+ let fullURL = EnvironmentConfig.baseURL + EnvironmentConfig.Endpoints.charges.path()
5926
6209
 
5927
- // Check if any field is empty
5928
- if cardNumberText.isEmpty || expiryText.isEmpty || cvvText.isEmpty || nameText.isEmpty {
5929
- let alert = UIAlertController(title: "Missing Information", message: "Please fill in all card details.", preferredStyle: .alert)
5930
- alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
5931
- self.present(alert, animated: true, completion: nil)
6210
+ guard let serviceURL = URL(string: fullURL) else {
6211
+ print("Invalid URL")
6212
+ hideLoadingIndicator()
5932
6213
  return
5933
6214
  }
5934
6215
 
5935
- // Validate expiry date format
5936
- let expiryDateFormat = "MM/yyyy"
5937
- let dateFormatter = DateFormatter()
5938
- dateFormatter.dateFormat = expiryDateFormat
5939
- dateFormatter.locale = Locale(identifier: "en_US_POSIX")
6216
+ var uRLRequest = URLRequest(url: serviceURL)
6217
+ uRLRequest.httpMethod = "POST"
6218
+ uRLRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
5940
6219
 
5941
- // Split the expiry date and validate its format
5942
- let exp = expiryText.split(separator: "/")
5943
- if exp.count != 2 || exp[0].count != 2 || exp[1].count != 4 {
5944
- let alert = UIAlertController(title: "Invalid Expiry Date", message: "Please enter the expiry date in the format MM/yyyy.", preferredStyle: .alert)
5945
- alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
5946
- self.present(alert, animated: true, completion: nil)
5947
- return
5948
- }
6220
+ let token = UserStoreSingleton.shared.clientToken
6221
+ print("Setting clientToken header: \(token ?? "None")")
6222
+ uRLRequest.addValue(token ?? "", forHTTPHeaderField: "Client-Token")
5949
6223
 
5950
- // Check if the expiry date is valid
5951
- if let expiryDateObj = dateFormatter.date(from: expiryText) {
5952
- // Check if the expiry date is in the past
5953
- let currentDate = Date()
5954
- let calendar = Calendar.current
5955
- let currentMonthYear = calendar.date(from: calendar.dateComponents([.year, .month], from: currentDate))
5956
- if expiryDateObj < currentMonthYear! {
6224
+ var params: [String: Any] = [
6225
+ "currency": "usd",
6226
+ "payment_method": "card",
6227
+ "save_card": 0,
6228
+ "customer" : selectedCard?.customerId ?? "",
6229
+ "customer_id" : selectedCard?.customerId ?? "",
6230
+ "card_id" : selectedCard?.cardId ?? "",
6231
+ "cvc" : txtFieldCVVSingleSavedCard.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "",
6232
+ ]
6233
+
6234
+ if let billingInfoData = request.billingInfoData {
6235
+ do {
6236
+ let fieldSection = try JSONDecoder().decode(FieldSection.self, from: billingInfoData)
6237
+
6238
+ // Billing Info
6239
+ let billing = fieldSection.billing
6240
+ if !billing.isEmpty {
6241
+ var billingDict: [String: Any] = [:]
6242
+ billing.forEach { billingDict[$0.name] = $0.value }
6243
+
6244
+ if let address = billingDict["address"] as? String, !address.isEmpty {
6245
+ params["address"] = address
6246
+ }
6247
+ if let country = billingDict["country"] as? String, !country.isEmpty {
6248
+ params["country"] = country
6249
+ }
6250
+ if let state = billingDict["state"] as? String, !state.isEmpty {
6251
+ params["state"] = state
6252
+ }
6253
+ if let city = billingDict["city"] as? String, !city.isEmpty {
6254
+ params["city"] = city
6255
+ }
6256
+ if let postalCode = billingDict["postal_code"] as? String, !postalCode.isEmpty {
6257
+ params["zip"] = postalCode
6258
+ }
6259
+ }
6260
+
6261
+ // Additional Info
6262
+ let additional = fieldSection.additional
6263
+ if !additional.isEmpty {
6264
+ var additionalDict: [String: Any] = [:]
6265
+ additional.forEach { additionalDict[$0.name] = $0.value }
6266
+
6267
+ if let desc = additionalDict["description"] as? String, !desc.isEmpty {
6268
+ params["description"] = desc
6269
+ } else {
6270
+ params["description"] = "Hosted payment checkout"
6271
+ }
6272
+
6273
+ if let phone = additionalDict["phone_number"] as? String, !phone.isEmpty {
6274
+ params["phone_number"] = phone
6275
+ }
6276
+ if let email = additionalDict["email"] as? String, !email.isEmpty {
6277
+ params["email"] = email
6278
+ }
6279
+ if let name = additionalDict["name"] as? String, !name.isEmpty {
6280
+ params["name"] = name
6281
+ }
6282
+ } else {
6283
+ // If no description in additional info, set default
6284
+ params["description"] = "Hosted payment checkout"
6285
+ }
6286
+
6287
+ } catch {
6288
+ print("Failed to decode FieldSection: \(error)")
6289
+ params["description"] = "Hosted payment checkout"
6290
+ }
6291
+ } else {
6292
+ // Fallback if billingInfoData is missing
6293
+ params["description"] = "Hosted payment checkout"
6294
+ }
6295
+
6296
+ // Add these if recurring is enabled
6297
+ if let req = request, req.is_recurring == true {
6298
+ if let recurringType = req.recurringStartDateType, recurringType == .custom {
6299
+ // Only send start_date if type is .custom and field is not empty
6300
+ if let startDateText = txtFieldSelectDateSingleSavedCard?.text, !startDateText.isEmpty {
6301
+ let inputFormatter = DateFormatter()
6302
+ inputFormatter.dateFormat = "dd/MM/yyyy"
6303
+
6304
+ let outputFormatter = DateFormatter()
6305
+ outputFormatter.dateFormat = "MM/dd/yyyy"
6306
+
6307
+ if let date = inputFormatter.date(from: startDateText) {
6308
+ let apiFormattedDate = outputFormatter.string(from: date)
6309
+ params["start_date"] = apiFormattedDate
6310
+ } else {
6311
+ print("Invalid date format in startDateText")
6312
+ }
6313
+ }
6314
+ }
6315
+
6316
+ params["interval"] = txtFieldSelectPlanSingleSavedCard.text.lowercased()
6317
+ }
6318
+
6319
+ do {
6320
+ let jsonData = try JSONSerialization.data(withJSONObject: params, options: .prettyPrinted)
6321
+ uRLRequest.httpBody = jsonData
6322
+ if let jsonString = String(data: jsonData, encoding: .utf8) {
6323
+ print("JSON Payload: \(jsonString)")
6324
+ }
6325
+ } catch let error {
6326
+ print("Error creating JSON data: \(error)")
6327
+ hideLoadingIndicator()
6328
+ return
6329
+ }
6330
+
6331
+ let session = URLSession.shared
6332
+ let task = session.dataTask(with: uRLRequest) { (serviceData, serviceResponse, error) in
6333
+
6334
+ DispatchQueue.main.async {
6335
+ self.hideLoadingIndicator() // Stop loader when response is received
6336
+ }
6337
+
6338
+ if let error = error {
6339
+ print("Error: \(error.localizedDescription)")
6340
+ return
6341
+ }
6342
+
6343
+ guard let httpResponse = serviceResponse as? HTTPURLResponse else {
6344
+ print("Invalid response")
6345
+ return
6346
+ }
6347
+
6348
+ if httpResponse.statusCode == 200 || httpResponse.statusCode == 201 {
6349
+ if let data = serviceData {
6350
+ do {
6351
+ if let responseObject = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
6352
+ print("Response Data: \(responseObject)")
6353
+
6354
+ // Check if status is 0 and handle the error
6355
+ if let status = responseObject["status"] as? Int, status == 0 {
6356
+ let errorMessage = responseObject["message"] as? String ?? "Unknown error"
6357
+ self.presentPaymentErrorVC(errorMessage: errorMessage)
6358
+ } else {
6359
+ DispatchQueue.main.async {
6360
+ if let paymentDoneVC = self.storyboard?.instantiateViewController(withIdentifier: "PaymentDoneVC") as? PaymentDoneVC {
6361
+ paymentDoneVC.chargeData = responseObject
6362
+ paymentDoneVC.selectedPaymentMethod = self.selectedPaymentMethod
6363
+ paymentDoneVC.easyPayDelegate = self.easyPayDelegate
6364
+ // Pass billing info and additional info if available
6365
+ if let billingInfoData = self.request.billingInfoData,
6366
+ let fieldSection = try? JSONDecoder().decode(FieldSection.self, from: billingInfoData) {
6367
+
6368
+ // Filter billing info: only include non-empty values
6369
+ let filteredBilling = fieldSection.billing.filter { !($0.value.trimmingCharacters(in: .whitespaces).isEmpty) }
6370
+ paymentDoneVC.billingInfoData = filteredBilling
6371
+ var billingDict: [String: Any] = [:]
6372
+ filteredBilling.forEach { billingDict[$0.name] = $0.value }
6373
+ paymentDoneVC.billingInfo = billingDict
6374
+
6375
+ // Filter additional info: only include non-empty values
6376
+ let filteredAdditional = fieldSection.additional.filter { !($0.value.trimmingCharacters(in: .whitespaces).isEmpty) }
6377
+ paymentDoneVC.additionalInfoData = filteredAdditional
6378
+ var additionalDict: [String: Any] = [:]
6379
+ filteredAdditional.forEach { additionalDict[$0.name] = $0.value }
6380
+ paymentDoneVC.additionalInfo = additionalDict
6381
+ }
6382
+ self.navigationController?.pushViewController(paymentDoneVC, animated: true)
6383
+ }
6384
+ }
6385
+ }
6386
+ } else {
6387
+ self.presentPaymentErrorVC(errorMessage: "Invalid JSON format")
6388
+ }
6389
+ } catch let jsonError {
6390
+ self.presentPaymentErrorVC(errorMessage: "Error parsing JSON: \(jsonError)")
6391
+ }
6392
+ } else {
6393
+ self.presentPaymentErrorVC(errorMessage: "No data received")
6394
+ }
6395
+ } else {
6396
+ if let data = serviceData,
6397
+ let responseObj = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
6398
+ let message = responseObj["message"] as? String {
6399
+ self.presentPaymentErrorVC(errorMessage: message)
6400
+ } else {
6401
+ self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
6402
+ }
6403
+ }
6404
+ }
6405
+ task.resume()
6406
+ }
6407
+
6408
+ //MARK: - Credit Card Charge Api from Add new cards If Billing info is nil and Logged in.
6409
+ func paymentIntentFromAddNewCardApi(customerId: String?) {
6410
+ // Get the text fields from the selected cell and trim whitespace
6411
+ let nameText = txtFieldNameOnCardNewCardView.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
6412
+ let cvvText = txtFieldCVVNewCardView.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
6413
+ let cardNumberText = (txtFieldCardNumberNewCardView.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "").replacingOccurrences(of: " ", with: "")
6414
+ let expiryText = txtFieldExpiryDateNewCardView.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
6415
+
6416
+
6417
+ // Check if any field is empty
6418
+ if cardNumberText.isEmpty || expiryText.isEmpty || cvvText.isEmpty || nameText.isEmpty {
6419
+ let alert = UIAlertController(title: "Missing Information", message: "Please fill in all card details.", preferredStyle: .alert)
6420
+ alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
6421
+ self.present(alert, animated: true, completion: nil)
6422
+ return
6423
+ }
6424
+
6425
+ // Validate expiry date format
6426
+ let expiryDateFormat = "MM/yyyy"
6427
+ let dateFormatter = DateFormatter()
6428
+ dateFormatter.dateFormat = expiryDateFormat
6429
+ dateFormatter.locale = Locale(identifier: "en_US_POSIX")
6430
+
6431
+ // Split the expiry date and validate its format
6432
+ let exp = expiryText.split(separator: "/")
6433
+ if exp.count != 2 || exp[0].count != 2 || exp[1].count != 4 {
6434
+ let alert = UIAlertController(title: "Invalid Expiry Date", message: "Please enter the expiry date in the format MM/yyyy.", preferredStyle: .alert)
6435
+ alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
6436
+ self.present(alert, animated: true, completion: nil)
6437
+ return
6438
+ }
6439
+
6440
+ // Check if the expiry date is valid
6441
+ if let expiryDateObj = dateFormatter.date(from: expiryText) {
6442
+ // Check if the expiry date is in the past
6443
+ let currentDate = Date()
6444
+ let calendar = Calendar.current
6445
+ let currentMonthYear = calendar.date(from: calendar.dateComponents([.year, .month], from: currentDate))
6446
+ if expiryDateObj < currentMonthYear! {
5957
6447
  let alert = UIAlertController(title: "Expired Card", message: "The expiry date cannot be in the past. Please enter a valid expiry date.", preferredStyle: .alert)
5958
6448
  alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
5959
6449
  self.present(alert, animated: true, completion: nil)
@@ -6158,6 +6648,237 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
6158
6648
  task.resume()
6159
6649
  }
6160
6650
 
6651
+ //MARK: - Credit Card Charge Api from Add new card from saved cards if billing info is available but their visibility is off
6652
+ func paymentIntentAddNewCardApi(customerId: String?) {
6653
+ showLoadingIndicator()
6654
+
6655
+ let fullURL = EnvironmentConfig.baseURL + EnvironmentConfig.Endpoints.charges.path()
6656
+
6657
+ guard let serviceURL = URL(string: fullURL) else {
6658
+ print("Invalid URL")
6659
+ hideLoadingIndicator()
6660
+ return
6661
+ }
6662
+
6663
+ var uRLRequest = URLRequest(url: serviceURL)
6664
+ uRLRequest.httpMethod = "POST"
6665
+ uRLRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
6666
+
6667
+ let token = UserStoreSingleton.shared.clientToken
6668
+ print("Setting clientToken header: \(token ?? "None")")
6669
+ uRLRequest.addValue(token ?? "", forHTTPHeaderField: "Client-Token")
6670
+
6671
+ let emailPrefix = UserStoreSingleton.shared.verificationEmail?.components(separatedBy: "@").first ?? ""
6672
+
6673
+ // Get the text fields from the selected cell and trim whitespace
6674
+ let nameText = txtFieldNameOnCardNewCardView.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
6675
+ let cvvText = txtFieldCVVNewCardView.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
6676
+ let cardNumberText = (txtFieldCardNumberNewCardView.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "").replacingOccurrences(of: " ", with: "")
6677
+ let expiryText = txtFieldExpiryDateNewCardView.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
6678
+
6679
+ var params: [String: Any] = [
6680
+ "name": nameText,
6681
+ "card_number": cardNumberText,
6682
+ "cardholder_name": nameText,
6683
+ "exp_month": expiryText.components(separatedBy: "/").first ?? "",
6684
+ "exp_year": expiryText.components(separatedBy: "/").last ?? "",
6685
+ "cvc": cvvText,
6686
+ "description": "TestDescription",
6687
+ "currency": "usd",
6688
+ "payment_method": "card",
6689
+ "save_card": isSavedNewCardForFuture ? 1 : 0,
6690
+ "email" : UserStoreSingleton.shared.verificationEmail ?? ""
6691
+ ]
6692
+
6693
+ // Add is_default parameter if save_card is 1
6694
+ if isSavedNewCard {
6695
+ params["is_default"] = "1"
6696
+ }
6697
+
6698
+ if let billingInfoData = request.billingInfoData {
6699
+ do {
6700
+ let fieldSection = try JSONDecoder().decode(FieldSection.self, from: billingInfoData)
6701
+
6702
+ // Billing Info
6703
+ let billing = fieldSection.billing
6704
+ if !billing.isEmpty {
6705
+ var billingDict: [String: Any] = [:]
6706
+ billing.forEach { billingDict[$0.name] = $0.value }
6707
+
6708
+ if let address = billingDict["address"] as? String, !address.isEmpty {
6709
+ params["address"] = address
6710
+ }
6711
+ if let country = billingDict["country"] as? String, !country.isEmpty {
6712
+ params["country"] = country
6713
+ }
6714
+ if let state = billingDict["state"] as? String, !state.isEmpty {
6715
+ params["state"] = state
6716
+ }
6717
+ if let city = billingDict["city"] as? String, !city.isEmpty {
6718
+ params["city"] = city
6719
+ }
6720
+ if let postalCode = billingDict["postal_code"] as? String, !postalCode.isEmpty {
6721
+ params["zip"] = postalCode
6722
+ }
6723
+ }
6724
+
6725
+ // Additional Info
6726
+ let additional = fieldSection.additional
6727
+ if !additional.isEmpty {
6728
+ var additionalDict: [String: Any] = [:]
6729
+ additional.forEach { additionalDict[$0.name] = $0.value }
6730
+
6731
+ if let desc = additionalDict["description"] as? String, !desc.isEmpty {
6732
+ params["description"] = desc
6733
+ } else {
6734
+ params["description"] = "Hosted payment checkout"
6735
+ }
6736
+
6737
+ if let phone = additionalDict["phone_number"] as? String, !phone.isEmpty {
6738
+ params["phone_number"] = phone
6739
+ }
6740
+ if let email = additionalDict["email"] as? String, !email.isEmpty {
6741
+ params["email"] = email
6742
+ }
6743
+ if let name = additionalDict["name"] as? String, !name.isEmpty {
6744
+ params["name"] = name
6745
+ }
6746
+ } else {
6747
+ // If no description in additional info, set default
6748
+ params["description"] = "Hosted payment checkout"
6749
+ }
6750
+
6751
+ } catch {
6752
+ print("Failed to decode FieldSection: \(error)")
6753
+ params["description"] = "Hosted payment checkout"
6754
+ }
6755
+ } else {
6756
+ // Fallback if billingInfoData is missing
6757
+ params["description"] = "Hosted payment checkout"
6758
+ }
6759
+
6760
+ // Add these if recurring is enabled
6761
+ if let req = request, req.is_recurring == true {
6762
+ if let recurringType = req.recurringStartDateType, recurringType == .custom {
6763
+ // Only send start_date if type is .custom and field is not empty
6764
+ if let startDateText = txtFieldSelectDateNewCardView?.text, !startDateText.isEmpty {
6765
+ let inputFormatter = DateFormatter()
6766
+ inputFormatter.dateFormat = "dd/MM/yyyy"
6767
+
6768
+ let outputFormatter = DateFormatter()
6769
+ outputFormatter.dateFormat = "MM/dd/yyyy"
6770
+
6771
+ if let date = inputFormatter.date(from: startDateText) {
6772
+ let apiFormattedDate = outputFormatter.string(from: date)
6773
+ params["start_date"] = apiFormattedDate
6774
+ } else {
6775
+ print("Invalid date format in startDateText")
6776
+ }
6777
+ }
6778
+ }
6779
+
6780
+ params["interval"] = txtFieldSelectPlanNewCardView.text.lowercased()
6781
+ }
6782
+
6783
+ if let customerId = customerId {
6784
+ params["customer"] = customerId
6785
+ params["customer_id"] = customerId
6786
+ } else {
6787
+ params["username"] = emailPrefix
6788
+ params["email"] = UserStoreSingleton.shared.verificationEmail
6789
+ }
6790
+
6791
+ print(params)
6792
+
6793
+ do {
6794
+ let jsonData = try JSONSerialization.data(withJSONObject: params, options: .prettyPrinted)
6795
+ uRLRequest.httpBody = jsonData
6796
+ if let jsonString = String(data: jsonData, encoding: .utf8) {
6797
+ print("JSON Payload: \(jsonString)")
6798
+ }
6799
+ } catch let error {
6800
+ print("Error creating JSON data: \(error)")
6801
+ hideLoadingIndicator()
6802
+ return
6803
+ }
6804
+
6805
+ let session = URLSession.shared
6806
+ let task = session.dataTask(with: uRLRequest) { (serviceData, serviceResponse, error) in
6807
+
6808
+ DispatchQueue.main.async {
6809
+ self.hideLoadingIndicator() // Stop loader when response is received
6810
+ }
6811
+
6812
+ if let error = error {
6813
+ self.presentPaymentErrorVC(errorMessage: error.localizedDescription)
6814
+ return
6815
+ }
6816
+
6817
+ guard let httpResponse = serviceResponse as? HTTPURLResponse else {
6818
+ self.presentPaymentErrorVC(errorMessage: "Invalid response")
6819
+ return
6820
+ }
6821
+
6822
+ if httpResponse.statusCode == 200 || httpResponse.statusCode == 201 {
6823
+ if let data = serviceData {
6824
+ do {
6825
+ if let responseObject = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
6826
+ print("Response Data: \(responseObject)")
6827
+
6828
+ // Check if status is 0 and handle the error
6829
+ if let status = responseObject["status"] as? Int, status == 0 {
6830
+ let errorMessage = responseObject["message"] as? String ?? "Unknown error"
6831
+ self.presentPaymentErrorVC(errorMessage: errorMessage)
6832
+ } else {
6833
+ DispatchQueue.main.async {
6834
+ if let paymentDoneVC = self.storyboard?.instantiateViewController(withIdentifier: "PaymentDoneVC") as? PaymentDoneVC {
6835
+ paymentDoneVC.chargeData = responseObject
6836
+ paymentDoneVC.selectedPaymentMethod = self.selectedPaymentMethod
6837
+ paymentDoneVC.easyPayDelegate = self.easyPayDelegate
6838
+ // Pass billing info and additional info if available
6839
+ if let billingInfoData = self.request.billingInfoData,
6840
+ let fieldSection = try? JSONDecoder().decode(FieldSection.self, from: billingInfoData) {
6841
+
6842
+ // Filter billing info: only include non-empty values
6843
+ let filteredBilling = fieldSection.billing.filter { !($0.value.trimmingCharacters(in: .whitespaces).isEmpty) }
6844
+ paymentDoneVC.billingInfoData = filteredBilling
6845
+ var billingDict: [String: Any] = [:]
6846
+ filteredBilling.forEach { billingDict[$0.name] = $0.value }
6847
+ paymentDoneVC.billingInfo = billingDict
6848
+
6849
+ // Filter additional info: only include non-empty values
6850
+ let filteredAdditional = fieldSection.additional.filter { !($0.value.trimmingCharacters(in: .whitespaces).isEmpty) }
6851
+ paymentDoneVC.additionalInfoData = filteredAdditional
6852
+ var additionalDict: [String: Any] = [:]
6853
+ filteredAdditional.forEach { additionalDict[$0.name] = $0.value }
6854
+ paymentDoneVC.additionalInfo = additionalDict
6855
+ }
6856
+ self.navigationController?.pushViewController(paymentDoneVC, animated: true)
6857
+ }
6858
+ }
6859
+ }
6860
+ } else {
6861
+ self.presentPaymentErrorVC(errorMessage: "Invalid JSON format")
6862
+ }
6863
+ } catch let jsonError {
6864
+ self.presentPaymentErrorVC(errorMessage: "Error parsing JSON: \(jsonError)")
6865
+ }
6866
+ } else {
6867
+ self.presentPaymentErrorVC(errorMessage: "No data received")
6868
+ }
6869
+ } else {
6870
+ if let data = serviceData,
6871
+ let responseObj = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
6872
+ let message = responseObj["message"] as? String {
6873
+ self.presentPaymentErrorVC(errorMessage: message)
6874
+ } else {
6875
+ self.presentPaymentErrorVC(errorMessage: "HTTP Status Code: \(httpResponse.statusCode)")
6876
+ }
6877
+ }
6878
+ }
6879
+ task.resume()
6880
+ }
6881
+
6161
6882
  //MARK: - Update Cards Api.
6162
6883
  func updateCardApi(cardID: String) {
6163
6884
  showLoadingIndicator()
@@ -7691,44 +8412,22 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
7691
8412
  paymentDoneVC.chargeData = responseObject
7692
8413
  paymentDoneVC.easyPayDelegate = self.easyPayDelegate
7693
8414
  paymentDoneVC.amount = self.amount
7694
- // // Pass billingInfo and additionalInfo
7695
- // if let billingData = self.request.billingInfoData,
7696
- // let billingInfoDict = try? JSONSerialization.jsonObject(with: billingData, options: []) as? [String: Any] {
7697
- //
7698
- // // Extract main billing fields
7699
- // let cleanBillingInfo: [String: Any] = [
7700
- // "postal_code": billingInfoDict["postal_code"] ?? "",
7701
- // "country": billingInfoDict["country"] ?? "",
7702
- // "city": billingInfoDict["city"] ?? "",
7703
- // "address": billingInfoDict["address"] ?? "",
7704
- // "state": billingInfoDict["state"] ?? ""
7705
- // ]
7706
- // paymentDoneVC.billingInfo = cleanBillingInfo
7707
- //
7708
- // // Extract additional_info
7709
- // if let additional = billingInfoDict["additional_info"] as? [String: Any] {
7710
- // let cleanAdditionalInfo: [String: Any] = [
7711
- // "email": additional["email"] ?? "",
7712
- // "phone_number": additional["phone_number"] ?? "",
7713
- // "name": additional["name"] ?? "",
7714
- // "country_code": additional["country_code"] ?? ""
7715
- // ]
7716
- // paymentDoneVC.additionalInfo = cleanAdditionalInfo
7717
- // }
7718
- // }
7719
-
7720
8415
  // Pass billing info and additional info if available
7721
8416
  if let billingInfoData = self.request.billingInfoData,
7722
8417
  let fieldSection = try? JSONDecoder().decode(FieldSection.self, from: billingInfoData) {
7723
8418
 
7724
- paymentDoneVC.billingInfoData = fieldSection.billing
8419
+ // Filter billing info: only include non-empty values
8420
+ let filteredBilling = fieldSection.billing.filter { !($0.value.trimmingCharacters(in: .whitespaces).isEmpty) }
8421
+ paymentDoneVC.billingInfoData = filteredBilling
7725
8422
  var billingDict: [String: Any] = [:]
7726
- fieldSection.billing.forEach { billingDict[$0.name] = $0.value }
8423
+ filteredBilling.forEach { billingDict[$0.name] = $0.value }
7727
8424
  paymentDoneVC.billingInfo = billingDict
7728
-
7729
- paymentDoneVC.additionalInfoData = fieldSection.additional
8425
+
8426
+ // Filter additional info: only include non-empty values
8427
+ let filteredAdditional = fieldSection.additional.filter { !($0.value.trimmingCharacters(in: .whitespaces).isEmpty) }
8428
+ paymentDoneVC.additionalInfoData = filteredAdditional
7730
8429
  var additionalDict: [String: Any] = [:]
7731
- fieldSection.additional.forEach { additionalDict[$0.name] = $0.value }
8430
+ filteredAdditional.forEach { additionalDict[$0.name] = $0.value }
7732
8431
  paymentDoneVC.additionalInfo = additionalDict
7733
8432
  }
7734
8433
  self.navigationController?.pushViewController(paymentDoneVC, animated: true)
@@ -8007,14 +8706,18 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
8007
8706
  if let billingInfoData = self.request.billingInfoData,
8008
8707
  let fieldSection = try? JSONDecoder().decode(FieldSection.self, from: billingInfoData) {
8009
8708
 
8010
- paymentDoneVC.billingInfoData = fieldSection.billing
8709
+ // Filter billing info: only include non-empty values
8710
+ let filteredBilling = fieldSection.billing.filter { !($0.value.trimmingCharacters(in: .whitespaces).isEmpty) }
8711
+ paymentDoneVC.billingInfoData = filteredBilling
8011
8712
  var billingDict: [String: Any] = [:]
8012
- fieldSection.billing.forEach { billingDict[$0.name] = $0.value }
8713
+ filteredBilling.forEach { billingDict[$0.name] = $0.value }
8013
8714
  paymentDoneVC.billingInfo = billingDict
8014
-
8015
- paymentDoneVC.additionalInfoData = fieldSection.additional
8715
+
8716
+ // Filter additional info: only include non-empty values
8717
+ let filteredAdditional = fieldSection.additional.filter { !($0.value.trimmingCharacters(in: .whitespaces).isEmpty) }
8718
+ paymentDoneVC.additionalInfoData = filteredAdditional
8016
8719
  var additionalDict: [String: Any] = [:]
8017
- fieldSection.additional.forEach { additionalDict[$0.name] = $0.value }
8720
+ filteredAdditional.forEach { additionalDict[$0.name] = $0.value }
8018
8721
  paymentDoneVC.additionalInfo = additionalDict
8019
8722
  }
8020
8723
  self.navigationController?.pushViewController(paymentDoneVC, animated: true)