@jimrising/easymerchantsdk-react-native 1.3.3 → 1.3.4
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 +11 -11
- package/README.md +60 -76
- package/ios/Classes/EasyMerchantSdk.m +52 -37
- package/ios/Classes/EasyMerchantSdk.swift +61 -59
- package/ios/CustomComponents/DatePickerHandler.swift +71 -0
- package/ios/CustomComponents/PlanSelector.swift +58 -0
- package/ios/EnvironmentConfig.swift +2 -1
- package/ios/Models/Request.swift +45 -43
- package/ios/Pods/ViewControllers/AdditionalInfoVC.swift +150 -165
- package/ios/Pods/ViewControllers/BillingInfoVC/BillingInfoVC.swift +56 -183
- package/ios/Pods/ViewControllers/CountryListVC.swift +12 -0
- package/ios/Pods/ViewControllers/EmailVerificationVC.swift +7 -0
- package/ios/Pods/ViewControllers/OTPVerificationVC.swift +77 -5
- package/ios/Pods/ViewControllers/PaymentDoneVC.swift +4 -1
- package/ios/Pods/ViewControllers/PaymentInformation/PaymentInfoVC.swift +585 -168
- package/ios/Pods/ViewControllers/PaymentInformation/RecurringTVC.swift +40 -0
- package/ios/easymerchantsdk.podspec +1 -1
- package/ios/easymerchantsdk.storyboard +2067 -732
- package/package.json +1 -1
- package/.idea/workspace.xml +0 -199
|
@@ -47,17 +47,6 @@
|
|
|
47
47
|
<option name="screenX" value="1080" />
|
|
48
48
|
<option name="screenY" value="2160" />
|
|
49
49
|
</PersistentDeviceSelectionData>
|
|
50
|
-
<PersistentDeviceSelectionData>
|
|
51
|
-
<option name="api" value="34" />
|
|
52
|
-
<option name="brand" value="Lenovo" />
|
|
53
|
-
<option name="codename" value="TB370FU" />
|
|
54
|
-
<option name="id" value="TB370FU" />
|
|
55
|
-
<option name="manufacturer" value="Lenovo" />
|
|
56
|
-
<option name="name" value="Tab P12" />
|
|
57
|
-
<option name="screenDensity" value="340" />
|
|
58
|
-
<option name="screenX" value="1840" />
|
|
59
|
-
<option name="screenY" value="2944" />
|
|
60
|
-
</PersistentDeviceSelectionData>
|
|
61
50
|
<PersistentDeviceSelectionData>
|
|
62
51
|
<option name="api" value="34" />
|
|
63
52
|
<option name="brand" value="samsung" />
|
|
@@ -69,6 +58,17 @@
|
|
|
69
58
|
<option name="screenX" value="1080" />
|
|
70
59
|
<option name="screenY" value="2340" />
|
|
71
60
|
</PersistentDeviceSelectionData>
|
|
61
|
+
<PersistentDeviceSelectionData>
|
|
62
|
+
<option name="api" value="34" />
|
|
63
|
+
<option name="brand" value="samsung" />
|
|
64
|
+
<option name="codename" value="a15x" />
|
|
65
|
+
<option name="id" value="a15x" />
|
|
66
|
+
<option name="manufacturer" value="Samsung" />
|
|
67
|
+
<option name="name" value="A15 5G" />
|
|
68
|
+
<option name="screenDensity" value="450" />
|
|
69
|
+
<option name="screenX" value="1080" />
|
|
70
|
+
<option name="screenY" value="2340" />
|
|
71
|
+
</PersistentDeviceSelectionData>
|
|
72
72
|
<PersistentDeviceSelectionData>
|
|
73
73
|
<option name="api" value="34" />
|
|
74
74
|
<option name="brand" value="samsung" />
|
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ To add the path of sdk in your project. Open your `package.json` file and inside
|
|
|
7
7
|
|
|
8
8
|
```json
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"@jimrising/easymerchantsdk-react-native": "^1.3.
|
|
10
|
+
"@jimrising/easymerchantsdk-react-native": "^1.3.4"
|
|
11
11
|
},
|
|
12
12
|
```
|
|
13
13
|
|
|
@@ -120,11 +120,9 @@ import {
|
|
|
120
120
|
StyleSheet,
|
|
121
121
|
Platform,
|
|
122
122
|
NativeModules,
|
|
123
|
-
NativeEventEmitter
|
|
124
123
|
} from 'react-native';
|
|
125
124
|
|
|
126
125
|
const { RNEasymerchantsdk, EasyMerchantSdk } = NativeModules;
|
|
127
|
-
const sdkEvents = Platform.OS === 'ios' ? new NativeEventEmitter(EasyMerchantSdk) : null;
|
|
128
126
|
|
|
129
127
|
const App = () => {
|
|
130
128
|
const [version, setVersion] = useState('');
|
|
@@ -136,38 +134,18 @@ const App = () => {
|
|
|
136
134
|
if (Platform.OS === 'ios') {
|
|
137
135
|
await EasyMerchantSdk.setViewController();
|
|
138
136
|
EasyMerchantSdk.configureEnvironment(
|
|
139
|
-
'staging', // sandbox
|
|
140
|
-
'
|
|
141
|
-
'
|
|
137
|
+
'staging', // Options: sandbox, staging, production
|
|
138
|
+
'14fbf8a186091763e59c289c1',
|
|
139
|
+
'f90863e7a853539f8ace8d6de'
|
|
142
140
|
);
|
|
143
141
|
}
|
|
144
|
-
|
|
145
|
-
// Add listeners for iOS
|
|
146
|
-
if (sdkEvents) {
|
|
147
|
-
sdkEvents.addListener('EasyPaySuccess', (data) => {
|
|
148
|
-
setResponse(`✅ Success: ${JSON.stringify(data)}`);
|
|
149
|
-
});
|
|
150
|
-
sdkEvents.addListener('EasyPayCancelled', () => {
|
|
151
|
-
setResponse('⚠️ Payment Cancelled');
|
|
152
|
-
});
|
|
153
|
-
sdkEvents.addListener('EasyPayError', (err) => {
|
|
154
|
-
setResponse(`❌ Error: ${JSON.stringify(err)}`);
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
142
|
} catch (err) {
|
|
158
|
-
console.error('Initialization Error:', err
|
|
143
|
+
console.error('Initialization Error:', err);
|
|
144
|
+
setResponse(`❌ Initialization Error: ${err.message || err}`);
|
|
159
145
|
}
|
|
160
146
|
};
|
|
161
147
|
|
|
162
148
|
setup();
|
|
163
|
-
|
|
164
|
-
return () => {
|
|
165
|
-
if (sdkEvents) {
|
|
166
|
-
sdkEvents.removeAllListeners('EasyPaySuccess');
|
|
167
|
-
sdkEvents.removeAllListeners('EasyPayCancelled');
|
|
168
|
-
sdkEvents.removeAllListeners('EasyPayError');
|
|
169
|
-
}
|
|
170
|
-
};
|
|
171
149
|
}, []);
|
|
172
150
|
|
|
173
151
|
const getPlatformVersion = async () => {
|
|
@@ -179,11 +157,12 @@ const App = () => {
|
|
|
179
157
|
setVersion(ver);
|
|
180
158
|
} catch (err) {
|
|
181
159
|
setVersion('Error fetching version');
|
|
160
|
+
console.error(err);
|
|
182
161
|
}
|
|
183
162
|
};
|
|
184
163
|
|
|
185
164
|
const handleBilling = async () => {
|
|
186
|
-
const amount = '
|
|
165
|
+
const amount = '64';
|
|
187
166
|
const billingInfo = {
|
|
188
167
|
address: 'Test',
|
|
189
168
|
country: 'test',
|
|
@@ -193,36 +172,44 @@ const App = () => {
|
|
|
193
172
|
additional_info: {
|
|
194
173
|
name: 'Test User',
|
|
195
174
|
email: 'test@gmail.com',
|
|
196
|
-
phone_number: '
|
|
175
|
+
phone_number: '234983789',
|
|
197
176
|
country_code: '91',
|
|
198
|
-
description: 'SDK Test'
|
|
199
|
-
}
|
|
177
|
+
description: 'SDK Test',
|
|
178
|
+
},
|
|
200
179
|
};
|
|
201
180
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
181
|
+
const themeConfiguration = {
|
|
182
|
+
bodyBackgroundColor: '#FFEEEE',
|
|
183
|
+
containerBackgroundColor: '#FFCCCC',
|
|
184
|
+
primaryFontColor: '#B30000',
|
|
185
|
+
secondaryFontColor: '#660000',
|
|
186
|
+
primaryButtonBackgroundColor: '#D50000',
|
|
187
|
+
primaryButtonHoverColor: '#9C0000',
|
|
188
|
+
primaryButtonFontColor: '#FFFFFF',
|
|
189
|
+
secondaryButtonBackgroundColor: '#FF6666',
|
|
190
|
+
secondaryButtonHoverColor: '#FF4D4D',
|
|
191
|
+
secondaryButtonFontColor: '#FFFFFF',
|
|
192
|
+
borderRadius: '12',
|
|
193
|
+
fontSize: '16',
|
|
194
|
+
};
|
|
218
195
|
|
|
196
|
+
const authConfig = {
|
|
197
|
+
accessToken: '251|uTijpDGfrS88UR2V1cZNMQ8S4hUJA0sVzsnsoUZF',
|
|
198
|
+
vendorId: '251',
|
|
199
|
+
role: 'business',
|
|
200
|
+
timeout: 10,
|
|
201
|
+
isSandbox: true,
|
|
202
|
+
brandingName: 'Lyfecycle Payments',
|
|
203
|
+
finderSubtitle: 'Search for your bank',
|
|
204
|
+
searchPlaceholder: 'Enter bank name',
|
|
205
|
+
};
|
|
219
206
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
await EasyMerchantSdk.billing(
|
|
207
|
+
try {
|
|
208
|
+
if (Platform.OS === 'android') {
|
|
209
|
+
const result = await RNEasymerchantsdk.billing(amount, null);
|
|
210
|
+
setResponse(`✅ Android Payment Success: ${result}`);
|
|
211
|
+
} else {
|
|
212
|
+
const result = await EasyMerchantSdk.billing(
|
|
226
213
|
amount,
|
|
227
214
|
JSON.stringify(billingInfo),
|
|
228
215
|
['card', 'bank', 'crypto'],
|
|
@@ -231,34 +218,30 @@ const App = () => {
|
|
|
231
218
|
false, // saveCard
|
|
232
219
|
false, // saveAccount
|
|
233
220
|
true, // authenticatedACH
|
|
234
|
-
|
|
235
|
-
accessToken: "251|uTijpDGfrS88UR2V1cZNMQ8S4hUJA0sVzsnsoUZF",
|
|
236
|
-
vendorId: "251",
|
|
237
|
-
role: "business",
|
|
238
|
-
timeout: 10,
|
|
239
|
-
isSandbox: true,
|
|
240
|
-
brandingName: "Lyfecycle Payments",
|
|
241
|
-
finderSubtitle: "Search for your bank",
|
|
242
|
-
searchPlaceholder: "Enter bank name"
|
|
243
|
-
}
|
|
221
|
+
authConfig
|
|
244
222
|
);
|
|
245
223
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
224
|
+
console.log("Billing success:", result);
|
|
225
|
+
setResponse(`✅ iOS Payment Success: ${JSON.stringify(result)}`);
|
|
226
|
+
}
|
|
227
|
+
} catch (error) {
|
|
228
|
+
console.error('Billing Error:', error);
|
|
229
|
+
setResponse(`❌ Billing Error: ${error.message || JSON.stringify(error)}`);
|
|
230
|
+
}
|
|
231
|
+
|
|
251
232
|
};
|
|
252
233
|
|
|
253
234
|
return (
|
|
254
235
|
<View style={styles.container}>
|
|
255
236
|
<Text style={styles.title}>EasyMerchant SDK</Text>
|
|
256
237
|
<Text style={styles.version}>Platform Version: {version}</Text>
|
|
238
|
+
|
|
257
239
|
<Button title="Get Platform Version" onPress={getPlatformVersion} />
|
|
258
240
|
<View style={styles.space} />
|
|
259
241
|
<Button title="Start Billing" onPress={handleBilling} />
|
|
260
242
|
<View style={styles.space} />
|
|
261
|
-
|
|
243
|
+
|
|
244
|
+
<Text style={styles.response}>{response}</Text>
|
|
262
245
|
</View>
|
|
263
246
|
);
|
|
264
247
|
};
|
|
@@ -271,30 +254,31 @@ const styles = StyleSheet.create({
|
|
|
271
254
|
backgroundColor: '#F9FAFB',
|
|
272
255
|
alignItems: 'center',
|
|
273
256
|
justifyContent: 'center',
|
|
274
|
-
padding: 24
|
|
257
|
+
padding: 24,
|
|
275
258
|
},
|
|
276
259
|
title: {
|
|
277
260
|
fontSize: 20,
|
|
278
261
|
fontWeight: 'bold',
|
|
279
|
-
marginBottom: 16
|
|
262
|
+
marginBottom: 16,
|
|
280
263
|
},
|
|
281
264
|
version: {
|
|
282
265
|
fontSize: 14,
|
|
283
|
-
marginBottom: 8
|
|
266
|
+
marginBottom: 8,
|
|
284
267
|
},
|
|
285
268
|
response: {
|
|
286
269
|
marginTop: 20,
|
|
287
270
|
paddingHorizontal: 12,
|
|
288
271
|
textAlign: 'center',
|
|
289
272
|
fontSize: 14,
|
|
290
|
-
color: '#333'
|
|
273
|
+
color: '#333',
|
|
291
274
|
},
|
|
292
275
|
space: {
|
|
293
|
-
height: 16
|
|
294
|
-
}
|
|
276
|
+
height: 16,
|
|
277
|
+
},
|
|
295
278
|
});
|
|
296
279
|
|
|
297
280
|
|
|
281
|
+
|
|
298
282
|
```
|
|
299
283
|
|
|
300
284
|
You can send `null` if billing info not available.
|
|
@@ -1,67 +1,82 @@
|
|
|
1
1
|
#import "EasyMerchantSdk.h"
|
|
2
2
|
#import <React/RCTLog.h>
|
|
3
3
|
#import <React/RCTBridgeModule.h>
|
|
4
|
-
#import <easymerchantsdk
|
|
5
|
-
|
|
4
|
+
#import <easymerchantsdk-Swift.h>
|
|
5
|
+
|
|
6
|
+
@interface EasyMerchantSdk()
|
|
7
|
+
@property (nonatomic, strong) EasyMerchantSdkPlugin *sdkPluginInstance;
|
|
8
|
+
@end
|
|
6
9
|
|
|
7
10
|
@implementation EasyMerchantSdk
|
|
8
11
|
|
|
9
12
|
RCT_EXPORT_MODULE()
|
|
10
13
|
|
|
11
|
-
|
|
12
14
|
RCT_EXPORT_METHOD(configureEnvironment:(NSString *)env
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
apiKey:(NSString *)apiKey
|
|
16
|
+
apiSecret:(NSString *)apiSecret)
|
|
15
17
|
{
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
if (!self.sdkPluginInstance) {
|
|
19
|
+
self.sdkPluginInstance = [[EasyMerchantSdkPlugin alloc] init];
|
|
20
|
+
}
|
|
21
|
+
[self.sdkPluginInstance configureEnvironment:env apiKey:apiKey apiSecret:apiSecret];
|
|
18
22
|
}
|
|
19
23
|
|
|
20
24
|
RCT_EXPORT_METHOD(
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
25
|
+
billing:(NSString *)amount
|
|
26
|
+
billingInfo:(NSString *)billingInfo
|
|
27
|
+
paymentMethods:(NSArray *)paymentMethods
|
|
28
|
+
themeConfiguration:(NSDictionary *)themeConfiguration
|
|
29
|
+
tokenOnly:(BOOL)tokenOnly
|
|
30
|
+
saveCard:(BOOL)saveCard
|
|
31
|
+
saveAccount:(BOOL)saveAccount
|
|
32
|
+
authenticatedACH:(BOOL)authenticatedACH
|
|
33
|
+
grailPayParams:(NSDictionary *)grailPayParams
|
|
34
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
35
|
+
rejecter:(RCTPromiseRejectBlock)reject
|
|
32
36
|
)
|
|
33
37
|
{
|
|
34
|
-
|
|
38
|
+
if (!self.sdkPluginInstance) {
|
|
39
|
+
self.sdkPluginInstance = [[EasyMerchantSdkPlugin alloc] init];
|
|
40
|
+
}
|
|
35
41
|
|
|
36
|
-
[
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
[self.sdkPluginInstance billing:amount
|
|
43
|
+
billinginfo:billingInfo
|
|
44
|
+
paymentMethods:paymentMethods
|
|
45
|
+
themeConfiguration:themeConfiguration
|
|
46
|
+
tokenOnly:tokenOnly
|
|
47
|
+
saveCard:saveCard
|
|
48
|
+
saveAccount:saveAccount
|
|
49
|
+
authenticatedACH:authenticatedACH
|
|
50
|
+
grailPayParams:grailPayParams
|
|
51
|
+
resolver:^(id result) {
|
|
52
|
+
resolve(result);
|
|
53
|
+
self.sdkPluginInstance = nil;
|
|
54
|
+
}
|
|
55
|
+
rejecter:^(NSString *code, NSString *message, NSError *error) {
|
|
56
|
+
reject(code, message, error);
|
|
57
|
+
self.sdkPluginInstance = nil;
|
|
58
|
+
}];
|
|
47
59
|
}
|
|
48
60
|
|
|
49
61
|
|
|
50
|
-
|
|
51
|
-
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
RCT_REMAP_METHOD(setViewController,
|
|
65
|
+
setViewControllerWithResolver:(RCTPromiseResolveBlock)resolve
|
|
66
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
52
67
|
{
|
|
53
|
-
UIViewController *
|
|
68
|
+
UIViewController *rootVC = [UIApplication sharedApplication].delegate.window.rootViewController;
|
|
54
69
|
EasyMerchantSdkPlugin *sdkPlugin = [[EasyMerchantSdkPlugin alloc] init];
|
|
55
|
-
[sdkPlugin setViewController:
|
|
56
|
-
resolve(@"ViewController set
|
|
70
|
+
[sdkPlugin setViewController:rootVC];
|
|
71
|
+
resolve(@"ViewController set");
|
|
57
72
|
}
|
|
58
73
|
|
|
74
|
+
|
|
59
75
|
RCT_EXPORT_METHOD(getPlatformVersion:(RCTPromiseResolveBlock)resolve
|
|
60
|
-
|
|
76
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
61
77
|
{
|
|
62
78
|
NSString *platformVersion = [NSString stringWithFormat:@"iOS %@", [[UIDevice currentDevice] systemVersion]];
|
|
63
79
|
resolve(platformVersion);
|
|
64
80
|
}
|
|
65
81
|
|
|
66
82
|
@end
|
|
67
|
-
|
|
@@ -3,11 +3,32 @@ import UIKit
|
|
|
3
3
|
import React
|
|
4
4
|
|
|
5
5
|
@objc(EasyMerchantSdkPlugin)
|
|
6
|
-
public class EasyMerchantSdkPlugin: NSObject {
|
|
6
|
+
public class EasyMerchantSdkPlugin: NSObject, RCTBridgeModule {
|
|
7
|
+
public static func moduleName() -> String { "EasyMerchantSdk" }
|
|
8
|
+
public static func requiresMainQueueSetup() -> Bool { true }
|
|
9
|
+
|
|
10
|
+
public var bridge: RCTBridge?
|
|
7
11
|
|
|
8
12
|
private var viewController: UIViewController?
|
|
9
13
|
private let viewControllerQueue = DispatchQueue(label: "com.easymerchantsdk.viewController")
|
|
10
14
|
|
|
15
|
+
private var billingResolver: RCTPromiseResolveBlock?
|
|
16
|
+
private var billingRejecter: RCTPromiseRejectBlock?
|
|
17
|
+
|
|
18
|
+
// ✅ Default initializer for Objective-C compatibility
|
|
19
|
+
@objc public override init() {
|
|
20
|
+
super.init()
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Optional: Called when the bridge finishes loading
|
|
24
|
+
public func bridgeDidFinishLoading() {
|
|
25
|
+
if self.bridge != nil {
|
|
26
|
+
print("Bridge has been initialized successfully.")
|
|
27
|
+
} else {
|
|
28
|
+
print("Bridge initialization failed.")
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
11
32
|
@objc public func setViewController(_ viewController: UIViewController) {
|
|
12
33
|
viewControllerQueue.sync {
|
|
13
34
|
self.viewController = viewController
|
|
@@ -15,12 +36,11 @@ public class EasyMerchantSdkPlugin: NSObject {
|
|
|
15
36
|
print("ViewController set: \(String(describing: self.viewController))")
|
|
16
37
|
}
|
|
17
38
|
|
|
18
|
-
|
|
19
39
|
@objc public func billing(
|
|
20
40
|
_ amount: String,
|
|
21
|
-
billinginfo: String
|
|
41
|
+
billinginfo: String?,
|
|
22
42
|
paymentMethods: [String],
|
|
23
|
-
themeConfiguration: [String: Any],
|
|
43
|
+
themeConfiguration: [String: Any],
|
|
24
44
|
tokenOnly: Bool,
|
|
25
45
|
saveCard: Bool,
|
|
26
46
|
saveAccount: Bool,
|
|
@@ -34,10 +54,12 @@ public class EasyMerchantSdkPlugin: NSObject {
|
|
|
34
54
|
return
|
|
35
55
|
}
|
|
36
56
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
57
|
+
if let billinginfo = billinginfo {
|
|
58
|
+
guard let billingInfoData = billinginfo.data(using: .utf8),
|
|
59
|
+
let _ = try? JSONSerialization.jsonObject(with: billingInfoData, options: []) else {
|
|
60
|
+
rejecter("INVALID_BILLING_INFO", "Billing info must be valid JSON", nil)
|
|
61
|
+
return
|
|
62
|
+
}
|
|
41
63
|
}
|
|
42
64
|
|
|
43
65
|
let methods: [PaymentMethod] = paymentMethods.compactMap {
|
|
@@ -63,35 +85,23 @@ public class EasyMerchantSdkPlugin: NSObject {
|
|
|
63
85
|
)
|
|
64
86
|
}
|
|
65
87
|
|
|
66
|
-
// Extract themeConfiguration values from JS
|
|
67
|
-
let bodyBackgroundColor = themeConfiguration["bodyBackgroundColor"] as? String ?? "#EBF8FF"
|
|
68
|
-
let containerBackgroundColor = themeConfiguration["containerBackgroundColor"] as? String ?? "#FFFFFF"
|
|
69
|
-
let primaryFontColor = themeConfiguration["primaryFontColor"] as? String ?? "#1E3A8A"
|
|
70
|
-
let secondaryFontColor = themeConfiguration["secondaryFontColor"] as? String ?? "#696969"
|
|
71
|
-
let primaryButtonBackgroundColor = themeConfiguration["primaryButtonBackgroundColor"] as? String ?? "#1D4ED8"
|
|
72
|
-
let primaryButtonHoverColor = themeConfiguration["primaryButtonHoverColor"] as? String ?? "#2563EB"
|
|
73
|
-
let primaryButtonFontColor = themeConfiguration["primaryButtonFontColor"] as? String ?? "#FFFFFF"
|
|
74
|
-
let secondaryButtonBackgroundColor = themeConfiguration["secondaryButtonBackgroundColor"] as? String ?? "#FFFFFF"
|
|
75
|
-
let secondaryButtonHoverColor = themeConfiguration["secondaryButtonHoverColor"] as? String ?? "#BFDBFE"
|
|
76
|
-
let secondaryButtonFontColor = themeConfiguration["secondaryButtonFontColor"] as? String ?? "#1E40AF"
|
|
77
|
-
let borderRadius = themeConfiguration["borderRadius"] as? String ?? "8"
|
|
78
|
-
let fontSize = themeConfiguration["fontSize"] as? String ?? "14"
|
|
79
|
-
|
|
80
88
|
let themeConfig = ThemeConfiguration(
|
|
81
|
-
bodyBackgroundColor: bodyBackgroundColor,
|
|
82
|
-
containerBackgroundColor: containerBackgroundColor,
|
|
83
|
-
primaryFontColor: primaryFontColor,
|
|
84
|
-
secondaryFontColor: secondaryFontColor,
|
|
85
|
-
primaryButtonBackgroundColor: primaryButtonBackgroundColor,
|
|
86
|
-
primaryButtonHoverColor: primaryButtonHoverColor,
|
|
87
|
-
primaryButtonFontColor: primaryButtonFontColor,
|
|
88
|
-
secondaryButtonBackgroundColor: secondaryButtonBackgroundColor,
|
|
89
|
-
secondaryButtonHoverColor: secondaryButtonHoverColor,
|
|
90
|
-
secondaryButtonFontColor: secondaryButtonFontColor,
|
|
91
|
-
borderRadius: borderRadius,
|
|
92
|
-
fontSize: fontSize
|
|
89
|
+
bodyBackgroundColor: themeConfiguration["bodyBackgroundColor"] as? String ?? "#EBF8FF",
|
|
90
|
+
containerBackgroundColor: themeConfiguration["containerBackgroundColor"] as? String ?? "#FFFFFF",
|
|
91
|
+
primaryFontColor: themeConfiguration["primaryFontColor"] as? String ?? "#1E3A8A",
|
|
92
|
+
secondaryFontColor: themeConfiguration["secondaryFontColor"] as? String ?? "#696969",
|
|
93
|
+
primaryButtonBackgroundColor: themeConfiguration["primaryButtonBackgroundColor"] as? String ?? "#1D4ED8",
|
|
94
|
+
primaryButtonHoverColor: themeConfiguration["primaryButtonHoverColor"] as? String ?? "#2563EB",
|
|
95
|
+
primaryButtonFontColor: themeConfiguration["primaryButtonFontColor"] as? String ?? "#FFFFFF",
|
|
96
|
+
secondaryButtonBackgroundColor: themeConfiguration["secondaryButtonBackgroundColor"] as? String ?? "#FFFFFF",
|
|
97
|
+
secondaryButtonHoverColor: themeConfiguration["secondaryButtonHoverColor"] as? String ?? "#BFDBFE",
|
|
98
|
+
secondaryButtonFontColor: themeConfiguration["secondaryButtonFontColor"] as? String ?? "#1E40AF",
|
|
99
|
+
borderRadius: themeConfiguration["borderRadius"] as? String ?? "8",
|
|
100
|
+
fontSize: themeConfiguration["fontSize"] as? String ?? "14"
|
|
93
101
|
)
|
|
94
102
|
|
|
103
|
+
let billingInfoData = billinginfo?.data(using: .utf8) ?? Data()
|
|
104
|
+
|
|
95
105
|
let request = Request(
|
|
96
106
|
amount: amountValue,
|
|
97
107
|
billingInfoData: billingInfoData,
|
|
@@ -105,23 +115,22 @@ public class EasyMerchantSdkPlugin: NSObject {
|
|
|
105
115
|
grailPayParams: authenticatedACH ? grailParams : nil
|
|
106
116
|
)
|
|
107
117
|
|
|
118
|
+
self.billingResolver = resolver
|
|
119
|
+
self.billingRejecter = rejecter
|
|
120
|
+
|
|
108
121
|
DispatchQueue.main.async {
|
|
109
122
|
let controller = EasyPayViewController(request: request, delegate: self)
|
|
110
123
|
if let vc = self.viewController {
|
|
111
|
-
vc.present(controller, animated: true)
|
|
112
|
-
resolver("Payment UI presented")
|
|
113
|
-
}
|
|
124
|
+
vc.present(controller, animated: true, completion: nil)
|
|
114
125
|
} else if let rootVC = UIApplication.shared.windows.first(where: { $0.isKeyWindow })?.rootViewController {
|
|
115
|
-
rootVC.present(controller, animated: true)
|
|
116
|
-
resolver("Payment UI presented (fallback)")
|
|
117
|
-
}
|
|
126
|
+
rootVC.present(controller, animated: true, completion: nil)
|
|
118
127
|
} else {
|
|
119
128
|
rejecter("NO_VIEW_CONTROLLER", "No view controller available to present payment screen.", nil)
|
|
129
|
+
self.clearResolvers()
|
|
120
130
|
}
|
|
121
131
|
}
|
|
122
132
|
}
|
|
123
133
|
|
|
124
|
-
|
|
125
134
|
@objc public func configureEnvironment(_ env: String, apiKey: String, apiSecret: String) {
|
|
126
135
|
switch env.lowercased() {
|
|
127
136
|
case "production":
|
|
@@ -131,7 +140,6 @@ public class EasyMerchantSdkPlugin: NSObject {
|
|
|
131
140
|
default:
|
|
132
141
|
EnvironmentConfig.setEnvironment(.staging)
|
|
133
142
|
}
|
|
134
|
-
|
|
135
143
|
EnvironmentConfig.configure(apiKey: apiKey, apiSecret: apiSecret)
|
|
136
144
|
}
|
|
137
145
|
|
|
@@ -141,41 +149,35 @@ public class EasyMerchantSdkPlugin: NSObject {
|
|
|
141
149
|
) {
|
|
142
150
|
resolver("iOS \(UIDevice.current.systemVersion)")
|
|
143
151
|
}
|
|
144
|
-
}
|
|
145
152
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
public static func requiresMainQueueSetup() -> Bool { true }
|
|
153
|
+
private func clearResolvers() {
|
|
154
|
+
self.billingResolver = nil
|
|
155
|
+
self.billingRejecter = nil
|
|
156
|
+
}
|
|
151
157
|
}
|
|
152
158
|
|
|
153
|
-
// MARK: - Payment Delegate
|
|
154
159
|
extension EasyMerchantSdkPlugin: EasyPayViewControllerDelegate {
|
|
155
160
|
public func easyPayController(_ controller: EasyPayViewController, didFinishWith result: Result) {
|
|
156
161
|
DispatchQueue.main.async {
|
|
157
162
|
switch result.type {
|
|
158
163
|
case .cancelled:
|
|
159
|
-
self.
|
|
164
|
+
self.billingResolver?(["status": "cancelled", "message": "User cancelled"])
|
|
160
165
|
case .success:
|
|
161
166
|
if let chargeData = result.chargeData,
|
|
162
167
|
let clientToken = chargeData["clientToken"] as? String {
|
|
163
|
-
self.
|
|
168
|
+
self.billingResolver?(["status": "success", "clientToken": clientToken])
|
|
164
169
|
} else {
|
|
165
|
-
self.
|
|
170
|
+
self.billingResolver?(["status": "success", "chargeData": result.chargeData ?? [:]])
|
|
166
171
|
}
|
|
167
172
|
case .error:
|
|
168
173
|
if let error = result.chargeData?["errorMessage"] as? String {
|
|
169
|
-
self.
|
|
174
|
+
self.billingRejecter?("PAYMENT_ERROR", error, nil)
|
|
170
175
|
} else {
|
|
171
|
-
self.
|
|
176
|
+
self.billingRejecter?("PAYMENT_ERROR", "Unknown error", nil)
|
|
172
177
|
}
|
|
173
178
|
}
|
|
179
|
+
self.clearResolvers()
|
|
180
|
+
controller.dismiss(animated: true)
|
|
174
181
|
}
|
|
175
182
|
}
|
|
176
|
-
|
|
177
|
-
private func sendEvent(name: String, body: [String: Any]) {
|
|
178
|
-
NotificationCenter.default.post(name: NSNotification.Name(name), object: nil, userInfo: body)
|
|
179
|
-
}
|
|
180
183
|
}
|
|
181
|
-
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
//
|
|
2
|
+
// DatePickerHandler.swift
|
|
3
|
+
// EasyPay
|
|
4
|
+
//
|
|
5
|
+
// Created by Mony's Mac on 14/05/25.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import UIKit
|
|
9
|
+
|
|
10
|
+
class DatePickerHandler: NSObject {
|
|
11
|
+
|
|
12
|
+
private let datePicker = UIDatePicker()
|
|
13
|
+
private var targetTextField: UITextField?
|
|
14
|
+
|
|
15
|
+
var onDateSelected: ((Date) -> Void)?
|
|
16
|
+
|
|
17
|
+
init(textField: UITextField, initialDate: Date? = nil) {
|
|
18
|
+
super.init()
|
|
19
|
+
|
|
20
|
+
self.targetTextField = textField
|
|
21
|
+
configureDatePicker()
|
|
22
|
+
|
|
23
|
+
if let date = initialDate {
|
|
24
|
+
datePicker.date = date
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
setupInputView(for: textField)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
private func configureDatePicker() {
|
|
31
|
+
if #available(iOS 14.0, *) {
|
|
32
|
+
datePicker.preferredDatePickerStyle = .inline
|
|
33
|
+
}
|
|
34
|
+
datePicker.datePickerMode = .date
|
|
35
|
+
datePicker.minimumDate = Date()
|
|
36
|
+
datePicker.addTarget(self, action: #selector(dateChanged(_:)), for: .valueChanged)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private func setupInputView(for textField: UITextField) {
|
|
40
|
+
textField.inputView = datePicker
|
|
41
|
+
|
|
42
|
+
let toolbar = UIToolbar()
|
|
43
|
+
toolbar.sizeToFit()
|
|
44
|
+
|
|
45
|
+
let doneButton = UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(doneDateSelection))
|
|
46
|
+
let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
|
|
47
|
+
|
|
48
|
+
toolbar.setItems([space, doneButton], animated: false)
|
|
49
|
+
textField.inputAccessoryView = toolbar
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@objc private func dateChanged(_ sender: UIDatePicker) {
|
|
53
|
+
let formatter = DateFormatter()
|
|
54
|
+
formatter.dateFormat = "dd/MM/yyyy"
|
|
55
|
+
targetTextField?.text = formatter.string(from: sender.date)
|
|
56
|
+
onDateSelected?(sender.date)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
@objc private func doneDateSelection() {
|
|
60
|
+
if targetTextField?.text?.isEmpty ?? true {
|
|
61
|
+
let formatter = DateFormatter()
|
|
62
|
+
formatter.dateFormat = "dd/MM/yyyy"
|
|
63
|
+
let dateText = formatter.string(from: datePicker.date)
|
|
64
|
+
targetTextField?.text = dateText
|
|
65
|
+
onDateSelected?(datePicker.date)
|
|
66
|
+
}
|
|
67
|
+
targetTextField?.resignFirstResponder()
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
}
|
|
71
|
+
|