@jimrising/easymerchantsdk-react-native 2.3.9 → 2.4.0

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 (69) hide show
  1. package/README.md +112 -41
  2. package/android/build/generated/source/buildConfig/debug/com/reactlibrary/BuildConfig.java +10 -0
  3. package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +7 -0
  4. package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json +18 -0
  5. package/android/build/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties +6 -0
  6. package/android/build/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json +1 -0
  7. package/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
  8. package/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar +0 -0
  9. package/android/build/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt +0 -0
  10. package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +1 -0
  11. package/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml +2 -0
  12. package/android/build/intermediates/incremental/mergeDebugAssets/merger.xml +2 -0
  13. package/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +2 -0
  14. package/android/build/intermediates/incremental/mergeDebugShaders/merger.xml +2 -0
  15. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/BuildConfig.class +0 -0
  16. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule$1$1.class +0 -0
  17. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule$1.class +0 -0
  18. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule$2.class +0 -0
  19. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule$3.class +0 -0
  20. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule.class +0 -0
  21. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkPackage.class +0 -0
  22. package/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt +2 -0
  23. package/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +7 -0
  24. package/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +7 -0
  25. package/android/build/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json +1 -0
  26. package/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt +1 -0
  27. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/BuildConfig.class +0 -0
  28. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/RNEasymerchantsdkModule$1$1.class +0 -0
  29. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/RNEasymerchantsdkModule$1.class +0 -0
  30. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/RNEasymerchantsdkModule$2.class +0 -0
  31. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/RNEasymerchantsdkModule$3.class +0 -0
  32. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/RNEasymerchantsdkModule.class +0 -0
  33. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/RNEasymerchantsdkPackage.class +0 -0
  34. package/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
  35. package/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt +1 -0
  36. package/android/build/outputs/logs/manifest-merger-debug-report.txt +16 -0
  37. package/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
  38. package/android/build.gradle +3 -2
  39. package/ios/Classes/EasyMerchantSdk.h +4 -0
  40. package/ios/Classes/EasyMerchantSdk.m +6 -0
  41. package/ios/Classes/EasyMerchantSdk.swift +14 -0
  42. package/ios/Helper/GrailPayHelper.swift +166 -5
  43. package/ios/Pods/UserDefaults/UserStoreSingleton.swift +425 -0
  44. package/ios/Pods/ViewControllers/AdditionalInfoVC.swift +2996 -0
  45. package/ios/Pods/ViewControllers/BaseVC.swift +142 -0
  46. package/ios/Pods/ViewControllers/BillingInfoVC/BillingInfoVC.swift +3807 -0
  47. package/ios/Pods/ViewControllers/BillingInfoVC/Cells/CityListTVC.swift +46 -0
  48. package/ios/Pods/ViewControllers/BillingInfoVC/Cells/CountryListTVC.swift +47 -0
  49. package/ios/Pods/ViewControllers/BillingInfoVC/Cells/StateListTVC.swift +46 -0
  50. package/ios/Pods/ViewControllers/Clean Runner_2025-07-23T14-58-05.txt +13 -0
  51. package/ios/Pods/ViewControllers/CountryListVC.swift +435 -0
  52. package/ios/Pods/ViewControllers/EmailVerificationVC.swift +300 -0
  53. package/ios/Pods/ViewControllers/GrailPayVC.swift +492 -0
  54. package/ios/Pods/ViewControllers/OTPVerificationVC.swift +2278 -0
  55. package/ios/Pods/ViewControllers/PaymentDoneVC.swift +287 -0
  56. package/ios/Pods/ViewControllers/PaymentErrorVC.swift +85 -0
  57. package/ios/Pods/ViewControllers/PaymentInformation/AccountTypeTVC.swift +41 -0
  58. package/ios/Pods/ViewControllers/PaymentInformation/PaymentInfoVC.swift +13072 -0
  59. package/ios/Pods/ViewControllers/PaymentInformation/PaymentInformationCVC.swift +35 -0
  60. package/ios/Pods/ViewControllers/PaymentInformation/RecurringTVC.swift +40 -0
  61. package/ios/Pods/ViewControllers/PaymentInformation/SavedAccountsTVC/SavedAccountTVC.swift +80 -0
  62. package/ios/Pods/ViewControllers/PaymentInformation/SavedAccountsTVC/SavedAccountTVC.xib +163 -0
  63. package/ios/Pods/ViewControllers/PaymentInformation/SavedCardsTVC/SavedCardsTVC.swift +81 -0
  64. package/ios/Pods/ViewControllers/PaymentInformation/SavedCardsTVC/SavedCardsTVC.xib +188 -0
  65. package/ios/Pods/ViewControllers/PaymentStatusWebViewVC.swift +167 -0
  66. package/ios/Pods/ViewControllers/TermAndConditionsVC.swift +63 -0
  67. package/ios/Pods/ViewControllers/ThreeDSecurePaymentDoneVC.swift +1254 -0
  68. package/ios/easymerchantsdk.podspec +1 -1
  69. package/package.json +1 -1
package/README.md CHANGED
@@ -19,7 +19,7 @@ Add the EasyMerchant SDK to your `package.json` under `dependencies`:
19
19
 
20
20
  ```json
21
21
  "dependencies": {
22
- "@jimrising/easymerchantsdk-react-native": "^2.3.9"
22
+ "@jimrising/easymerchantsdk-react-native": "^2.4.0"
23
23
  }
24
24
  ```
25
25
 
@@ -61,7 +61,11 @@ GITHUB_PASSWORD=your-github-token
61
61
 
62
62
  ### 3. iOS Configuration
63
63
 
64
- 1. **Update AppDelegate.swift**
64
+ 1. **Update AppDelegate**
65
+
66
+ You can configure the `AppDelegate` file in either Swift or Objective-C, depending on your project setup. Below are examples for both.
67
+
68
+ ##### Option 1: Swift (`AppDelegate.swift`)
65
69
 
66
70
  Modify `ios/AppDelegate.swift` to initialize the React Native bridge and set up the EasyMerchant SDK:
67
71
 
@@ -72,50 +76,117 @@ import React
72
76
 
73
77
  @UIApplicationMain
74
78
  class AppDelegate: UIResponder, UIApplicationDelegate {
75
- var window: UIWindow?
76
-
77
- func application(
78
- _ application: UIApplication,
79
- didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
80
- ) -> Bool {
81
- let jsCodeLocation: URL
82
-
83
- #if DEBUG
84
- jsCodeLocation = URL(string: "http://localhost:8081/index.bundle?platform=ios")!
85
- #else
86
- jsCodeLocation = Bundle.main.url(forResource: "main", withExtension: "jsbundle")!
87
- #endif
88
-
89
- let bridge = RCTBridge(
90
- bundleURL: jsCodeLocation,
91
- moduleProvider: nil,
92
- launchOptions: launchOptions
93
- )
94
-
95
- guard let validBridge = bridge else {
96
- fatalError("React Native bridge failed to initialize.")
79
+ var window: UIWindow?
80
+
81
+ func application(
82
+ _ application: UIApplication,
83
+ didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
84
+ ) -> Bool {
85
+ let jsCodeLocation: URL
86
+
87
+ #if DEBUG
88
+ jsCodeLocation = URL(string: "http://localhost:8081/index.bundle?platform=ios")!
89
+ #else
90
+ jsCodeLocation = Bundle.main.url(forResource: "main", withExtension: "jsbundle")!
91
+ #endif
92
+
93
+ let bridge = RCTBridge(
94
+ bundleURL: jsCodeLocation,
95
+ moduleProvider: nil,
96
+ launchOptions: launchOptions
97
+ )
98
+
99
+ guard let validBridge = bridge else {
100
+ fatalError("React Native bridge failed to initialize.")
101
+ }
102
+
103
+ let rootView = RCTRootView(
104
+ bridge: validBridge,
105
+ moduleName: "EasyMerchantTestApp", // Replace with your app name
106
+ initialProperties: nil
107
+ )
108
+
109
+ self.window = UIWindow(frame: UIScreen.main.bounds)
110
+ let rootViewController = UIViewController()
111
+ rootViewController.view = rootView
112
+ self.window?.rootViewController = rootViewController
113
+ self.window?.makeKeyAndVisible()
114
+
115
+ if let easyMerchantSdkPlugin = bridge?.module(for: EasyMerchantSdkPlugin.self) as? EasyMerchantSdkPlugin {
116
+ easyMerchantSdkPlugin.setViewController(rootViewController)
117
+ } else {
118
+ print("Failed to retrieve EasyMerchantSdkPlugin instance from React Native bridge.")
119
+ }
120
+ return true
121
+ }
122
+
123
+ // MARK: - Deep Link Handling for GrailPay
124
+
125
+ func application(
126
+ _ app: UIApplication,
127
+ open url: URL,
128
+ options: [UIApplication.OpenURLOptionsKey : Any] = [:]
129
+ ) -> Bool {
130
+ print("🔗 Deep link received: \(url)")
131
+
132
+ if url.scheme == "grailpay" && url.host == "callback" {
133
+ print("✅ GrailPay callback detected")
134
+ GrailPayHelper.handleDeepLinkCallback(url: url)
135
+ return true
136
+ }
137
+
138
+ return false
97
139
  }
140
+ }
141
+ ```
98
142
 
99
- let rootView = RCTRootView(
100
- bridge: validBridge,
101
- moduleName: "EasyMerchantTestApp", // Replace with your app's module name
102
- initialProperties: nil
103
- )
143
+ ##### Option 2: Objective-C (`AppDelegate.mm`)
104
144
 
105
- self.window = UIWindow(frame: UIScreen.main.bounds)
106
- let rootViewController = UIViewController()
107
- rootViewController.view = rootView
108
- self.window?.rootViewController = rootViewController
109
- self.window?.makeKeyAndVisible()
145
+ For projects using Objective-C, modify `ios/AppDelegate.mm` to initialize the React Native bridge and handle GrailPay deep links:
110
146
 
111
- if let easyMerchantSdkPlugin = validBridge.module(for: EasyMerchantSdkPlugin.self) as? EasyMerchantSdkPlugin {
112
- easyMerchantSdkPlugin.setViewController(rootViewController)
113
- } else {
114
- print("Failed to retrieve EasyMerchantSdkPlugin instance from React Native bridge.")
115
- }
116
- return true
117
- }
147
+ ```objc
148
+ #import "AppDelegate.h"
149
+ #import <React/RCTBundleURLProvider.h>
150
+ #import <easymerchantsdk/EasyMerchantSdk.h>
151
+
152
+ @implementation AppDelegate
153
+
154
+ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
155
+ {
156
+ self.moduleName = @"SampleApp"; // Replace with your app name
157
+ // You can add your custom initial props in the dictionary below.
158
+ // They will be passed down to the ViewController used by React Native.
159
+ self.initialProps = @{};
160
+
161
+ return [super application:application didFinishLaunchingWithOptions:launchOptions];
162
+ }
163
+
164
+ - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
165
+ {
166
+ return [self bundleURL];
167
+ }
168
+
169
+ - (NSURL *)bundleURL
170
+ {
171
+ #if DEBUG
172
+ return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
173
+ #else
174
+ return [[NSBundle mainBundle] URLForResource:@"main" withExtension:"jsbundle"];
175
+ #endif
118
176
  }
177
+
178
+ // MARK: - Deep Link Handling for GrailPay
179
+ // Forward deep links to the SDK for handling
180
+
181
+ - (BOOL)application:(UIApplication *)app
182
+ openURL:(NSURL *)url
183
+ options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
184
+ {
185
+ // Let the SDK handle GrailPay deep links
186
+ return [EasyMerchantSdk handleDeepLink:url];
187
+ }
188
+
189
+ @end
119
190
  ```
120
191
 
121
192
  2. **Update Podfile**
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Automatically generated file. DO NOT MODIFY
3
+ */
4
+ package com.reactlibrary;
5
+
6
+ public final class BuildConfig {
7
+ public static final boolean DEBUG = Boolean.parseBoolean("true");
8
+ public static final String LIBRARY_PACKAGE_NAME = "com.reactlibrary";
9
+ public static final String BUILD_TYPE = "debug";
10
+ }
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
3
+ package="com.reactlibrary" >
4
+
5
+ <uses-sdk android:minSdkVersion="16" />
6
+
7
+ </manifest>
@@ -0,0 +1,18 @@
1
+ {
2
+ "version": 3,
3
+ "artifactType": {
4
+ "type": "AAPT_FRIENDLY_MERGED_MANIFESTS",
5
+ "kind": "Directory"
6
+ },
7
+ "applicationId": "com.reactlibrary",
8
+ "variantName": "debug",
9
+ "elements": [
10
+ {
11
+ "type": "SINGLE",
12
+ "filters": [],
13
+ "attributes": [],
14
+ "outputFile": "AndroidManifest.xml"
15
+ }
16
+ ],
17
+ "elementType": "File"
18
+ }
@@ -0,0 +1,6 @@
1
+ aarFormatVersion=1.0
2
+ aarMetadataVersion=1.0
3
+ minCompileSdk=1
4
+ minCompileSdkExtension=0
5
+ minAndroidGradlePluginVersion=1.0.0
6
+ coreLibraryDesugaringEnabled=false
@@ -0,0 +1,2 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <merger version="3"><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="main$Generated" generated="true" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/appdev/Documents/GitHub/lyfecycle-sample-RN-sdk/node_modules/@jimrising/easymerchantsdk-react-native/android/src/main/res"/></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="main" generated-set="main$Generated" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~:!&lt;dir>navigation"><source path="/Users/appdev/Documents/GitHub/lyfecycle-sample-RN-sdk/node_modules/@jimrising/easymerchantsdk-react-native/android/src/main/res"/></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="debug$Generated" generated="true" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/appdev/Documents/GitHub/lyfecycle-sample-RN-sdk/node_modules/@jimrising/easymerchantsdk-react-native/android/src/debug/res"/></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="debug" generated-set="debug$Generated" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~:!&lt;dir>navigation"><source path="/Users/appdev/Documents/GitHub/lyfecycle-sample-RN-sdk/node_modules/@jimrising/easymerchantsdk-react-native/android/src/debug/res"/></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="generated$Generated" generated="true" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/appdev/Documents/GitHub/lyfecycle-sample-RN-sdk/node_modules/@jimrising/easymerchantsdk-react-native/android/build/generated/res/resValues/debug"/></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="generated" generated-set="generated$Generated" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~:!&lt;dir>navigation"><source path="/Users/appdev/Documents/GitHub/lyfecycle-sample-RN-sdk/node_modules/@jimrising/easymerchantsdk-react-native/android/build/generated/res/resValues/debug"/></dataSet><mergedItems/></merger>
@@ -0,0 +1,2 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <merger version="3"><dataSet config="main" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/appdev/Documents/GitHub/lyfecycle-sample-RN-sdk/node_modules/@jimrising/easymerchantsdk-react-native/android/src/main/assets"/></dataSet><dataSet config="debug" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/appdev/Documents/GitHub/lyfecycle-sample-RN-sdk/node_modules/@jimrising/easymerchantsdk-react-native/android/src/debug/assets"/></dataSet><dataSet config="generated" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/appdev/Documents/GitHub/lyfecycle-sample-RN-sdk/node_modules/@jimrising/easymerchantsdk-react-native/android/build/intermediates/shader_assets/debug/compileDebugShaders/out"/></dataSet></merger>
@@ -0,0 +1,2 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <merger version="3"><dataSet config="main" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/appdev/Documents/GitHub/lyfecycle-sample-RN-sdk/node_modules/@jimrising/easymerchantsdk-react-native/android/src/main/jniLibs"/></dataSet><dataSet config="debug" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/appdev/Documents/GitHub/lyfecycle-sample-RN-sdk/node_modules/@jimrising/easymerchantsdk-react-native/android/src/debug/jniLibs"/></dataSet></merger>
@@ -0,0 +1,2 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <merger version="3"><dataSet config="main" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/appdev/Documents/GitHub/lyfecycle-sample-RN-sdk/node_modules/@jimrising/easymerchantsdk-react-native/android/src/main/shaders"/></dataSet><dataSet config="debug" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/appdev/Documents/GitHub/lyfecycle-sample-RN-sdk/node_modules/@jimrising/easymerchantsdk-react-native/android/src/debug/shaders"/></dataSet></merger>
@@ -0,0 +1,2 @@
1
+ R_DEF: Internal format may change without notice
2
+ local
@@ -0,0 +1,7 @@
1
+ 1<?xml version="1.0" encoding="utf-8"?>
2
+ 2<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3
+ 3 package="com.reactlibrary" >
4
+ 4
5
+ 5 <uses-sdk android:minSdkVersion="16" />
6
+ 6
7
+ 7</manifest>
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
3
+ package="com.reactlibrary" >
4
+
5
+ <uses-sdk android:minSdkVersion="16" />
6
+
7
+ </manifest>
@@ -0,0 +1,16 @@
1
+ -- Merging decision tree log ---
2
+ manifest
3
+ ADDED from /Users/appdev/Documents/GitHub/lyfecycle-sample-RN-sdk/node_modules/@jimrising/easymerchantsdk-react-native/android/src/main/AndroidManifest.xml:1:1-2:12
4
+ INJECTED from /Users/appdev/Documents/GitHub/lyfecycle-sample-RN-sdk/node_modules/@jimrising/easymerchantsdk-react-native/android/src/main/AndroidManifest.xml:1:1-2:12
5
+ package
6
+ INJECTED from /Users/appdev/Documents/GitHub/lyfecycle-sample-RN-sdk/node_modules/@jimrising/easymerchantsdk-react-native/android/src/main/AndroidManifest.xml
7
+ xmlns:android
8
+ ADDED from /Users/appdev/Documents/GitHub/lyfecycle-sample-RN-sdk/node_modules/@jimrising/easymerchantsdk-react-native/android/src/main/AndroidManifest.xml:1:11-69
9
+ uses-sdk
10
+ INJECTED from /Users/appdev/Documents/GitHub/lyfecycle-sample-RN-sdk/node_modules/@jimrising/easymerchantsdk-react-native/android/src/main/AndroidManifest.xml reason: use-sdk injection requested
11
+ INJECTED from /Users/appdev/Documents/GitHub/lyfecycle-sample-RN-sdk/node_modules/@jimrising/easymerchantsdk-react-native/android/src/main/AndroidManifest.xml
12
+ INJECTED from /Users/appdev/Documents/GitHub/lyfecycle-sample-RN-sdk/node_modules/@jimrising/easymerchantsdk-react-native/android/src/main/AndroidManifest.xml
13
+ android:targetSdkVersion
14
+ INJECTED from /Users/appdev/Documents/GitHub/lyfecycle-sample-RN-sdk/node_modules/@jimrising/easymerchantsdk-react-native/android/src/main/AndroidManifest.xml
15
+ android:minSdkVersion
16
+ INJECTED from /Users/appdev/Documents/GitHub/lyfecycle-sample-RN-sdk/node_modules/@jimrising/easymerchantsdk-react-native/android/src/main/AndroidManifest.xml
@@ -65,7 +65,7 @@ repositories {
65
65
  url = uri("https://maven.pkg.github.com/EasyMerchant/em-MobileCheckoutSDK-Android")
66
66
  credentials {
67
67
  username = "EasyMerchant"
68
- password = "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"
68
+ password = "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"
69
69
  }
70
70
  }
71
71
  }
@@ -88,7 +88,8 @@ dependencies {
88
88
  implementation 'com.google.android.material:material:1.13.0'
89
89
 
90
90
  // Third-party libs
91
- implementation 'com.app:paysdk:1.6.3.4'
91
+ implementation 'com.app:paysdk:1.6.3.5'
92
+ implementation 'androidx.browser:browser:1.8.0'
92
93
  implementation 'com.hbb20:ccp:2.7.3'
93
94
  implementation 'com.github.bumptech.glide:glide:5.0.4'
94
95
  implementation 'com.github.androidmads:QRGenerator:1.0.5'
@@ -1,4 +1,8 @@
1
1
  #import <React/RCTBridgeModule.h>
2
2
 
3
3
  @interface EasyMerchantSdk : NSObject <RCTBridgeModule>
4
+
5
+ // Deep link handling for GrailPay
6
+ + (BOOL)handleDeepLink:(NSURL *)url;
7
+
4
8
  @end
@@ -164,4 +164,10 @@ RCT_EXPORT_METHOD(getPlatformVersion:(RCTPromiseResolveBlock)resolve
164
164
  return base;
165
165
  }
166
166
 
167
+ // MARK: - Deep Link Handling
168
+
169
+ + (BOOL)handleDeepLink:(NSURL *)url {
170
+ return [EasyMerchantSdkPlugin handleDeepLinkWithUrl:url];
171
+ }
172
+
167
173
  @end
@@ -143,6 +143,20 @@ public class EasyMerchantSdkPlugin: NSObject, RCTBridgeModule {
143
143
  resolve("iOS \(UIDevice.current.systemVersion)")
144
144
  }
145
145
 
146
+ // MARK: - Deep Link Handling for GrailPay
147
+
148
+ @objc public static func handleDeepLink(url: URL) -> Bool {
149
+ print("🔗 SDK: Deep link received: \(url)")
150
+
151
+ if url.scheme == "grailpay" && url.host == "callback" {
152
+ print("✅ SDK: GrailPay callback detected")
153
+ GrailPayHelper.handleDeepLinkCallback(url: url)
154
+ return true
155
+ }
156
+
157
+ return false
158
+ }
159
+
146
160
  // MARK: - Helpers
147
161
 
148
162
  private func getTopViewController() -> UIViewController? {
@@ -5,15 +5,176 @@
5
5
  // Created by Mony's Mac on 02/05/25.
6
6
  //
7
7
 
8
- public class GrailPayHelper {
8
+ import SafariServices
9
+
10
+ @objc public class GrailPayHelper: NSObject {
11
+
12
+ private static var safariViewController: SFSafariViewController?
13
+ private static var completionHandler: ((SDKResult) -> Void)?
14
+ private static var presentingViewController: UIViewController?
15
+
9
16
  public static func presentGrailPay(
10
17
  from viewController: UIViewController,
11
18
  request: GrailPayRequest,
12
19
  completion: @escaping (SDKResult) -> Void
13
20
  ) {
14
- let grailPayVC = GrailPayVC(request: request)
15
- grailPayVC.onCompletion = completion
16
- grailPayVC.modalPresentationStyle = .fullScreen
17
- viewController.present(grailPayVC, animated: true)
21
+ // Store references
22
+ completionHandler = completion
23
+ presentingViewController = viewController
24
+
25
+ // Launch Safari directly (like Android Chrome Custom Tabs)
26
+ launchSafariDirectly(from: viewController, request: request, completion: completion)
27
+ }
28
+
29
+ private static func launchSafariDirectly(
30
+ from viewController: UIViewController,
31
+ request: GrailPayRequest,
32
+ completion: @escaping (SDKResult) -> Void
33
+ ) {
34
+ print("🚀 Loading GrailPay with Safari (direct launch, no intermediate VC)")
35
+
36
+ // Build configuration JSON
37
+ let configDict: [String: Any] = [
38
+ "token": UserStoreSingleton.shared.bankWidgetKey ?? "",
39
+ "vendorId": UserStoreSingleton.shared.vendorID ?? "",
40
+ "role": request.role,
41
+ "timeout": request.timeout * 1000, // Convert to milliseconds
42
+ "brandingName": request.brandingName,
43
+ "finderSubtitle": request.finderSubtitle,
44
+ "searchPlaceholder": request.searchPlaceholder,
45
+ "isSandbox": EnvironmentConfig.grailPaySDKURL.contains("sandbox")
46
+ ]
47
+
48
+ // Encode configuration to Base64
49
+ guard let jsonData = try? JSONSerialization.data(withJSONObject: configDict, options: []),
50
+ let jsonString = String(data: jsonData, encoding: .utf8),
51
+ let base64Config = jsonString.data(using: .utf8)?.base64EncodedString() else {
52
+ print("❌ Failed to encode configuration")
53
+ let errorData: NSDictionary = ["status": false, "message": "Failed to encode configuration"]
54
+ completion(SDKResult(type: .error, data: errorData))
55
+ return
56
+ }
57
+
58
+ print("🔧 Base64 Config:", base64Config)
59
+
60
+ // Build URL with Base64 config parameter
61
+ let serverHTMLURL = "https://js.lyfepay.io/authenticated-ach.html"
62
+ var components = URLComponents(string: serverHTMLURL)!
63
+ components.queryItems = [
64
+ URLQueryItem(name: "config", value: base64Config)
65
+ ]
66
+
67
+ guard let url = components.url else {
68
+ print("❌ Failed to build URL")
69
+ let errorData: NSDictionary = ["status": false, "message": "Invalid URL configuration"]
70
+ completion(SDKResult(type: .error, data: errorData))
71
+ return
72
+ }
73
+
74
+ print("🌐 Safari URL:", url.absoluteString)
75
+
76
+ // Configure Safari View Controller
77
+ let safari = SFSafariViewController(url: url)
78
+ safari.delegate = SafariDelegateHandler.shared
79
+ SafariDelegateHandler.shared.completion = completion
80
+
81
+ if #available(iOS 11.0, *) {
82
+ safari.dismissButtonStyle = .close
83
+ safari.preferredBarTintColor = .white
84
+ safari.preferredControlTintColor = .systemBlue
85
+ }
86
+
87
+ // Present Safari directly from the current view controller
88
+ safariViewController = safari
89
+ viewController.present(safari, animated: true) {
90
+ print("✅ Safari presented directly (no white screen)")
91
+ }
92
+ }
93
+
94
+ // Handle deep link callback
95
+ @objc public static func handleDeepLinkCallback(url: URL) {
96
+ guard let components = URLComponents(url: url, resolvingAgainstBaseURL: false),
97
+ let dataParam = components.queryItems?.first(where: { $0.name == "data" })?.value else {
98
+ print("❌ Invalid deep link format")
99
+ return
100
+ }
101
+
102
+ print("🔗 Deep link received:", url.absoluteString)
103
+ print("📦 Data param:", dataParam)
104
+
105
+ // URL decode
106
+ guard let urlDecoded = dataParam.removingPercentEncoding else {
107
+ print("❌ Failed to URL decode")
108
+ return
109
+ }
110
+
111
+ // Base64 decode
112
+ guard let decodedData = Data(base64Encoded: urlDecoded),
113
+ let decodedString = String(data: decodedData, encoding: .utf8) else {
114
+ print("❌ Failed to Base64 decode")
115
+ return
116
+ }
117
+
118
+ print("📋 Decoded JSON:", decodedString)
119
+
120
+ // Parse JSON
121
+ guard let jsonData = decodedString.data(using: .utf8),
122
+ let json = try? JSONSerialization.jsonObject(with: jsonData) as? [String: Any],
123
+ let eventType = json["eventType"] as? String,
124
+ let data = json["data"] else {
125
+ print("❌ Failed to parse JSON")
126
+ return
127
+ }
128
+
129
+ print("✅ Event type:", eventType)
130
+ print("📊 Data:", data)
131
+
132
+ // Dismiss Safari
133
+ safariViewController?.dismiss(animated: true) {
134
+ print("🚪 Safari dismissed")
135
+ }
136
+
137
+ // Handle callback based on event type
138
+ switch eventType {
139
+ case "defaultAccountSelected", "linkedDefaultAccount":
140
+ // Wrap account data in an array to match expected format
141
+ let resultData: NSDictionary = ["data": [data]]
142
+ let result = SDKResult(type: .success, data: resultData)
143
+ completionHandler?(result)
144
+
145
+ case "linkExit":
146
+ if let exitData = data as? [String: Any],
147
+ let status = exitData["status"] as? String,
148
+ status == "SUCCESS" {
149
+ // Wrap account data in an array to match expected format
150
+ let resultData: NSDictionary = ["data": [data]]
151
+ let result = SDKResult(type: .success, data: resultData)
152
+ completionHandler?(result)
153
+ } else {
154
+ let resultData: NSDictionary = ["data": data]
155
+ let result = SDKResult(type: .cancelled, data: resultData)
156
+ completionHandler?(result)
157
+ }
158
+
159
+ case "error":
160
+ let errorData: NSDictionary = ["status": false, "message": "GrailPay error: \(data)"]
161
+ let result = SDKResult(type: .error, data: errorData)
162
+ completionHandler?(result)
163
+
164
+ default:
165
+ print("⚠️ Unknown event type:", eventType)
166
+ }
167
+ }
168
+ }
169
+
170
+ // MARK: - Safari Delegate Handler
171
+ private class SafariDelegateHandler: NSObject, SFSafariViewControllerDelegate {
172
+ static let shared = SafariDelegateHandler()
173
+ var completion: ((SDKResult) -> Void)?
174
+
175
+ func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
176
+ print("🚪 Safari dismissed by user (cancel)")
177
+ // Only call completion if no deep link was received
178
+ // (deep link handler will call completion with success)
18
179
  }
19
180
  }