@jimrising/easymerchantsdk-react-native 1.0.6 → 1.0.8

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 (81) hide show
  1. package/.idea/workspace.xml +708 -24
  2. package/README.md +2 -2
  3. package/android/build.gradle +1 -1
  4. package/android/src/main/java/com/reactlibrary/RNEasymerchantsdkModule.java +5 -4
  5. package/ios/Bundle/EasyPayBundle.swift +0 -1
  6. package/ios/Classes/EasyMerchantSdk.m +16 -14
  7. package/ios/Classes/EasyMerchantSdk.swift +1 -30
  8. package/ios/Classes/EasyPayViewController.swift +15 -19
  9. package/ios/Example/ViewController.swift +14 -16
  10. package/ios/Models/Request.swift +37 -18
  11. package/ios/Pods/ViewControllers/AdditionalInfoVC.swift +37 -92
  12. package/ios/Pods/ViewControllers/BillingInfoVC/BillingInfoVC.swift +403 -296
  13. package/ios/Pods/ViewControllers/EmailVerificationVC.swift +6 -15
  14. package/ios/Pods/ViewControllers/OTPVerificationVC.swift +36 -90
  15. package/ios/Pods/ViewControllers/PaymentInformation/PaymentInfoVC.swift +107 -222
  16. package/ios/easymerchantsdk.podspec +3 -18
  17. package/package.json +6 -15
  18. package/src/index.js +2 -2
  19. package/.idea/caches/deviceStreaming.xml +0 -340
  20. package/.idea/em-MobileCheckoutSDK-ReactNative.iml +0 -0
  21. package/.idea/misc.xml +0 -6
  22. package/.idea/modules.xml +0 -0
  23. package/.idea/vcs.xml +0 -6
  24. package/android/build/.transforms/27d3a0c22098810ca42038b1b8102417/results.bin +0 -1
  25. package/android/build/.transforms/27d3a0c22098810ca42038b1b8102417/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/BuildConfig.dex +0 -0
  26. package/android/build/.transforms/27d3a0c22098810ca42038b1b8102417/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkModule$1.dex +0 -0
  27. package/android/build/.transforms/27d3a0c22098810ca42038b1b8102417/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkModule.dex +0 -0
  28. package/android/build/.transforms/27d3a0c22098810ca42038b1b8102417/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkPackage.dex +0 -0
  29. package/android/build/.transforms/27d3a0c22098810ca42038b1b8102417/transformed/bundleLibRuntimeToDirDebug/desugar_graph.bin +0 -0
  30. package/android/build/.transforms/41cd2635778c1bb5c18af2c46eb9196e/results.bin +0 -1
  31. package/android/build/.transforms/41cd2635778c1bb5c18af2c46eb9196e/transformed/classes/classes_dex/classes.dex +0 -0
  32. package/android/build/.transforms/6b36622787f586c4b6e3df98c5efa11c/results.bin +0 -1
  33. package/android/build/.transforms/6b36622787f586c4b6e3df98c5efa11c/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/BuildConfig.dex +0 -0
  34. package/android/build/.transforms/6b36622787f586c4b6e3df98c5efa11c/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkModule$1.dex +0 -0
  35. package/android/build/.transforms/6b36622787f586c4b6e3df98c5efa11c/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkModule.dex +0 -0
  36. package/android/build/.transforms/6b36622787f586c4b6e3df98c5efa11c/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkPackage.dex +0 -0
  37. package/android/build/.transforms/6b36622787f586c4b6e3df98c5efa11c/transformed/bundleLibRuntimeToDirDebug/desugar_graph.bin +0 -0
  38. package/android/build/.transforms/7eb7ceaa43c9e8323ac65b4f785987b6/results.bin +0 -1
  39. package/android/build/.transforms/7eb7ceaa43c9e8323ac65b4f785987b6/transformed/classes/classes_dex/classes.dex +0 -0
  40. package/android/build/.transforms/a8b93af4be449a0e2cca4bd6ddb6685e/results.bin +0 -1
  41. package/android/build/.transforms/a8b93af4be449a0e2cca4bd6ddb6685e/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/BuildConfig.dex +0 -0
  42. package/android/build/.transforms/a8b93af4be449a0e2cca4bd6ddb6685e/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkModule$1.dex +0 -0
  43. package/android/build/.transforms/a8b93af4be449a0e2cca4bd6ddb6685e/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkModule.dex +0 -0
  44. package/android/build/.transforms/a8b93af4be449a0e2cca4bd6ddb6685e/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkPackage.dex +0 -0
  45. package/android/build/.transforms/a8b93af4be449a0e2cca4bd6ddb6685e/transformed/bundleLibRuntimeToDirDebug/desugar_graph.bin +0 -0
  46. package/android/build/.transforms/f1a160720415bc76d8d6c6734c5acf3e/results.bin +0 -1
  47. package/android/build/.transforms/f1a160720415bc76d8d6c6734c5acf3e/transformed/classes/classes_dex/classes.dex +0 -0
  48. package/android/build/generated/source/buildConfig/debug/com/reactlibrary/BuildConfig.java +0 -10
  49. package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +0 -7
  50. package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json +0 -18
  51. package/android/build/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties +0 -6
  52. package/android/build/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json +0 -1
  53. package/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
  54. package/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar +0 -0
  55. package/android/build/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt +0 -0
  56. package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +0 -1
  57. package/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml +0 -2
  58. package/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +0 -2
  59. package/android/build/intermediates/incremental/mergeDebugShaders/merger.xml +0 -2
  60. package/android/build/intermediates/incremental/packageDebugAssets/merger.xml +0 -2
  61. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/BuildConfig.class +0 -0
  62. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule$1.class +0 -0
  63. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule.class +0 -0
  64. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkPackage.class +0 -0
  65. package/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt +0 -2
  66. package/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +0 -7
  67. package/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +0 -7
  68. package/android/build/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json +0 -1
  69. package/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt +0 -1
  70. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/BuildConfig.class +0 -0
  71. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/RNEasymerchantsdkModule$1.class +0 -0
  72. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/RNEasymerchantsdkModule.class +0 -0
  73. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/RNEasymerchantsdkPackage.class +0 -0
  74. package/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
  75. package/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt +0 -1
  76. package/android/build/outputs/logs/manifest-merger-debug-report.txt +0 -17
  77. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/RNEasymerchantsdkModule$1.class.uniqueId2 +0 -0
  78. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/RNEasymerchantsdkModule.class.uniqueId1 +0 -0
  79. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/RNEasymerchantsdkPackage.class.uniqueId0 +0 -0
  80. package/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
  81. package/ios/EnvironmentConfig.swift +0 -63
@@ -7,14 +7,12 @@
7
7
 
8
8
  import UIKit
9
9
 
10
- @available(iOS 16.0, *)
11
-
12
10
  protocol BillingInfoVCDelegate: AnyObject {
13
11
  func didPassTextBack(_ text: String)
14
12
  }
15
13
 
16
14
  class BillingInfoVC: BaseVC {
17
-
15
+
18
16
  @IBOutlet weak var viewBillingInfo: UIView!
19
17
  @IBOutlet weak var btnPrevious: UIButton!
20
18
  @IBOutlet weak var viewCountryList: UIView!
@@ -28,123 +26,116 @@ class BillingInfoVC: BaseVC {
28
26
  @IBOutlet weak var tblViewCityList: UITableView!
29
27
  @IBOutlet weak var txtFieldCity: UITextField!
30
28
  @IBOutlet weak var txtFieldPostalCode: UITextField!
31
-
29
+
32
30
  @IBOutlet weak var buttonBottomConstraint: NSLayoutConstraint!
33
-
31
+
34
32
  // Variable to store the auth token
35
33
  var authToken: String?
36
-
34
+
37
35
  var countryList: [[String: Any]] = []
38
36
  var stateList: [[String: Any]] = []
39
37
  var cityList: [[String: Any]] = []
40
-
38
+
41
39
  var billingInfoData: [String: Any]?
42
-
40
+
43
41
  var cardNumber: String?
44
42
  var expiryDate: String?
45
43
  var cvv: String?
46
44
  var nameOnCard: String?
47
-
45
+
48
46
  //Banking Params
49
47
  var accountName: String?
50
48
  var routingNumber: String?
51
49
  var accountType: String?
52
50
  var accountNumber: String?
53
-
51
+
54
52
  var selectedPaymentMethod: String?
55
-
53
+
56
54
  private let keyboardObserver = KeyboardObserver()
57
-
55
+
58
56
  var isSavedForFuture: Bool = false
59
57
  var isSavedNewCard: Bool = false
60
-
58
+
61
59
  private var request: Request!
62
60
  var selectedCard: CardModel?
63
61
  var amount: Int?
64
62
  var cvvText: String?
65
-
63
+
66
64
  var isFrom = String()
67
-
65
+
68
66
  //From Regular Saved Bank Accounts
69
67
  var customerID: String?
70
68
  var accountID: String?
71
-
69
+
72
70
  var isSavedNewAccount: Bool?
73
-
71
+
74
72
  weak var delegate: BillingInfoVCDelegate?
75
-
73
+
76
74
  override func viewDidLoad() {
77
75
  super.viewDidLoad()
78
-
76
+
79
77
  viewBillingInfo.layer.borderColor = UIColor.systemGray.cgColor
80
78
  viewBillingInfo.layer.borderWidth = 1
81
79
  viewBillingInfo.layer.cornerRadius = 8
82
-
80
+
83
81
  btnPrevious.layer.borderColor = UIColor.systemBlue.cgColor
84
82
  btnPrevious.layer.borderWidth = 1
85
83
  btnPrevious.layer.cornerRadius = 8
86
-
84
+
87
85
  setupShadowForListViews()
88
-
86
+
89
87
  tblViewCountryList.delegate = self
90
88
  tblViewCountryList.dataSource = self
91
89
  viewCountryList.isHidden = true
92
-
90
+
93
91
  tblViewStateList.delegate = self
94
92
  tblViewStateList.dataSource = self
95
93
  viewStateList.isHidden = true
96
-
94
+
97
95
  tblViewCityList.delegate = self
98
96
  tblViewCityList.dataSource = self
99
97
  viewCityList.isHidden = true
100
-
98
+
101
99
  txtFieldCity.delegate = self
102
100
  txtFieldState.delegate = self
103
101
  txtFieldAddress.delegate = self
104
102
  txtFieldCountry.delegate = self
105
103
  txtFieldPostalCode.delegate = self
106
-
107
- getTokenApi()
108
-
104
+
105
+ getCountryListApi()
106
+
109
107
  // Add tap gesture to hide the views and dismiss the keyboard
110
108
  let tapGesture = UITapGestureRecognizer(target: self, action: #selector(didTapOutside))
111
109
  tapGesture.cancelsTouchesInView = false
112
110
  self.view.addGestureRecognizer(tapGesture)
113
-
111
+
114
112
  // Print data for verification
115
113
  if let billingInfoData = billingInfoData {
116
114
  print("Billing Info Data: \(billingInfoData)")
117
-
115
+
118
116
  if let address = billingInfoData["address"] as? String {
119
117
  txtFieldAddress.text = address
120
118
  }
121
-
119
+
122
120
  if let country = billingInfoData["country"] as? String {
123
121
  txtFieldCountry.text = country
124
122
  }
125
-
123
+
126
124
  if let state = billingInfoData["state"] as? String {
127
125
  txtFieldState.text = state
128
126
  }
129
-
127
+
130
128
  if let city = billingInfoData["city"] as? String {
131
129
  txtFieldCity.text = city
132
130
  }
133
-
131
+
134
132
  if let postalCode = billingInfoData["postal_code"] as? String {
135
133
  txtFieldPostalCode.text = postalCode
136
134
  }
137
135
  }
138
-
139
- print(accountName ?? "")
140
- print(routingNumber ?? "")
141
- print(accountType ?? "")
142
- print(accountNumber ?? "")
143
- print(billingInfoData ?? "")
144
- print(selectedPaymentMethod ?? "")
145
- print(isSavedForFuture)
136
+
146
137
  }
147
-
138
+
148
139
  override func viewWillAppear(_ animated: Bool) {
149
140
  super.viewWillAppear(animated)
150
141
  keyboardObserver.animateChanges({ [self] height in
@@ -154,32 +145,32 @@ class BillingInfoVC: BaseVC {
154
145
  self.view.layoutIfNeeded()
155
146
  })
156
147
  }
157
-
148
+
158
149
  override func viewWillDisappear(_ animated: Bool) {
159
150
  super.viewWillDisappear(animated)
160
151
  keyboardObserver.invalidate()
161
152
  }
162
-
153
+
163
154
  @objc func didTapOutside() {
164
155
  // Dismiss the keyboard
165
156
  self.view.endEditing(true)
166
-
157
+
167
158
  // Hide the country list view if it is visible
168
159
  if !viewCountryList.isHidden {
169
160
  viewCountryList.isHidden = true
170
161
  }
171
-
162
+
172
163
  // Hide the state list view if it is visible
173
164
  if !viewStateList.isHidden {
174
165
  viewStateList.isHidden = true
175
166
  }
176
-
167
+
177
168
  // Hide the city list view if it is visible
178
169
  if !viewCityList.isHidden {
179
170
  viewCityList.isHidden = true
180
171
  }
181
172
  }
182
-
173
+
183
174
  func setupShadowForListViews() {
184
175
  // Ensure the view does not clip its content or shadows
185
176
  viewCountryList.clipsToBounds = false
@@ -191,7 +182,7 @@ class BillingInfoVC: BaseVC {
191
182
  // Optionally, you might want to set a corner radius to the view as well
192
183
  viewCountryList.layer.cornerRadius = 8
193
184
  tblViewCountryList.layer.cornerRadius = 8
194
-
185
+
195
186
  // Ensure the view does not clip its content or shadows
196
187
  viewStateList.clipsToBounds = false
197
188
  // Apply shadow properties
@@ -202,7 +193,7 @@ class BillingInfoVC: BaseVC {
202
193
  // Optionally, you might want to set a corner radius to the view as well
203
194
  viewStateList.layer.cornerRadius = 8
204
195
  tblViewStateList.layer.cornerRadius = 8
205
-
196
+
206
197
  // Ensure the view does not clip its content or shadows
207
198
  viewCityList.clipsToBounds = false
208
199
  // Apply shadow properties
@@ -214,222 +205,344 @@ class BillingInfoVC: BaseVC {
214
205
  viewCityList.layer.cornerRadius = 8
215
206
  tblViewCityList.layer.cornerRadius = 8
216
207
  }
217
-
218
- //MARK: Get Auth Token
219
- func getTokenApi() {
220
- showLoadingIndicator()
221
- let session = URLSession.shared
222
- let serviceURL = URL(string: "https://www.universal-tutorial.com/api/getaccesstoken")!
223
-
224
- var request = URLRequest(url: serviceURL)
225
- request.httpMethod = "GET"
226
-
227
- // Add the headers
228
- request.addValue("nL1j-qXjd2cH3N4ZZ7SeL5TCI2mKhXdxFYh52DjahJyrSxAmQXeDJQADwkRO0fZSy84", forHTTPHeaderField: "api-token")
229
- request.addValue("bright.developer7@gmail.com", forHTTPHeaderField: "user-email")
230
-
231
- let task = session.dataTask(with: request) { (serviceData, serviceResponse, error) in
232
-
233
- if error == nil {
234
- if let httpResponse = serviceResponse as? HTTPURLResponse, httpResponse.statusCode == 200 {
235
- if let data = serviceData {
236
- do {
237
- self.hideLoadingIndicator()
238
- if let jsonData = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any],
239
- let authToken = jsonData["auth_token"] as? String {
240
- // Save the auth token to the variable
241
- self.authToken = authToken
242
- print("Auth Token: \(authToken)")
243
- self.getCountryListApi()
244
- } else {
245
- self.hideLoadingIndicator()
246
- print("Error: Unable to parse JSON or find auth_token")
247
- }
248
- } catch {
249
- self.hideLoadingIndicator()
250
- print("Error parsing JSON: \(error.localizedDescription)")
251
- }
252
- }
253
- } else {
254
- self.hideLoadingIndicator()
255
- print("Error: HTTP Status Code \(String(describing: (serviceResponse as? HTTPURLResponse)?.statusCode))")
256
- }
257
- } else {
258
- self.hideLoadingIndicator()
259
- print("Error: \(error?.localizedDescription ?? "Unknown error")")
260
- }
261
- }
262
- task.resume()
263
- }
264
-
208
+
265
209
  //MARK: Get Country List
266
210
  func getCountryListApi() {
267
- guard let authToken = authToken else {
268
- print("Auth token is missing")
269
- return
270
- }
271
-
272
211
  let session = URLSession.shared
273
- let serviceURL = URL(string: "https://www.universal-tutorial.com/api/countries")!
274
-
212
+ let serviceURL = URL(string: "https://countriesnow.space/api/v0.1/countries/iso")!
213
+
275
214
  var request = URLRequest(url: serviceURL)
276
215
  request.httpMethod = "GET"
277
-
278
- request.addValue("Bearer \(authToken)", forHTTPHeaderField: "Authorization")
279
-
216
+
280
217
  let task = session.dataTask(with: request) { (serviceData, serviceResponse, error) in
281
-
282
- if error == nil {
283
- if let httpResponse = serviceResponse as? HTTPURLResponse, httpResponse.statusCode == 200 {
284
- if let data = serviceData {
285
- do {
286
- if let jsonData = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [[String: Any]] {
287
- self.countryList = jsonData
288
- DispatchQueue.main.async {
289
- self.tblViewCountryList.reloadData()
290
- }
291
- } else {
292
- self.hideLoadingIndicator()
293
- print("Error: Unable to parse JSON or find country data")
294
- }
295
- } catch {
296
- self.hideLoadingIndicator()
297
- print("Error parsing JSON: \(error.localizedDescription)")
298
- }
218
+ if let error = error {
219
+ self.hideLoadingIndicator()
220
+ print("Error: \(error.localizedDescription)")
221
+ return
222
+ }
223
+
224
+ guard let httpResponse = serviceResponse as? HTTPURLResponse, httpResponse.statusCode == 200 else {
225
+ self.hideLoadingIndicator()
226
+ print("Error: HTTP Status Code \(String(describing: (serviceResponse as? HTTPURLResponse)?.statusCode))")
227
+ return
228
+ }
229
+
230
+ guard let data = serviceData else {
231
+ self.hideLoadingIndicator()
232
+ print("Error: No data received")
233
+ return
234
+ }
235
+
236
+ do {
237
+ if let jsonResponse = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any],
238
+ let countryData = jsonResponse["data"] as? [[String: Any]] {
239
+
240
+ self.countryList = countryData // Store the list of countries
241
+
242
+ DispatchQueue.main.async {
243
+ self.tblViewCountryList.reloadData() // Reload the table view
299
244
  }
300
245
  } else {
301
246
  self.hideLoadingIndicator()
302
- print("Error: HTTP Status Code \(String(describing: (serviceResponse as? HTTPURLResponse)?.statusCode))")
247
+ print("Error: Unable to parse JSON or find country data")
303
248
  }
304
- } else {
249
+ } catch {
305
250
  self.hideLoadingIndicator()
306
- print("Error: \(error?.localizedDescription ?? "Unknown error")")
251
+ print("Error parsing JSON: \(error.localizedDescription)")
307
252
  }
308
253
  }
309
254
  task.resume()
310
255
  }
311
-
312
- //MARK: Get State List
256
+
257
+ ///** Normal Case
258
+ // //MARK: Get State List
259
+ // func getStateListApi(for country: String) {
260
+ // let urlString = "https://countriesnow.space/api/v0.1/countries/states"
261
+ // guard let serviceURL = URL(string: urlString) else {
262
+ // print("Invalid URL")
263
+ // hideLoadingIndicator()
264
+ // return
265
+ // }
266
+ //
267
+ // var request = URLRequest(url: serviceURL)
268
+ // request.httpMethod = "POST"
269
+ // request.addValue("application/json", forHTTPHeaderField: "Content-Type")
270
+ //
271
+ // let params: [String: Any] = [
272
+ // "country": country
273
+ // ]
274
+ //
275
+ // do {
276
+ // let jsonData = try JSONSerialization.data(withJSONObject: params, options: .prettyPrinted)
277
+ // request.httpBody = jsonData
278
+ // } catch {
279
+ // print("Error creating JSON data: \(error)")
280
+ // return
281
+ // }
282
+ //
283
+ // let session = URLSession.shared
284
+ // let task = session.dataTask(with: request) { (serviceData, serviceResponse, error) in
285
+ // if let error = error {
286
+ // print("Error: \(error.localizedDescription)")
287
+ // return
288
+ // }
289
+ //
290
+ // guard let httpResponse = serviceResponse as? HTTPURLResponse, httpResponse.statusCode == 200 else {
291
+ // print("Invalid response or status code")
292
+ // return
293
+ // }
294
+ //
295
+ // if let data = serviceData {
296
+ // do {
297
+ // if let responseObject = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
298
+ // let dataObject = responseObject["data"] as? [String: Any],
299
+ // let statesArray = dataObject["states"] as? [[String: Any]] {
300
+ //
301
+ // DispatchQueue.main.async {
302
+ // self.stateList = statesArray
303
+ // self.tblViewStateList.reloadData()
304
+ //
305
+ // // Pick a random state and set it in txtFieldState
306
+ // if let randomState = statesArray.randomElement(),
307
+ // let stateName = randomState["name"] as? String {
308
+ // self.txtFieldState.text = stateName
309
+ //
310
+ // // Fetch cities for the randomly selected state and country
311
+ // if let country = self.txtFieldCountry.text {
312
+ // self.getCityListListApi(for: country, state: stateName)
313
+ // }
314
+ // } else {
315
+ // self.txtFieldState.text = "" // No state available
316
+ // }
317
+ // }
318
+ // } else {
319
+ // print("Error: Invalid JSON structure")
320
+ // }
321
+ // } catch {
322
+ // print("Error parsing JSON: \(error)")
323
+ // }
324
+ // } else {
325
+ // print("No data received")
326
+ // }
327
+ // }
328
+ // task.resume()
329
+ // }
330
+ //
331
+
332
+ ///** Normal Case
333
+ // //MARK: Get City List
334
+ // func getCityListListApi(for country: String, state: String) {
335
+ // let urlString = "https://countriesnow.space/api/v0.1/countries/state/cities"
336
+ // guard let serviceURL = URL(string: urlString) else {
337
+ // print("Invalid URL")
338
+ // hideLoadingIndicator()
339
+ // return
340
+ // }
341
+ //
342
+ // var request = URLRequest(url: serviceURL)
343
+ // request.httpMethod = "POST"
344
+ // request.addValue("application/json", forHTTPHeaderField: "Content-Type")
345
+ //
346
+ // let params: [String: Any] = [
347
+ // "country": country,
348
+ // "state": state
349
+ // ]
350
+ //
351
+ // do {
352
+ // let jsonData = try JSONSerialization.data(withJSONObject: params, options: .prettyPrinted)
353
+ // request.httpBody = jsonData
354
+ // } catch {
355
+ // print("Error creating JSON data: \(error)")
356
+ // return
357
+ // }
358
+ //
359
+ // let session = URLSession.shared
360
+ // let task = session.dataTask(with: request) { (serviceData, serviceResponse, error) in
361
+ // if let error = error {
362
+ // print("Error: \(error.localizedDescription)")
363
+ // return
364
+ // }
365
+ //
366
+ // guard let httpResponse = serviceResponse as? HTTPURLResponse, httpResponse.statusCode == 200 else {
367
+ // print("Invalid response or status code")
368
+ // return
369
+ // }
370
+ //
371
+ // if let data = serviceData {
372
+ // do {
373
+ // if let responseObject = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
374
+ // let citiesArray = responseObject["data"] as? [String] { // Directly accessing city list array
375
+ //
376
+ // DispatchQueue.main.async {
377
+ // self.cityList = citiesArray.map { ["city_name": $0] } // Converting to expected format
378
+ // self.tblViewCityList.reloadData()
379
+ //
380
+ // // Pick a random city and set it in txtFieldCity
381
+ // if let randomCity = citiesArray.randomElement() {
382
+ // self.txtFieldCity.text = randomCity
383
+ // } else {
384
+ // self.txtFieldCity.text = "" // No city available
385
+ // }
386
+ // }
387
+ // } else {
388
+ // print("Error: Invalid JSON structure")
389
+ // }
390
+ // } catch {
391
+ // print("Error parsing JSON: \(error)")
392
+ // }
393
+ // } else {
394
+ // print("No data received")
395
+ // }
396
+ // }
397
+ // task.resume()
398
+ // }
399
+
400
+
401
+ ///**In case of state and city name not found
313
402
  func getStateListApi(for country: String) {
314
- guard let authToken = authToken else {
315
- print("Auth token is missing")
403
+ let urlString = "https://countriesnow.space/api/v0.1/countries/states"
404
+ guard let serviceURL = URL(string: urlString) else {
405
+ print("Invalid URL")
406
+ hideLoadingIndicator()
316
407
  return
317
408
  }
318
-
319
- let session = URLSession.shared
320
- let serviceURLString = "https://www.universal-tutorial.com/api/states/\(country.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed)!)"
321
-
322
- guard let serviceURL = URL(string: serviceURLString) else {
323
- print("Error: Invalid URL")
409
+
410
+ var request = URLRequest(url: serviceURL)
411
+ request.httpMethod = "POST"
412
+ request.addValue("application/json", forHTTPHeaderField: "Content-Type")
413
+
414
+ let params: [String: Any] = [
415
+ "country": country
416
+ ]
417
+
418
+ do {
419
+ let jsonData = try JSONSerialization.data(withJSONObject: params, options: .prettyPrinted)
420
+ request.httpBody = jsonData
421
+ } catch {
422
+ print("Error creating JSON data: \(error)")
324
423
  return
325
424
  }
326
-
327
- var request = URLRequest(url: serviceURL)
328
- request.httpMethod = "GET"
329
- request.addValue("Bearer \(authToken)", forHTTPHeaderField: "Authorization")
330
-
425
+
426
+ let session = URLSession.shared
331
427
  let task = session.dataTask(with: request) { (serviceData, serviceResponse, error) in
332
-
333
- if error == nil {
334
- if let httpResponse = serviceResponse as? HTTPURLResponse, httpResponse.statusCode == 200 {
335
- if let data = serviceData {
336
- do {
337
- if let jsonData = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [[String: Any]] {
338
- self.stateList = jsonData
339
-
340
- // Automatically select the first state
341
- if let firstState = self.stateList.first?["state_name"] as? String {
342
- DispatchQueue.main.async {
343
- self.txtFieldState.text = firstState
344
- // Fetch cities for the first state
345
- self.getCityListListApi(for: firstState)
346
- }
347
- }
348
-
349
- DispatchQueue.main.async {
350
- self.tblViewStateList.reloadData()
351
- }
428
+ if let error = error {
429
+ print("Error: \(error.localizedDescription)")
430
+ return
431
+ }
432
+
433
+ guard let httpResponse = serviceResponse as? HTTPURLResponse, httpResponse.statusCode == 200 else {
434
+ print("Invalid response or status code")
435
+ return
436
+ }
437
+
438
+ if let data = serviceData {
439
+ do {
440
+ if let responseObject = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
441
+ let dataObject = responseObject["data"] as? [String: Any],
442
+ let statesArray = dataObject["states"] as? [[String: Any]] {
443
+
444
+ DispatchQueue.main.async {
445
+ self.stateList = statesArray
446
+ self.tblViewStateList.reloadData()
447
+
448
+ // If no state is found, clear the state and city fields and fill country in both
449
+ if statesArray.isEmpty {
450
+ self.txtFieldState.text = country
451
+ self.txtFieldCity.text = country
352
452
  } else {
353
- self.hideLoadingIndicator()
354
- print("Error: Unable to parse JSON or find state data")
453
+ // Pick a random state and set it in txtFieldState
454
+ if let randomState = statesArray.randomElement(),
455
+ let stateName = randomState["name"] as? String {
456
+ self.txtFieldState.text = stateName
457
+
458
+ // Fetch cities for the randomly selected state and country
459
+ self.getCityListListApi(for: country, state: stateName)
460
+ }
355
461
  }
356
- } catch {
357
- self.hideLoadingIndicator()
358
- print("Error parsing JSON: \(error.localizedDescription)")
359
462
  }
463
+ } else {
464
+ print("Error: Invalid JSON structure")
360
465
  }
361
- } else {
362
- self.hideLoadingIndicator()
363
- print("Error: HTTP Status Code \(String(describing: (serviceResponse as? HTTPURLResponse)?.statusCode))")
466
+ } catch {
467
+ print("Error parsing JSON: \(error)")
364
468
  }
365
469
  } else {
366
- self.hideLoadingIndicator()
367
- print("Error: \(error?.localizedDescription ?? "Unknown error")")
470
+ print("No data received")
368
471
  }
369
472
  }
370
473
  task.resume()
371
474
  }
372
-
373
- //MARK: Get City List
374
- func getCityListListApi(for state: String) {
375
- guard let authToken = authToken else {
376
- print("Auth token is missing")
475
+
476
+ ///**In case of state and city name not found
477
+ func getCityListListApi(for country: String, state: String) {
478
+ let urlString = "https://countriesnow.space/api/v0.1/countries/state/cities"
479
+ guard let serviceURL = URL(string: urlString) else {
480
+ print("Invalid URL")
481
+ hideLoadingIndicator()
377
482
  return
378
483
  }
379
-
380
- let session = URLSession.shared
381
- let serviceURLString = "https://www.universal-tutorial.com/api/cities/\(state.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed)!)"
382
-
383
- guard let serviceURL = URL(string: serviceURLString) else {
384
- print("Error: Invalid URL")
484
+
485
+ var request = URLRequest(url: serviceURL)
486
+ request.httpMethod = "POST"
487
+ request.addValue("application/json", forHTTPHeaderField: "Content-Type")
488
+
489
+ let params: [String: Any] = [
490
+ "country": country,
491
+ "state": state
492
+ ]
493
+
494
+ do {
495
+ let jsonData = try JSONSerialization.data(withJSONObject: params, options: .prettyPrinted)
496
+ request.httpBody = jsonData
497
+ } catch {
498
+ print("Error creating JSON data: \(error)")
385
499
  return
386
500
  }
387
-
388
- var request = URLRequest(url: serviceURL)
389
- request.httpMethod = "GET"
390
- request.addValue("Bearer \(authToken)", forHTTPHeaderField: "Authorization")
391
-
501
+
502
+ let session = URLSession.shared
392
503
  let task = session.dataTask(with: request) { (serviceData, serviceResponse, error) in
393
-
394
- if error == nil {
395
- if let httpResponse = serviceResponse as? HTTPURLResponse, httpResponse.statusCode == 200 {
396
- if let data = serviceData {
397
- do {
398
- if let jsonData = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [[String: Any]] {
399
- self.cityList = jsonData
400
-
401
- DispatchQueue.main.async {
402
- if self.cityList.isEmpty {
403
- self.txtFieldCity.text = "" // Clear the city field if no cities are available
404
- } else {
405
- // Automatically select the first city if available
406
- if let firstCity = self.cityList.first?["city_name"] as? String {
407
- self.txtFieldCity.text = firstCity
408
- }
409
- }
410
- self.tblViewCityList.reloadData()
411
- }
504
+ if let error = error {
505
+ print("Error: \(error.localizedDescription)")
506
+ return
507
+ }
508
+
509
+ guard let httpResponse = serviceResponse as? HTTPURLResponse, httpResponse.statusCode == 200 else {
510
+ print("Invalid response or status code")
511
+ return
512
+ }
513
+
514
+ if let data = serviceData {
515
+ do {
516
+ if let responseObject = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
517
+ let citiesArray = responseObject["data"] as? [String] { // Directly accessing city list array
518
+
519
+ DispatchQueue.main.async {
520
+ self.cityList = citiesArray.map { ["city_name": $0] } // Converting to expected format
521
+ self.tblViewCityList.reloadData()
522
+
523
+ // If no cities found, set state name in city field
524
+ if citiesArray.isEmpty {
525
+ self.txtFieldCity.text = self.txtFieldState.text
412
526
  } else {
413
- self.hideLoadingIndicator()
414
- print("Error: Unable to parse JSON or find city data")
527
+ // Pick a random city and set it in txtFieldCity
528
+ if let randomCity = citiesArray.randomElement() {
529
+ self.txtFieldCity.text = randomCity
530
+ }
415
531
  }
416
- } catch {
417
- self.hideLoadingIndicator()
418
- print("Error parsing JSON: \(error.localizedDescription)")
419
532
  }
533
+ } else {
534
+ print("Error: Invalid JSON structure")
420
535
  }
421
- } else {
422
- self.hideLoadingIndicator()
423
- print("Error: HTTP Status Code \(String(describing: (serviceResponse as? HTTPURLResponse)?.statusCode))")
536
+ } catch {
537
+ print("Error parsing JSON: \(error)")
424
538
  }
425
539
  } else {
426
- self.hideLoadingIndicator()
427
- print("Error: \(error?.localizedDescription ?? "Unknown error")")
540
+ print("No data received")
428
541
  }
429
542
  }
430
543
  task.resume()
431
544
  }
432
-
545
+
433
546
  func updateBillingInfoData() {
434
547
  billingInfoData?["address"] = txtFieldAddress.text
435
548
  billingInfoData?["country"] = txtFieldCountry.text
@@ -437,31 +550,31 @@ class BillingInfoVC: BaseVC {
437
550
  billingInfoData?["city"] = txtFieldCity.text
438
551
  billingInfoData?["postal_code"] = txtFieldPostalCode.text
439
552
  }
440
-
553
+
441
554
  @IBAction func actionBtnSelectCountry(_ sender: UIButton) {
442
555
  UIView.animate(withDuration: 0.3) {
443
556
  self.viewCountryList.isHidden.toggle()
444
557
  }
445
558
  }
446
-
559
+
447
560
  @IBAction func actionBtnSelectState(_ sender: UIButton) {
448
561
  UIView.animate(withDuration: 0.3) {
449
562
  self.viewStateList.isHidden.toggle()
450
563
  }
451
564
  }
452
-
565
+
453
566
  @IBAction func actionBtnSelectCity(_ sender: UIButton) {
454
567
  UIView.animate(withDuration: 0.3) {
455
568
  self.viewCityList.isHidden.toggle()
456
569
  }
457
570
  }
458
-
571
+
459
572
  @IBAction func actionBtnPrevious(_ sender: UIButton) {
460
573
  // Pass the text back to the previous screen
461
574
  delegate?.didPassTextBack("NewAccount")
462
575
  self.navigationController?.popViewController(animated: true)
463
576
  }
464
-
577
+
465
578
  @IBAction func actionBtnNext(_ sender: UIButton) {
466
579
  let vc = EasyPaySdk.instantiateViewController(withIdentifier: "AdditionalInfoVC") as! AdditionalInfoVC
467
580
  // Set properties on AdditionalInfoVC
@@ -474,39 +587,39 @@ class BillingInfoVC: BaseVC {
474
587
  // Pass the selected payment method
475
588
  vc.selectedPaymentMethod = selectedPaymentMethod
476
589
  vc.isSavedForFuture = isSavedForFuture
477
-
590
+
478
591
  //Banking Case
479
592
  vc.accountName = accountName
480
593
  vc.routingNumber = routingNumber
481
594
  vc.accountType = accountType
482
595
  vc.accountNumber = accountNumber
483
-
596
+
484
597
  vc.customerID = customerID
485
598
  vc.accountID = accountID
486
599
  vc.isFrom = isFrom
487
-
600
+
488
601
  vc.isSavedNewAccount = isSavedNewAccount
489
602
  vc.amount = amount
490
-
603
+
491
604
  if isFrom == "SavedCards" {
492
605
  vc.isFrom = "SavedCards"
493
606
  vc.selectedCard = selectedCard // Passing the selected card data
494
607
  vc.cvvText = cvvText // Passing the CVV text
495
608
  vc.amount = amount
496
609
  }
497
-
610
+
498
611
  if isFrom == "AddNewCard" {
499
612
  vc.isFrom = "AddNewCard"
500
613
  vc.amount = amount
501
614
  vc.isSavedNewCard = isSavedNewCard
502
615
  }
503
-
616
+
504
617
  self.navigationController?.pushViewController(vc, animated: true)
505
618
  }
506
-
619
+
507
620
  }
508
621
 
509
- @available(iOS 16.0, *)
622
+ //MARK: - Table View
510
623
  extension BillingInfoVC: UITableViewDelegate, UITableViewDataSource {
511
624
  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
512
625
  if tableView == tblViewCountryList {
@@ -522,70 +635,74 @@ extension BillingInfoVC: UITableViewDelegate, UITableViewDataSource {
522
635
  return 0
523
636
  }
524
637
  }
525
-
526
- func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
527
- if tableView == tblViewCountryList {
528
- let cell = tableView.dequeueReusableCell(withIdentifier: "CountryListTVC") as! CountryListTVC
529
- let country = countryList[indexPath.row]
530
- cell.lblCountryName.text = country["country_name"] as? String
531
- return cell
532
- } else if tableView == tblViewStateList {
533
- let cell = tableView.dequeueReusableCell(withIdentifier: "StateListTVC") as! StateListTVC
534
- let state = stateList[indexPath.row]
535
- cell.lblStateName.text = state["state_name"] as? String
536
- return cell
537
- } else if tableView == tblViewCityList {
538
- let cell = tableView.dequeueReusableCell(withIdentifier: "CityListTVC") as! CityListTVC
539
- let city = cityList[indexPath.row]
540
- cell.lblCityName.text = city["city_name"] as? String
541
- return cell
542
- } else {
543
- return UITableViewCell()
544
- }
545
- }
546
-
547
- func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
548
- if tableView == tblViewCountryList {
549
- let selectedCountry = countryList[indexPath.row]["country_name"] as? String
550
- txtFieldCountry.text = selectedCountry
551
- viewCountryList.isHidden = true
552
-
553
- // Fetch states for the selected country
554
- if let country = selectedCountry {
555
- getStateListApi(for: country)
638
+
639
+ func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
640
+ if tableView == tblViewCountryList {
641
+ let cell = tableView.dequeueReusableCell(withIdentifier: "CountryListTVC") as! CountryListTVC
642
+ let country = countryList[indexPath.row]
643
+ cell.lblCountryName.text = country["name"] as? String
644
+ return cell
645
+ } else if tableView == tblViewStateList {
646
+ let cell = tableView.dequeueReusableCell(withIdentifier: "StateListTVC") as! StateListTVC
647
+ let state = stateList[indexPath.row]
648
+ cell.lblStateName.text = state["name"] as? String
649
+ return cell
650
+ } else if tableView == tblViewCityList {
651
+ let cell = tableView.dequeueReusableCell(withIdentifier: "CityListTVC") as! CityListTVC
652
+ let city = cityList[indexPath.row]
653
+ cell.lblCityName.text = city["city_name"] as? String
654
+ return cell
655
+ } else {
656
+ return UITableViewCell()
556
657
  }
557
- } else if tableView == tblViewStateList {
558
- let selectedState = stateList[indexPath.row]["state_name"] as? String
559
- txtFieldState.text = selectedState
560
- viewStateList.isHidden = true
561
-
562
- // Fetch cities for the selected state
563
- if let state = selectedState {
564
- getCityListListApi(for: state)
658
+ }
659
+
660
+ func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
661
+ if tableView == tblViewCountryList {
662
+ let selectedCountry = countryList[indexPath.row]["name"] as? String
663
+ txtFieldCountry.text = selectedCountry
664
+ viewCountryList.isHidden = true
665
+
666
+ // Fetch states for the selected country
667
+ if let country = selectedCountry {
668
+ getStateListApi(for: country)
669
+ }
670
+ } else if tableView == tblViewStateList {
671
+ let selectedState = stateList[indexPath.row]["name"] as? String
672
+ txtFieldState.text = selectedState
673
+ viewStateList.isHidden = true
674
+
675
+ // Fetch cities for the selected state and country
676
+ if let state = selectedState, let country = txtFieldCountry.text {
677
+ getCityListListApi(for: country, state: state)
678
+ }
679
+ } else if tableView == tblViewCityList {
680
+ let selectedCity = cityList[indexPath.row]["city_name"] as? String
681
+ txtFieldCity.text = selectedCity
682
+ viewCityList.isHidden = true
683
+
684
+ // Fetch the city list again based on selected state & country
685
+ if let state = txtFieldState.text, let country = txtFieldCountry.text {
686
+ getCityListListApi(for: country, state: state)
687
+ }
565
688
  }
566
- } else if tableView == tblViewCityList {
567
- let selectedCity = cityList[indexPath.row]["city_name"] as? String
568
- txtFieldCity.text = selectedCity
569
- viewCityList.isHidden = true
689
+
690
+ updateBillingInfoData()
570
691
  }
571
-
572
- updateBillingInfoData()
573
- }
574
-
575
-
692
+
576
693
  func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
577
694
  return 50
578
695
  }
579
-
696
+
580
697
  }
581
698
 
582
- @available(iOS 16.0, *)
699
+
583
700
  extension BillingInfoVC: UITextFieldDelegate {
584
701
  func textFieldShouldReturn(_ textField: UITextField) -> Bool {
585
702
  textField.resignFirstResponder() // Dismiss the keyboard
586
703
  return true
587
704
  }
588
-
705
+
589
706
  // Update billingInfoData when user finishes editing a field
590
707
  func textFieldDidEndEditing(_ textField: UITextField) {
591
708
  switch textField {
@@ -603,14 +720,4 @@ extension BillingInfoVC: UITextFieldDelegate {
603
720
  break
604
721
  }
605
722
  }
606
- }
607
-
608
-
609
-
610
-
611
-
612
-
613
-
614
-
615
-
616
-
723
+ }