@jimrising/easymerchantsdk-react-native 2.5.2 → 2.5.3

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.
@@ -96,7 +96,7 @@ dependencies {
96
96
  implementation 'com.google.android.material:material:1.13.0'
97
97
 
98
98
  // Third-party libs
99
- implementation 'com.app:paysdk:1.6.6.3'
99
+ implementation 'com.app:paysdk:1.7.0'
100
100
  implementation 'com.hbb20:ccp:2.7.3'
101
101
  implementation 'com.github.bumptech.glide:glide:5.0.4'
102
102
  implementation 'com.github.androidmads:QRGenerator:1.0.5'
@@ -22,12 +22,6 @@ struct APIHeaders {
22
22
  return ["Customer-Token": token]
23
23
  }
24
24
 
25
- /// For verify_otp only: match Android — header "Customer-Token" (Pascal case), no Client-Token, no X-Api-Key/Secret
26
- static func verifyOtpHeaders() -> [String: String] {
27
- guard let token = UserStoreSingleton.shared.customerToken else { return [:] }
28
- return ["Customer-Token": token]
29
- }
30
-
31
25
  /// API key/secret headers (match Android SDK: X-Api-Key, X-Api-Secret)
32
26
  static func apiAuthHeaders() -> [String: String] {
33
27
  guard let key = EnvironmentConfig.apiKey,
@@ -29,14 +29,9 @@ struct APIRequest {
29
29
 
30
30
  // Combine default headers with passed-in headers
31
31
  var allHeaders = APIHeaders.commonHeaders()
32
- if endpoint == .verifyOtp {
33
- // verify_otp: match Android — only Customer-Token + Content-Type (no Client-Token, no X-Api-Key/Secret)
34
- allHeaders.merge(APIHeaders.verifyOtpHeaders(), uniquingKeysWith: { $1 })
35
- } else {
36
- allHeaders.merge(APIHeaders.clientTokenHeader(), uniquingKeysWith: { $1 })
37
- allHeaders.merge(APIHeaders.customerTokenHeader(), uniquingKeysWith: { $1 })
38
- allHeaders.merge(APIHeaders.apiAuthHeaders(), uniquingKeysWith: { $1 })
39
- }
32
+ allHeaders.merge(APIHeaders.clientTokenHeader(), uniquingKeysWith: { $1 })
33
+ allHeaders.merge(APIHeaders.customerTokenHeader(), uniquingKeysWith: { $1 })
34
+ allHeaders.merge(APIHeaders.apiAuthHeaders(), uniquingKeysWith: { $1 })
40
35
  allHeaders.merge(headers, uniquingKeysWith: { $1 }) // override if needed
41
36
 
42
37
  // Apply to request
@@ -2,8 +2,8 @@
2
2
  #import <React/RCTLog.h>
3
3
  #import <React/RCTBridgeModule.h>
4
4
 
5
- #import "easymerchantsdk-Swift.h"
6
- //#import <easymerchantsdk/easymerchantsdk-Swift.h>
5
+ //#import "easymerchantsdk-Swift.h"
6
+ #import <easymerchantsdk/easymerchantsdk-Swift.h>
7
7
 
8
8
 
9
9
  @interface EasyMerchantSdk ()
@@ -84,8 +84,8 @@ public class EasyMerchantSdkPlugin: NSObject, RCTBridgeModule {
84
84
  return
85
85
  }
86
86
 
87
- guard let presentingVC = viewController ?? getTopViewController() else {
88
- reject("NO_VIEW_CONTROLLER", "Unable to find a valid view controller", nil)
87
+ guard let presentingVC = presentingViewControllerInWindowHierarchy() else {
88
+ reject("NO_VIEW_CONTROLLER", "Unable to find a view controller in the window hierarchy", nil)
89
89
  clearCallbacks()
90
90
  return
91
91
  }
@@ -117,8 +117,8 @@ public class EasyMerchantSdkPlugin: NSObject, RCTBridgeModule {
117
117
  return
118
118
  }
119
119
 
120
- guard let presentingVC = viewController ?? getTopViewController() else {
121
- reject("NO_VIEW_CONTROLLER", "Unable to find a valid view controller", nil)
120
+ guard let presentingVC = presentingViewControllerInWindowHierarchy() else {
121
+ reject("NO_VIEW_CONTROLLER", "Unable to find a view controller in the window hierarchy", nil)
122
122
  clearCallbacks()
123
123
  return
124
124
  }
@@ -145,16 +145,28 @@ public class EasyMerchantSdkPlugin: NSObject, RCTBridgeModule {
145
145
 
146
146
  // MARK: - Helpers
147
147
 
148
- private func getTopViewController() -> UIViewController? {
149
- guard let windowScene = UIApplication.shared.connectedScenes
150
- .filter({ $0.activationState == .foregroundActive })
151
- .first as? UIWindowScene,
152
- let rootVC = windowScene.windows
153
- .filter({ $0.isKeyWindow })
154
- .first?.rootViewController else {
155
- return nil
148
+ private func keyWindowRootViewController() -> UIViewController? {
149
+ if let windowScene = UIApplication.shared.connectedScenes
150
+ .first(where: { ($0 as? UIWindowScene)?.activationState == .foregroundActive }) as? UIWindowScene,
151
+ let keyWindow = windowScene.windows.first(where: { $0.isKeyWindow }),
152
+ let root = keyWindow.rootViewController {
153
+ return root
156
154
  }
157
-
155
+ return UIApplication.shared.windows.first(where: { $0.isKeyWindow })?.rootViewController
156
+ }
157
+
158
+ /// Present from the last VC in the chain whose view is in the window. RCTFabricModalHostViewController
159
+ /// is often on top but its view is not in the window hierarchy; presenting from it crashes.
160
+ private func presentingViewControllerInWindowHierarchy() -> UIViewController? {
161
+ guard var vc = keyWindowRootViewController() else { return nil }
162
+ while let presented = vc.presentedViewController, presented.viewIfLoaded?.window != nil {
163
+ vc = presented
164
+ }
165
+ return vc.viewIfLoaded?.window != nil ? vc : nil
166
+ }
167
+
168
+ private func getTopViewController() -> UIViewController? {
169
+ guard let rootVC = keyWindowRootViewController() else { return nil }
158
170
  var topVC = rootVC
159
171
  while let presentedVC = topVC.presentedViewController {
160
172
  topVC = presentedVC
@@ -263,6 +263,7 @@ import UIKit
263
263
  storedCompletionHandler?(result)
264
264
 
265
265
  default:
266
+ break
266
267
  }
267
268
  }
268
269
  }
@@ -939,11 +939,11 @@ public final class Request: NSObject {
939
939
  let token = clientToken ?? UserStoreSingleton.shared.clientToken ?? ""
940
940
  uRLRequest.addValue(token, forHTTPHeaderField: "clientToken")
941
941
 
942
- // Add API key/secret headers
942
+ // Add API key/secret headers (match Android SDK: X-Api-Key, X-Api-Secret)
943
943
  if let apiKey = EnvironmentConfig.apiKey,
944
944
  let apiSecret = EnvironmentConfig.apiSecret {
945
- uRLRequest.addValue(apiKey, forHTTPHeaderField: "x-api-key")
946
- uRLRequest.addValue(apiSecret, forHTTPHeaderField: "x-api-secret")
945
+ uRLRequest.addValue(apiKey, forHTTPHeaderField: "X-Api-Key")
946
+ uRLRequest.addValue(apiSecret, forHTTPHeaderField: "X-Api-Secret")
947
947
  }
948
948
 
949
949
  let task = URLSession.shared.dataTask(with: uRLRequest) { data, response, error in