@jimrising/easymerchantsdk-react-native 1.3.9 → 1.4.2
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.
- package/.idea/caches/deviceStreaming.xml +77 -0
- package/README.md +140 -81
- package/android/.gradle/8.10/checksums/checksums.lock +0 -0
- package/android/.gradle/8.10/checksums/md5-checksums.bin +0 -0
- package/android/.gradle/8.10/checksums/sha1-checksums.bin +0 -0
- package/android/.gradle/8.10/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/8.9/checksums/checksums.lock +0 -0
- package/android/.gradle/8.9/checksums/md5-checksums.bin +0 -0
- package/android/.gradle/8.9/checksums/sha1-checksums.bin +0 -0
- package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
- package/android/.gradle/buildOutputCleanup/cache.properties +1 -1
- package/android/build/.transforms/20e1216b87bd06eaab3c9e5c68d4267a/results.bin +1 -0
- package/android/build/.transforms/20e1216b87bd06eaab3c9e5c68d4267a/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/BuildConfig.dex +0 -0
- package/android/build/.transforms/20e1216b87bd06eaab3c9e5c68d4267a/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkModule$1.dex +0 -0
- package/android/build/.transforms/20e1216b87bd06eaab3c9e5c68d4267a/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkModule$2.dex +0 -0
- package/android/build/.transforms/20e1216b87bd06eaab3c9e5c68d4267a/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkModule.dex +0 -0
- package/android/build/.transforms/20e1216b87bd06eaab3c9e5c68d4267a/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkPackage.dex +0 -0
- package/android/build/.transforms/20e1216b87bd06eaab3c9e5c68d4267a/transformed/bundleLibRuntimeToDirDebug/desugar_graph.bin +0 -0
- package/android/build/.transforms/e9a664a11ce12edf79cd87b1e07aa243/results.bin +1 -0
- package/android/build/.transforms/e9a664a11ce12edf79cd87b1e07aa243/transformed/classes/classes_dex/classes.dex +0 -0
- package/android/build/generated/source/buildConfig/debug/com/reactlibrary/BuildConfig.java +10 -0
- package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +7 -0
- package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json +18 -0
- package/android/build/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties +6 -0
- package/android/build/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json +1 -0
- package/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
- package/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar +0 -0
- package/android/build/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt +0 -0
- package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +1 -0
- package/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml +2 -0
- package/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +2 -0
- package/android/build/intermediates/incremental/mergeDebugShaders/merger.xml +2 -0
- package/android/build/intermediates/incremental/packageDebugAssets/merger.xml +2 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/BuildConfig.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule$1.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule$2.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkPackage.class +0 -0
- package/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt +2 -0
- package/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +7 -0
- package/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +7 -0
- package/android/build/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json +1 -0
- package/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt +1 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/BuildConfig.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/RNEasymerchantsdkModule$1.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/RNEasymerchantsdkModule$2.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/RNEasymerchantsdkModule.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/RNEasymerchantsdkPackage.class +0 -0
- package/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
- package/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt +1 -0
- package/android/build/outputs/logs/manifest-merger-debug-report.txt +17 -0
- package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/RNEasymerchantsdkModule$1.class.uniqueId2 +0 -0
- package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/RNEasymerchantsdkModule$2.class.uniqueId0 +0 -0
- package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/RNEasymerchantsdkModule.class.uniqueId3 +0 -0
- package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/RNEasymerchantsdkPackage.class.uniqueId1 +0 -0
- package/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
- package/android/build.gradle +4 -1
- package/android/src/main/java/com/reactlibrary/RNEasymerchantsdkModule.java +158 -36
- package/android/src/main/java/com/reactlibrary/RNEasymerchantsdkPackage.java +45 -13
- package/ios/Classes/EasyMerchantSdk.m +106 -55
- package/ios/Classes/EasyMerchantSdk.swift +199 -77
- package/ios/Classes/EasyPayViewController.swift +1 -1
- package/ios/CustomComponents/DatePickerHandler.swift +15 -4
- package/ios/EnvironmentConfig.swift +32 -30
- package/ios/Models/Request.swift +176 -14
- package/ios/Models/Result.swift +12 -5
- package/ios/Pods/ViewControllers/AdditionalInfoVC.swift +855 -366
- package/ios/Pods/ViewControllers/BaseVC.swift +51 -36
- package/ios/Pods/ViewControllers/BillingInfoVC/BillingInfoVC.swift +1985 -178
- package/ios/Pods/ViewControllers/CountryListVC.swift +20 -1
- package/ios/Pods/ViewControllers/CustomOverlay.swift +199 -0
- package/ios/Pods/ViewControllers/EmailVerificationVC.swift +74 -5
- package/ios/Pods/ViewControllers/GrailPayVC.swift +131 -107
- package/ios/Pods/ViewControllers/OTPVerificationVC.swift +296 -106
- package/ios/Pods/ViewControllers/PaymentDoneVC.swift +35 -26
- package/ios/Pods/ViewControllers/PaymentInformation/PaymentInfoVC.swift +1276 -545
- package/ios/Pods/ViewControllers/ThreeDSecurePaymentDoneVC.swift +607 -24
- package/ios/easymerchantsdk.podspec +1 -1
- package/ios/easymerchantsdk.storyboard +1388 -1165
- package/package.json +1 -1
|
@@ -5,35 +5,398 @@
|
|
|
5
5
|
// Created by Mony's Mac on 20/05/25.
|
|
6
6
|
//
|
|
7
7
|
|
|
8
|
+
//import UIKit
|
|
9
|
+
//
|
|
10
|
+
//class ThreeDSecurePaymentDoneVC: UIViewController {
|
|
11
|
+
//
|
|
12
|
+
// @IBOutlet weak var imgViewPaymentDone: UIImageView!
|
|
13
|
+
// @IBOutlet weak var imgViewLoading: UIImageView!
|
|
14
|
+
// @IBOutlet weak var viewMain: UIView!
|
|
15
|
+
// @IBOutlet weak var lblCompleteAuthentication: UILabel!
|
|
16
|
+
// @IBOutlet weak var btnDone: UIButton!
|
|
17
|
+
// @IBOutlet weak var lblPaymentLink: UILabel!
|
|
18
|
+
// @IBOutlet weak var lblBillingInfoData: UILabel!
|
|
19
|
+
//
|
|
20
|
+
// var easyPayDelegate: EasyPayViewControllerDelegate?
|
|
21
|
+
// var redirectURL: String?
|
|
22
|
+
// var chargeData: [String: Any] = [:]
|
|
23
|
+
//
|
|
24
|
+
// // Add these two properties:
|
|
25
|
+
// var billingInfo: [String: Any]?
|
|
26
|
+
// var additionalInfo: [String: Any]?
|
|
27
|
+
//
|
|
28
|
+
// var threeDSecureStatusResponse: [String: Any]?
|
|
29
|
+
//
|
|
30
|
+
// var statusCheckTimer: Timer?
|
|
31
|
+
//
|
|
32
|
+
// var additionalInfoData: [FieldItem]?
|
|
33
|
+
// var billingInfoData: [FieldItem]?
|
|
34
|
+
// var visibility: FieldsVisibility?
|
|
35
|
+
//
|
|
36
|
+
// override func viewDidLoad() {
|
|
37
|
+
// super.viewDidLoad()
|
|
38
|
+
// uiFinishingTouchElements()
|
|
39
|
+
//
|
|
40
|
+
// setupTapOnLabel()
|
|
41
|
+
//
|
|
42
|
+
// // showBillingInfo()
|
|
43
|
+
//
|
|
44
|
+
// checkThreeDSecureStatus()
|
|
45
|
+
// startStatusCheckTimer()
|
|
46
|
+
// }
|
|
47
|
+
//
|
|
48
|
+
// override func viewWillAppear(_ animated: Bool) {
|
|
49
|
+
// uiFinishingTouchElements()
|
|
50
|
+
// startStatusCheckTimer()
|
|
51
|
+
// }
|
|
52
|
+
//
|
|
53
|
+
// override func viewWillDisappear(_ animated: Bool) {
|
|
54
|
+
// super.viewWillDisappear(animated)
|
|
55
|
+
// statusCheckTimer?.invalidate()
|
|
56
|
+
// statusCheckTimer = nil
|
|
57
|
+
// }
|
|
58
|
+
//
|
|
59
|
+
// func startRotatingImage() {
|
|
60
|
+
// let rotationAnimation = CABasicAnimation(keyPath: "transform.rotation")
|
|
61
|
+
// rotationAnimation.toValue = CGFloat.pi * 2 // 360 degrees in radians
|
|
62
|
+
// rotationAnimation.duration = 1 // Adjust the duration as needed
|
|
63
|
+
// rotationAnimation.isCumulative = true
|
|
64
|
+
// rotationAnimation.repeatCount = .infinity // Continuous rotation
|
|
65
|
+
// imgViewLoading.layer.add(rotationAnimation, forKey: "rotationAnimation")
|
|
66
|
+
// }
|
|
67
|
+
//
|
|
68
|
+
// private func setupTapOnLabel() {
|
|
69
|
+
// if let url = redirectURL {
|
|
70
|
+
// lblPaymentLink.text = url
|
|
71
|
+
// }
|
|
72
|
+
// lblPaymentLink.textColor = .systemBlue
|
|
73
|
+
// lblPaymentLink.isUserInteractionEnabled = true
|
|
74
|
+
//
|
|
75
|
+
// let tapGesture = UITapGestureRecognizer(target: self, action: #selector(linkTapped))
|
|
76
|
+
// lblPaymentLink.addGestureRecognizer(tapGesture)
|
|
77
|
+
// }
|
|
78
|
+
//
|
|
79
|
+
// @objc private func linkTapped() {
|
|
80
|
+
// guard let text = lblPaymentLink.text,
|
|
81
|
+
// let url = URL(string: text),
|
|
82
|
+
// UIApplication.shared.canOpenURL(url) else {
|
|
83
|
+
// return
|
|
84
|
+
// }
|
|
85
|
+
// UIApplication.shared.open(url, options: [:], completionHandler: nil)
|
|
86
|
+
// }
|
|
87
|
+
//
|
|
88
|
+
//// func showBillingInfo() {
|
|
89
|
+
//// var displayText = ""
|
|
90
|
+
////
|
|
91
|
+
//// if let visibility = visibility {
|
|
92
|
+
//// if visibility.billing, let billing = billingInfo {
|
|
93
|
+
//// displayText += "Billing Info:-\n"
|
|
94
|
+
//// for (key, value) in billing {
|
|
95
|
+
//// displayText += "\(key.capitalized): \(value)\n"
|
|
96
|
+
//// }
|
|
97
|
+
//// }
|
|
98
|
+
////
|
|
99
|
+
//// if visibility.additional, let additional = additionalInfo {
|
|
100
|
+
//// if !displayText.isEmpty {
|
|
101
|
+
//// displayText += "\n"
|
|
102
|
+
//// }
|
|
103
|
+
//// displayText += "Additional Info:-\n"
|
|
104
|
+
//// for (key, value) in additional {
|
|
105
|
+
//// displayText += "\(key.capitalized): \(value)\n"
|
|
106
|
+
//// }
|
|
107
|
+
//// }
|
|
108
|
+
//// }
|
|
109
|
+
////
|
|
110
|
+
//// if displayText.isEmpty {
|
|
111
|
+
//// lblBillingInfoData.isHidden = true
|
|
112
|
+
//// } else {
|
|
113
|
+
//// lblBillingInfoData.text = displayText.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
114
|
+
//// lblBillingInfoData.isHidden = false
|
|
115
|
+
//// }
|
|
116
|
+
//// }
|
|
117
|
+
//
|
|
118
|
+
// private func startStatusCheckTimer() {
|
|
119
|
+
// statusCheckTimer?.invalidate() // Invalidate any existing timer
|
|
120
|
+
// statusCheckTimer = Timer.scheduledTimer(withTimeInterval: 10.0, repeats: true) { [weak self] _ in
|
|
121
|
+
// self?.checkThreeDSecureStatus()
|
|
122
|
+
// }
|
|
123
|
+
// }
|
|
124
|
+
//
|
|
125
|
+
// @IBAction func actionBtnDone(_ sender: UIButton) {
|
|
126
|
+
// // ✅ Combine 3DS status into additionalInfo
|
|
127
|
+
// var combinedAdditionalInfo = additionalInfo ?? [:]
|
|
128
|
+
// if let threeDS = threeDSecureStatusResponse {
|
|
129
|
+
// combinedAdditionalInfo["threeDSecureStatus"] = threeDS
|
|
130
|
+
// }
|
|
131
|
+
//
|
|
132
|
+
// let result = Result(type: .success,
|
|
133
|
+
// chargeData: chargeData,
|
|
134
|
+
// billingInfo: billingInfo,
|
|
135
|
+
// additionalInfo: combinedAdditionalInfo)
|
|
136
|
+
//
|
|
137
|
+
// easyPayDelegate?.easyPayController(self.navigationController as! EasyPayViewController, didFinishWith: result)
|
|
138
|
+
//
|
|
139
|
+
// if let easyPayVC = self.navigationController as? EasyPayViewController {
|
|
140
|
+
// easyPayVC.dismiss(animated: true, completion: {
|
|
141
|
+
// if let delegate = easyPayVC.easyPayDelegate {
|
|
142
|
+
// UserStoreSingleton.shared.isLoggedIn = false
|
|
143
|
+
// delegate.easyPayController(easyPayVC, didFinishWith: result)
|
|
144
|
+
// }
|
|
145
|
+
// })
|
|
146
|
+
// }
|
|
147
|
+
// }
|
|
148
|
+
//
|
|
149
|
+
// func uiFinishingTouchElements() {
|
|
150
|
+
// // Set background color for the main view
|
|
151
|
+
// if let containerBGcolor = UserStoreSingleton.shared.container_bg_col,
|
|
152
|
+
// let uiColor = UIColor(hex: containerBGcolor) {
|
|
153
|
+
// self.view.backgroundColor = uiColor
|
|
154
|
+
// self.viewMain.backgroundColor = uiColor
|
|
155
|
+
// }
|
|
156
|
+
//
|
|
157
|
+
// if let primaryBtnBackGroundColor = UserStoreSingleton.shared.primary_btn_bg_col,
|
|
158
|
+
// let uiColor = UIColor(hex: primaryBtnBackGroundColor) {
|
|
159
|
+
// btnDone.backgroundColor = uiColor
|
|
160
|
+
// }
|
|
161
|
+
//
|
|
162
|
+
// if let primaryBtnFontColor = UserStoreSingleton.shared.primary_btn_font_col,
|
|
163
|
+
// let secondaryUIColor = UIColor(hex: primaryBtnFontColor) {
|
|
164
|
+
// btnDone.setTitleColor(secondaryUIColor, for: .normal)
|
|
165
|
+
// }
|
|
166
|
+
//
|
|
167
|
+
// if let borderRadiusString = UserStoreSingleton.shared.border_radious,
|
|
168
|
+
// let borderRadius = Double(borderRadiusString) { // Convert String to Double
|
|
169
|
+
// btnDone.layer.cornerRadius = CGFloat(borderRadius) // Set corner radius
|
|
170
|
+
// } else {
|
|
171
|
+
// btnDone.layer.cornerRadius = 8 // Default value
|
|
172
|
+
// }
|
|
173
|
+
// btnDone.layer.masksToBounds = true // Ensure the corners are clipped properly
|
|
174
|
+
//
|
|
175
|
+
// if let primaryFontColor = UserStoreSingleton.shared.primary_font_col,
|
|
176
|
+
// let uiColor = UIColor(hex: primaryFontColor) {
|
|
177
|
+
// lblCompleteAuthentication.textColor = uiColor
|
|
178
|
+
// lblBillingInfoData.textColor = uiColor
|
|
179
|
+
// }
|
|
180
|
+
//
|
|
181
|
+
// if let fontSizeString = UserStoreSingleton.shared.fontSize,
|
|
182
|
+
// let fontSizeDouble = Double(fontSizeString) { // Convert String to Double
|
|
183
|
+
// let fontSize = CGFloat(fontSizeDouble) // Convert Double to CGFloat
|
|
184
|
+
// lblCompleteAuthentication.font = UIFont.systemFont(ofSize: fontSize, weight: .semibold)
|
|
185
|
+
// lblPaymentLink.font = UIFont.systemFont(ofSize: fontSize, weight: .medium)
|
|
186
|
+
// lblBillingInfoData.font = UIFont.systemFont(ofSize: fontSize, weight: .medium)
|
|
187
|
+
// }
|
|
188
|
+
//
|
|
189
|
+
// }
|
|
190
|
+
//
|
|
191
|
+
// // MARK: - GET Transaction Status API
|
|
192
|
+
// private func checkThreeDSecureStatus() {
|
|
193
|
+
// guard let secureToken = chargeData["secure_token"] as? String else {
|
|
194
|
+
// print("Secure token not found in chargeData")
|
|
195
|
+
// return
|
|
196
|
+
// }
|
|
197
|
+
//
|
|
198
|
+
// let urlString = EnvironmentConfig.baseURL + EnvironmentConfig.Endpoints.threeDSecureStatus(secureToken).path()
|
|
199
|
+
// print("Final 3DS status URL: \(urlString)")
|
|
200
|
+
//
|
|
201
|
+
// guard let url = URL(string: urlString) else {
|
|
202
|
+
// print("Invalid URL")
|
|
203
|
+
// return
|
|
204
|
+
// }
|
|
205
|
+
//
|
|
206
|
+
// var uRLRequest = URLRequest(url: url)
|
|
207
|
+
// uRLRequest.httpMethod = "GET"
|
|
208
|
+
// uRLRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
|
|
209
|
+
//
|
|
210
|
+
// let token = UserStoreSingleton.shared.customerToken
|
|
211
|
+
// print("Setting customerToken header: \(token ?? "None")")
|
|
212
|
+
// uRLRequest.addValue(token ?? "", forHTTPHeaderField: "Customer-Token")
|
|
213
|
+
//
|
|
214
|
+
// // Add API key/secret headers
|
|
215
|
+
// if let apiKey = EnvironmentConfig.apiKey,
|
|
216
|
+
// let apiSecret = EnvironmentConfig.apiSecret {
|
|
217
|
+
// uRLRequest.addValue(apiKey, forHTTPHeaderField: "x-api-key")
|
|
218
|
+
// uRLRequest.addValue(apiSecret, forHTTPHeaderField: "x-api-secret")
|
|
219
|
+
// }
|
|
220
|
+
//
|
|
221
|
+
// let task = URLSession.shared.dataTask(with: uRLRequest) { [weak self] data, response, error in
|
|
222
|
+
// guard let self = self else { return }
|
|
223
|
+
//
|
|
224
|
+
// if let error = error {
|
|
225
|
+
// print("3DS status check error:", error.localizedDescription)
|
|
226
|
+
// return
|
|
227
|
+
// }
|
|
228
|
+
//
|
|
229
|
+
// guard let data = data else {
|
|
230
|
+
// print("No data in response")
|
|
231
|
+
// return
|
|
232
|
+
// }
|
|
233
|
+
//
|
|
234
|
+
// do {
|
|
235
|
+
// if let json = try JSONSerialization.jsonObject(with: data) as? [String: Any] {
|
|
236
|
+
// print("3DS status response:", json)
|
|
237
|
+
// self.threeDSecureStatusResponse = json
|
|
238
|
+
// }
|
|
239
|
+
// } catch {
|
|
240
|
+
// print("Error parsing JSON:", error.localizedDescription)
|
|
241
|
+
// }
|
|
242
|
+
// }
|
|
243
|
+
//
|
|
244
|
+
// task.resume()
|
|
245
|
+
// }
|
|
246
|
+
//
|
|
247
|
+
//}
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
|
|
8
256
|
import UIKit
|
|
9
257
|
|
|
10
|
-
class ThreeDSecurePaymentDoneVC:
|
|
258
|
+
class ThreeDSecurePaymentDoneVC: BaseVC {
|
|
11
259
|
|
|
260
|
+
@IBOutlet weak var imgViewPaymentDone: UIImageView!
|
|
261
|
+
@IBOutlet weak var imgViewLoading: UIImageView!
|
|
12
262
|
@IBOutlet weak var viewMain: UIView!
|
|
13
263
|
@IBOutlet weak var lblCompleteAuthentication: UILabel!
|
|
14
264
|
@IBOutlet weak var btnDone: UIButton!
|
|
15
265
|
@IBOutlet weak var lblPaymentLink: UILabel!
|
|
16
266
|
@IBOutlet weak var lblBillingInfoData: UILabel!
|
|
17
267
|
|
|
268
|
+
@IBOutlet weak var viewPaymentDetails: UIStackView!
|
|
269
|
+
@IBOutlet weak var lblDateHeading: UILabel!
|
|
270
|
+
@IBOutlet weak var lblTransactionHeading: UILabel!
|
|
271
|
+
@IBOutlet weak var lblSubscriptionHeading: UILabel!
|
|
272
|
+
@IBOutlet weak var lblChargeIdHeading: UILabel!
|
|
273
|
+
@IBOutlet weak var lblReferenceIdHeading: UILabel!
|
|
274
|
+
@IBOutlet weak var lblPaymentMethodHeading: UILabel!
|
|
275
|
+
@IBOutlet weak var lblTotalHeading: UILabel!
|
|
276
|
+
@IBOutlet weak var lblStatusHeading: UILabel!
|
|
277
|
+
|
|
278
|
+
@IBOutlet weak var lblDate: UILabel!
|
|
279
|
+
@IBOutlet weak var lblTransactionId: UILabel!
|
|
280
|
+
@IBOutlet weak var lblSubscriptionId: UILabel!
|
|
281
|
+
@IBOutlet weak var lblChargeId: UILabel!
|
|
282
|
+
@IBOutlet weak var lblTotal: UILabel!
|
|
283
|
+
@IBOutlet weak var lblRefferenceId: UILabel!
|
|
284
|
+
@IBOutlet weak var lblPaymentMethodValue: UILabel!
|
|
285
|
+
@IBOutlet weak var lblStatus: UILabel!
|
|
286
|
+
|
|
18
287
|
var easyPayDelegate: EasyPayViewControllerDelegate?
|
|
19
288
|
var redirectURL: String?
|
|
20
289
|
var chargeData: [String: Any] = [:]
|
|
21
290
|
|
|
22
|
-
// Add these two properties:
|
|
23
291
|
var billingInfo: [String: Any]?
|
|
24
292
|
var additionalInfo: [String: Any]?
|
|
25
293
|
|
|
294
|
+
var threeDSecureStatusResponse: [String: Any]?
|
|
295
|
+
|
|
296
|
+
// Rename for clarity, this will be for the periodic API check
|
|
297
|
+
var apiStatusCheckTimer: Timer?
|
|
298
|
+
// New property for the 1-minute countdown
|
|
299
|
+
var oneMinuteCountdownTimer: DispatchSourceTimer?
|
|
300
|
+
var countdownRemaining: Int = 60 // 60 seconds
|
|
301
|
+
|
|
302
|
+
var additionalInfoData: [FieldItem]?
|
|
303
|
+
var billingInfoData: [FieldItem]?
|
|
304
|
+
var visibility: FieldsVisibility?
|
|
305
|
+
|
|
306
|
+
// Dispatch group to wait for initial API call
|
|
307
|
+
let initialAPIGroup = DispatchGroup()
|
|
308
|
+
|
|
309
|
+
var amount: Int?
|
|
310
|
+
|
|
26
311
|
override func viewDidLoad() {
|
|
27
312
|
super.viewDidLoad()
|
|
28
313
|
uiFinishingTouchElements()
|
|
29
314
|
|
|
30
315
|
setupTapOnLabel()
|
|
31
316
|
|
|
32
|
-
|
|
317
|
+
// Initially hide done image and show loading image
|
|
318
|
+
imgViewPaymentDone.isHidden = true
|
|
319
|
+
imgViewLoading.isHidden = false
|
|
320
|
+
lblCompleteAuthentication.text = "Completing Authentication..." // Initial text
|
|
321
|
+
btnDone.isHidden = true
|
|
322
|
+
|
|
323
|
+
startRotatingImage()
|
|
324
|
+
startOneMinuteCountdownAndAPICheck()
|
|
325
|
+
|
|
326
|
+
NotificationCenter.default.addObserver(self, selector: #selector(appDidBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil)
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
deinit {
|
|
330
|
+
NotificationCenter.default.removeObserver(self)
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
@objc private func appDidBecomeActive() {
|
|
334
|
+
if !imgViewLoading.isHidden && imgViewLoading.layer.animation(forKey: "rotationAnimation") == nil {
|
|
335
|
+
startRotatingImage()
|
|
336
|
+
}
|
|
33
337
|
}
|
|
34
338
|
|
|
35
339
|
override func viewWillAppear(_ animated: Bool) {
|
|
340
|
+
super.viewWillAppear(animated)
|
|
36
341
|
uiFinishingTouchElements()
|
|
342
|
+
|
|
343
|
+
// Restart rotating animation if missing
|
|
344
|
+
if !imgViewLoading.isHidden && imgViewLoading.layer.animation(forKey: "rotationAnimation") == nil {
|
|
345
|
+
startRotatingImage()
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
if let chargeId = (threeDSecureStatusResponse?["data"] as? [String: Any])?["charge_id"] as? String,
|
|
349
|
+
!chargeId.isEmpty {
|
|
350
|
+
// Charge already found - do nothing
|
|
351
|
+
return
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
if countdownRemaining > 0 {
|
|
355
|
+
imgViewLoading.isHidden = false
|
|
356
|
+
imgViewPaymentDone.isHidden = true
|
|
357
|
+
lblCompleteAuthentication.text = "Please wait while Authentication is in process..."
|
|
358
|
+
btnDone.isHidden = true
|
|
359
|
+
|
|
360
|
+
if apiStatusCheckTimer == nil {
|
|
361
|
+
apiStatusCheckTimer = Timer.scheduledTimer(withTimeInterval: 10.0, repeats: true) { [weak self] _ in
|
|
362
|
+
guard let self = self else { return }
|
|
363
|
+
if self.countdownRemaining > 0 {
|
|
364
|
+
self.checkThreeDSecureStatus(completion: nil)
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
} else {
|
|
370
|
+
imgViewLoading.layer.removeAllAnimations()
|
|
371
|
+
imgViewLoading.isHidden = true
|
|
372
|
+
imgViewPaymentDone.isHidden = false
|
|
373
|
+
imgViewPaymentDone.image = UIImage(systemName: "exclamationmark.circle.fill")
|
|
374
|
+
imgViewPaymentDone.tintColor = .systemRed
|
|
375
|
+
lblCompleteAuthentication.text = "Please complete 3DS Authentication.!!"
|
|
376
|
+
btnDone.isHidden = false
|
|
377
|
+
lblPaymentLink.isHidden = false
|
|
378
|
+
viewPaymentDetails.isHidden = false
|
|
379
|
+
|
|
380
|
+
apiStatusCheckTimer?.invalidate()
|
|
381
|
+
apiStatusCheckTimer = nil
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
override func viewWillDisappear(_ animated: Bool) {
|
|
386
|
+
super.viewWillDisappear(animated)
|
|
387
|
+
apiStatusCheckTimer?.invalidate()
|
|
388
|
+
apiStatusCheckTimer = nil
|
|
389
|
+
oneMinuteCountdownTimer?.cancel() // Cancel the dispatch source timer
|
|
390
|
+
oneMinuteCountdownTimer = nil
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
func startRotatingImage() {
|
|
394
|
+
let rotationAnimation = CABasicAnimation(keyPath: "transform.rotation")
|
|
395
|
+
rotationAnimation.toValue = CGFloat.pi * 2 // 360 degrees in radians
|
|
396
|
+
rotationAnimation.duration = 1 // Adjust the duration as needed
|
|
397
|
+
rotationAnimation.isCumulative = true
|
|
398
|
+
rotationAnimation.repeatCount = .infinity // Continuous rotation
|
|
399
|
+
imgViewLoading.layer.add(rotationAnimation, forKey: "rotationAnimation")
|
|
37
400
|
}
|
|
38
401
|
|
|
39
402
|
private func setupTapOnLabel() {
|
|
@@ -55,37 +418,96 @@ class ThreeDSecurePaymentDoneVC: UIViewController {
|
|
|
55
418
|
}
|
|
56
419
|
UIApplication.shared.open(url, options: [:], completionHandler: nil)
|
|
57
420
|
}
|
|
58
|
-
|
|
59
|
-
func showBillingInfo() {
|
|
60
|
-
var displayText = ""
|
|
61
421
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
422
|
+
private func startOneMinuteCountdownAndAPICheck() {
|
|
423
|
+
startRotatingImage()
|
|
424
|
+
imgViewPaymentDone.isHidden = true
|
|
425
|
+
imgViewLoading.isHidden = false
|
|
426
|
+
lblCompleteAuthentication.text = "Please wait while Authentication is in process..."
|
|
427
|
+
btnDone.isHidden = true
|
|
428
|
+
|
|
429
|
+
apiStatusCheckTimer?.invalidate()
|
|
430
|
+
apiStatusCheckTimer = nil
|
|
431
|
+
|
|
432
|
+
initialAPIGroup.enter()
|
|
433
|
+
checkThreeDSecureStatus { [weak self] in
|
|
434
|
+
self?.initialAPIGroup.leave()
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
countdownRemaining = 60
|
|
438
|
+
|
|
439
|
+
oneMinuteCountdownTimer = DispatchSource.makeTimerSource(queue: .main)
|
|
440
|
+
oneMinuteCountdownTimer?.schedule(deadline: .now(), repeating: .seconds(1))
|
|
441
|
+
oneMinuteCountdownTimer?.setEventHandler { [weak self] in
|
|
442
|
+
guard let self = self else { return }
|
|
443
|
+
|
|
444
|
+
self.countdownRemaining -= 1
|
|
445
|
+
if self.countdownRemaining <= 0 {
|
|
446
|
+
self.oneMinuteCountdownTimer?.cancel()
|
|
447
|
+
self.oneMinuteCountdownTimer = nil
|
|
448
|
+
|
|
449
|
+
DispatchQueue.main.async {
|
|
450
|
+
self.imgViewLoading.layer.removeAllAnimations()
|
|
451
|
+
self.imgViewLoading.isHidden = true
|
|
452
|
+
self.imgViewPaymentDone.isHidden = false
|
|
453
|
+
self.lblCompleteAuthentication.text = "Please complete 3DS Authentication.!!"
|
|
454
|
+
self.btnDone.isHidden = false
|
|
455
|
+
self.lblPaymentLink.isHidden = false
|
|
456
|
+
self.viewPaymentDetails.isHidden = false
|
|
457
|
+
|
|
458
|
+
if let json = self.threeDSecureStatusResponse,
|
|
459
|
+
let data = json["data"] as? [String: Any],
|
|
460
|
+
let chargeId = data["charge_id"],
|
|
461
|
+
chargeId is NSNull || (chargeId as? String ?? "").isEmpty {
|
|
462
|
+
self.imgViewPaymentDone.image = UIImage(systemName: "exclamationmark.circle.fill")
|
|
463
|
+
self.imgViewPaymentDone.tintColor = .systemRed
|
|
464
|
+
|
|
465
|
+
let refToken = data["ref_token"] as? String ?? "N/A"
|
|
466
|
+
let chargeId = data["charge_id"] as? String ?? "N/A"
|
|
467
|
+
let transactionId = data["transaction_id"] as? String ?? "N/A"
|
|
468
|
+
let subscriptionId = data["subscription_id"] as? String ?? "N/A"
|
|
469
|
+
let createdAt = data["created_at"] as? String ?? ""
|
|
470
|
+
let status = data["status"] as? String ?? ""
|
|
471
|
+
|
|
472
|
+
let formattedDate: String
|
|
473
|
+
if let date = self.convertToDate(dateString: createdAt) {
|
|
474
|
+
formattedDate = self.formatDate(date: date)
|
|
475
|
+
} else {
|
|
476
|
+
formattedDate = "N/A"
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
self.lblChargeId.text = "\(chargeId)"
|
|
480
|
+
self.lblTransactionId.text = "\(transactionId)"
|
|
481
|
+
self.lblSubscriptionId.text = "\(subscriptionId)"
|
|
482
|
+
self.lblDate.text = "\(formattedDate)"
|
|
483
|
+
self.lblTotal.text = "$\(self.amount ?? 0)"
|
|
484
|
+
self.lblRefferenceId.text = "\(refToken)"
|
|
485
|
+
self.lblStatus.text = "\(status)"
|
|
486
|
+
}
|
|
72
487
|
}
|
|
73
488
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
489
|
+
}
|
|
490
|
+
oneMinuteCountdownTimer?.resume()
|
|
491
|
+
|
|
492
|
+
// ✅ API check timer: runs continuously every 5 seconds until success/failure
|
|
493
|
+
apiStatusCheckTimer = Timer.scheduledTimer(withTimeInterval: 5.0, repeats: true) { [weak self] _ in
|
|
494
|
+
guard let self = self else { return }
|
|
495
|
+
self.checkThreeDSecureStatus(completion: nil)
|
|
81
496
|
}
|
|
82
497
|
}
|
|
498
|
+
|
|
83
499
|
|
|
84
500
|
@IBAction func actionBtnDone(_ sender: UIButton) {
|
|
501
|
+
// ✅ Combine 3DS status into additionalInfo
|
|
502
|
+
var combinedAdditionalInfo = additionalInfo ?? [:]
|
|
503
|
+
if let threeDS = threeDSecureStatusResponse {
|
|
504
|
+
combinedAdditionalInfo["threeDSecureStatus"] = threeDS
|
|
505
|
+
}
|
|
506
|
+
|
|
85
507
|
let result = Result(type: .success,
|
|
86
508
|
chargeData: chargeData,
|
|
87
509
|
billingInfo: billingInfo,
|
|
88
|
-
additionalInfo:
|
|
510
|
+
additionalInfo: combinedAdditionalInfo)
|
|
89
511
|
|
|
90
512
|
easyPayDelegate?.easyPayController(self.navigationController as! EasyPayViewController, didFinishWith: result)
|
|
91
513
|
|
|
@@ -105,11 +527,14 @@ class ThreeDSecurePaymentDoneVC: UIViewController {
|
|
|
105
527
|
let uiColor = UIColor(hex: containerBGcolor) {
|
|
106
528
|
self.view.backgroundColor = uiColor
|
|
107
529
|
self.viewMain.backgroundColor = uiColor
|
|
530
|
+
// self.viewOverlay.backgroundColor = uiColor.withAlphaComponent(0.3)
|
|
108
531
|
}
|
|
109
532
|
|
|
110
533
|
if let primaryBtnBackGroundColor = UserStoreSingleton.shared.primary_btn_bg_col,
|
|
111
534
|
let uiColor = UIColor(hex: primaryBtnBackGroundColor) {
|
|
112
535
|
btnDone.backgroundColor = uiColor
|
|
536
|
+
imgViewLoading.image = UIImage(systemName: "arrow.2.circlepath")?.withRenderingMode(.alwaysTemplate)
|
|
537
|
+
imgViewLoading.tintColor = uiColor
|
|
113
538
|
}
|
|
114
539
|
|
|
115
540
|
if let primaryBtnFontColor = UserStoreSingleton.shared.primary_btn_font_col,
|
|
@@ -117,6 +542,26 @@ class ThreeDSecurePaymentDoneVC: UIViewController {
|
|
|
117
542
|
btnDone.setTitleColor(secondaryUIColor, for: .normal)
|
|
118
543
|
}
|
|
119
544
|
|
|
545
|
+
if let primaryFontColor = UserStoreSingleton.shared.primary_font_col,
|
|
546
|
+
let uiColor = UIColor(hex: primaryFontColor) {
|
|
547
|
+
lblDateHeading.textColor = uiColor
|
|
548
|
+
lblTransactionHeading.textColor = uiColor
|
|
549
|
+
lblSubscriptionHeading.textColor = uiColor
|
|
550
|
+
lblChargeIdHeading.textColor = uiColor
|
|
551
|
+
lblReferenceIdHeading.textColor = uiColor
|
|
552
|
+
lblPaymentMethodHeading.textColor = uiColor
|
|
553
|
+
lblTotalHeading.textColor = uiColor
|
|
554
|
+
lblDate.textColor = uiColor
|
|
555
|
+
lblTransactionId.textColor = uiColor
|
|
556
|
+
lblSubscriptionId.textColor = uiColor
|
|
557
|
+
lblChargeId.textColor = uiColor
|
|
558
|
+
lblTotal.textColor = uiColor
|
|
559
|
+
lblRefferenceId.textColor = uiColor
|
|
560
|
+
lblPaymentMethodValue.textColor = uiColor
|
|
561
|
+
lblStatusHeading.textColor = uiColor
|
|
562
|
+
lblStatus.textColor = uiColor
|
|
563
|
+
}
|
|
564
|
+
|
|
120
565
|
if let borderRadiusString = UserStoreSingleton.shared.border_radious,
|
|
121
566
|
let borderRadius = Double(borderRadiusString) { // Convert String to Double
|
|
122
567
|
btnDone.layer.cornerRadius = CGFloat(borderRadius) // Set corner radius
|
|
@@ -141,4 +586,142 @@ class ThreeDSecurePaymentDoneVC: UIViewController {
|
|
|
141
586
|
|
|
142
587
|
}
|
|
143
588
|
|
|
589
|
+
private func convertToDate(dateString: String) -> Date? {
|
|
590
|
+
let formatter = DateFormatter()
|
|
591
|
+
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
|
|
592
|
+
formatter.timeZone = TimeZone(abbreviation: "UTC")
|
|
593
|
+
return formatter.date(from: dateString)
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
private func formatDate(date: Date) -> String {
|
|
597
|
+
let formatter = DateFormatter()
|
|
598
|
+
formatter.dateFormat = "dd/MM/yyyy, HH:mm:ss"
|
|
599
|
+
formatter.timeZone = TimeZone.current
|
|
600
|
+
return formatter.string(from: date)
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
// MARK: - GET Transaction Status API
|
|
604
|
+
private func checkThreeDSecureStatus(completion: (() -> Void)?) {
|
|
605
|
+
guard let secureToken = chargeData["secure_token"] as? String else {
|
|
606
|
+
print("Secure token not found in chargeData")
|
|
607
|
+
completion?()
|
|
608
|
+
return
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
let urlString = EnvironmentConfig.baseURL + EnvironmentConfig.Endpoints.threeDSecureStatus(secureToken).path()
|
|
612
|
+
print("Final 3DS status URL: \(urlString)")
|
|
613
|
+
|
|
614
|
+
guard let url = URL(string: urlString) else {
|
|
615
|
+
print("Invalid URL")
|
|
616
|
+
completion?()
|
|
617
|
+
return
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
var uRLRequest = URLRequest(url: url)
|
|
621
|
+
uRLRequest.httpMethod = "GET"
|
|
622
|
+
uRLRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
|
|
623
|
+
|
|
624
|
+
if let token = UserStoreSingleton.shared.customerToken {
|
|
625
|
+
uRLRequest.addValue(token, forHTTPHeaderField: "Customer-Token")
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
if let apiKey = EnvironmentConfig.apiKey,
|
|
629
|
+
let apiSecret = EnvironmentConfig.apiSecret {
|
|
630
|
+
uRLRequest.addValue(apiKey, forHTTPHeaderField: "x-api-key")
|
|
631
|
+
uRLRequest.addValue(apiSecret, forHTTPHeaderField: "x-api-secret")
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
let task = URLSession.shared.dataTask(with: uRLRequest) { [weak self] data, response, error in
|
|
635
|
+
defer { completion?() }
|
|
636
|
+
|
|
637
|
+
guard let self = self else { return }
|
|
638
|
+
|
|
639
|
+
if let error = error {
|
|
640
|
+
print("3DS status check error:", error.localizedDescription)
|
|
641
|
+
return
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
guard let data = data else {
|
|
645
|
+
print("No data in response")
|
|
646
|
+
return
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
do {
|
|
650
|
+
if let json = try JSONSerialization.jsonObject(with: data) as? [String: Any] {
|
|
651
|
+
print("3DS status response:", json)
|
|
652
|
+
self.threeDSecureStatusResponse = json
|
|
653
|
+
|
|
654
|
+
if let dataDict = json["data"] as? [String: Any] {
|
|
655
|
+
DispatchQueue.main.async {
|
|
656
|
+
let chargeId = dataDict["charge_id"] as? String ?? "N/A"
|
|
657
|
+
let transactionId = dataDict["transaction_id"] as? String ?? "N/A"
|
|
658
|
+
let subscriptionId = dataDict["subscription_id"] as? String ?? "N/A"
|
|
659
|
+
let createdAt = dataDict["created_at"] as? String ?? ""
|
|
660
|
+
let referenceId = dataDict["ref_token"] as? String ?? "N/A"
|
|
661
|
+
let status = dataDict["status"] as? String ?? "N/A"
|
|
662
|
+
|
|
663
|
+
let formattedDate: String
|
|
664
|
+
if let date = self.convertToDate(dateString: createdAt) {
|
|
665
|
+
formattedDate = self.formatDate(date: date)
|
|
666
|
+
} else {
|
|
667
|
+
formattedDate = "N/A"
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
self.lblChargeId.text = chargeId
|
|
671
|
+
self.lblTransactionId.text = transactionId
|
|
672
|
+
self.lblSubscriptionId.text = subscriptionId
|
|
673
|
+
self.lblDate.text = formattedDate
|
|
674
|
+
self.lblTotal.text = "$\(self.amount ?? 0)"
|
|
675
|
+
self.lblRefferenceId.text = referenceId
|
|
676
|
+
self.lblStatus.text = status
|
|
677
|
+
|
|
678
|
+
if status.lowercased() == "failed" {
|
|
679
|
+
// Handle failed status
|
|
680
|
+
self.imgViewPaymentDone.image = UIImage(systemName: "xmark.circle.fill")
|
|
681
|
+
self.imgViewPaymentDone.tintColor = .systemRed
|
|
682
|
+
self.apiStatusCheckTimer?.invalidate()
|
|
683
|
+
self.apiStatusCheckTimer = nil
|
|
684
|
+
self.oneMinuteCountdownTimer?.cancel()
|
|
685
|
+
self.oneMinuteCountdownTimer = nil
|
|
686
|
+
|
|
687
|
+
self.imgViewLoading.layer.removeAllAnimations()
|
|
688
|
+
self.imgViewLoading.isHidden = true
|
|
689
|
+
self.imgViewPaymentDone.isHidden = false
|
|
690
|
+
self.lblCompleteAuthentication.text = "Payment Failed"
|
|
691
|
+
self.btnDone.isHidden = false
|
|
692
|
+
self.lblPaymentLink.isHidden = false
|
|
693
|
+
self.viewPaymentDetails.isHidden = false
|
|
694
|
+
|
|
695
|
+
} else if !(chargeId.isEmpty || chargeId == "N/A") {
|
|
696
|
+
// Success case
|
|
697
|
+
self.imgViewPaymentDone.image = UIImage(named: "payment_done_icon")
|
|
698
|
+
self.apiStatusCheckTimer?.invalidate()
|
|
699
|
+
self.apiStatusCheckTimer = nil
|
|
700
|
+
self.oneMinuteCountdownTimer?.cancel()
|
|
701
|
+
self.oneMinuteCountdownTimer = nil
|
|
702
|
+
|
|
703
|
+
self.imgViewLoading.layer.removeAllAnimations()
|
|
704
|
+
self.imgViewLoading.isHidden = true
|
|
705
|
+
self.imgViewPaymentDone.isHidden = false
|
|
706
|
+
self.lblCompleteAuthentication.text = "Authentication Completed"
|
|
707
|
+
self.btnDone.isHidden = false
|
|
708
|
+
self.lblPaymentLink.isHidden = false
|
|
709
|
+
self.viewPaymentDetails.isHidden = false
|
|
710
|
+
|
|
711
|
+
} else {
|
|
712
|
+
// Still waiting
|
|
713
|
+
self.imgViewPaymentDone.image = UIImage(systemName: "exclamationmark.circle.fill")
|
|
714
|
+
self.imgViewPaymentDone.tintColor = .systemRed
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
} catch {
|
|
720
|
+
print("Error parsing JSON:", error.localizedDescription)
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
task.resume()
|
|
724
|
+
}
|
|
725
|
+
|
|
144
726
|
}
|
|
727
|
+
|