@jimrising/easymerchantsdk-react-native 1.2.7 → 1.2.9
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/README.md +132 -88
- package/ios/Classes/EasyMerchantSdk.m +73 -0
- package/ios/Classes/EasyMerchantSdk.swift +211 -76
- package/ios/Example/ViewController.swift +122 -122
- package/ios/easymerchantsdk.podspec +1 -1
- package/package.json +1 -1
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.2.
|
|
10
|
+
"@jimrising/easymerchantsdk-react-native": "^1.2.9"
|
|
11
11
|
},
|
|
12
12
|
```
|
|
13
13
|
|
|
@@ -112,135 +112,179 @@ you can call the sdk using below example:
|
|
|
112
112
|
|
|
113
113
|
```javascript
|
|
114
114
|
|
|
115
|
-
import React, {
|
|
116
|
-
import {
|
|
115
|
+
import React, { useEffect, useState } from 'react';
|
|
116
|
+
import {
|
|
117
|
+
View,
|
|
118
|
+
Text,
|
|
119
|
+
Button,
|
|
120
|
+
StyleSheet,
|
|
121
|
+
Platform,
|
|
122
|
+
NativeModules,
|
|
123
|
+
NativeEventEmitter
|
|
124
|
+
} from 'react-native';
|
|
117
125
|
|
|
118
126
|
const { RNEasymerchantsdk, EasyMerchantSdk } = NativeModules;
|
|
127
|
+
const sdkEvents = Platform.OS === 'ios' ? new NativeEventEmitter(EasyMerchantSdk) : null;
|
|
119
128
|
|
|
120
129
|
const App = () => {
|
|
121
130
|
const [version, setVersion] = useState('');
|
|
122
|
-
const [
|
|
123
|
-
|
|
131
|
+
const [response, setResponse] = useState('');
|
|
132
|
+
|
|
133
|
+
useEffect(() => {
|
|
134
|
+
const setup = async () => {
|
|
135
|
+
try {
|
|
136
|
+
if (Platform.OS === 'ios') {
|
|
137
|
+
await EasyMerchantSdk.setViewController();
|
|
138
|
+
EasyMerchantSdk.configureEnvironment(
|
|
139
|
+
'sandbox', // sandbox , staging , production
|
|
140
|
+
'apiKey',
|
|
141
|
+
'apiSecret'
|
|
142
|
+
);
|
|
143
|
+
}
|
|
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
|
+
} catch (err) {
|
|
158
|
+
console.error('Initialization Error:', err.message || err);
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
setup();
|
|
163
|
+
|
|
164
|
+
return () => {
|
|
165
|
+
if (sdkEvents) {
|
|
166
|
+
sdkEvents.removeAllListeners('EasyPaySuccess');
|
|
167
|
+
sdkEvents.removeAllListeners('EasyPayCancelled');
|
|
168
|
+
sdkEvents.removeAllListeners('EasyPayError');
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
}, []);
|
|
124
172
|
|
|
125
173
|
const getPlatformVersion = async () => {
|
|
126
174
|
try {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}
|
|
134
|
-
} catch (error) {
|
|
175
|
+
const ver =
|
|
176
|
+
Platform.OS === 'android'
|
|
177
|
+
? await RNEasymerchantsdk.platformVersion()
|
|
178
|
+
: await EasyMerchantSdk.getPlatformVersion();
|
|
179
|
+
setVersion(ver);
|
|
180
|
+
} catch (err) {
|
|
135
181
|
setVersion('Error fetching version');
|
|
136
182
|
}
|
|
137
183
|
};
|
|
138
184
|
|
|
139
185
|
const handleBilling = async () => {
|
|
140
|
-
const amount = '
|
|
141
|
-
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
186
|
+
const amount = '72';
|
|
187
|
+
|
|
188
|
+
const billingInfo = {
|
|
189
|
+
address: '123 Main Street',
|
|
190
|
+
country: 'USA',
|
|
191
|
+
state: 'California',
|
|
192
|
+
city: 'San Francisco',
|
|
193
|
+
postal_code: '94107',
|
|
194
|
+
additional_info: {
|
|
195
|
+
name: 'John Doe',
|
|
196
|
+
email: 'johndoe@example.com',
|
|
197
|
+
phone_number: '1234567890',
|
|
198
|
+
country_code: '1',
|
|
199
|
+
description: 'Testing SDK Integration'
|
|
200
|
+
}
|
|
148
201
|
};
|
|
149
202
|
|
|
150
|
-
const billingInfoData = {
|
|
151
|
-
address: "Mohali, Punjab",
|
|
152
|
-
country: "India",
|
|
153
|
-
state: "Punjab",
|
|
154
|
-
city: "Anandpur Sahib",
|
|
155
|
-
postal_code: "140118",
|
|
156
|
-
additional_info: additionalInfoRequest
|
|
157
|
-
};
|
|
158
203
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
204
|
+
const theme = {
|
|
205
|
+
bodyBackgroundColor: '#F0FDF4',
|
|
206
|
+
containerBackgroundColor: '#FFFFFF',
|
|
207
|
+
primaryFontColor: '#14532D',
|
|
208
|
+
secondaryFontColor: '#4D7C0F',
|
|
209
|
+
primaryButtonBackgroundColor: '#22C55E',
|
|
210
|
+
primaryButtonHoverColor: '#16A34A',
|
|
211
|
+
primaryButtonFontColor: '#FFFFFF',
|
|
212
|
+
secondaryButtonBackgroundColor: '#DCFCE7',
|
|
213
|
+
secondaryButtonHoverColor: '#BBF7D0',
|
|
214
|
+
secondaryButtonFontColor: '#166534',
|
|
215
|
+
borderRadius: '12',
|
|
216
|
+
fontSize: '16'
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
|
|
173
220
|
|
|
174
221
|
try {
|
|
175
222
|
if (Platform.OS === 'android') {
|
|
176
|
-
const
|
|
177
|
-
|
|
178
|
-
} else
|
|
179
|
-
|
|
223
|
+
const result = await RNEasymerchantsdk.billing(amount, null);
|
|
224
|
+
setResponse(`✅ Android Payment Success: ${result}`);
|
|
225
|
+
} else {
|
|
226
|
+
await EasyMerchantSdk.billing(
|
|
180
227
|
amount,
|
|
181
|
-
JSON.stringify(
|
|
182
|
-
['Card', 'Bank', 'Crypto'],
|
|
183
|
-
|
|
184
|
-
false,
|
|
185
|
-
false,
|
|
186
|
-
false
|
|
228
|
+
JSON.stringify(billingInfo),
|
|
229
|
+
['Card', 'Bank', 'Crypto'],
|
|
230
|
+
theme,
|
|
231
|
+
false,
|
|
232
|
+
false,
|
|
233
|
+
false
|
|
187
234
|
);
|
|
188
|
-
|
|
235
|
+
setResponse('🔁 Billing started on iOS. Awaiting response...');
|
|
189
236
|
}
|
|
190
237
|
} catch (error) {
|
|
191
|
-
|
|
192
|
-
setPaymentResponse(`Payment Error: ${error}`);
|
|
193
|
-
} else if (Platform.OS === 'ios') {
|
|
194
|
-
setBillingResult(`Billing Error: ${error.message || error}`);
|
|
195
|
-
}
|
|
238
|
+
setResponse(`❌ Billing Error: ${error.message || error}`);
|
|
196
239
|
}
|
|
197
240
|
};
|
|
198
241
|
|
|
199
|
-
useEffect(() => {
|
|
200
|
-
if (Platform.OS === 'ios') {
|
|
201
|
-
const initializeViewController = async () => {
|
|
202
|
-
if (EasyMerchantSdk && EasyMerchantSdk.setViewController) {
|
|
203
|
-
try {
|
|
204
|
-
await EasyMerchantSdk.setViewController();
|
|
205
|
-
console.log('ViewController set successfully');
|
|
206
|
-
} catch (error) {
|
|
207
|
-
console.error('Error setting ViewController:', error.message || error);
|
|
208
|
-
}
|
|
209
|
-
} else {
|
|
210
|
-
console.warn('EasyMerchantSdk.setViewController is not available');
|
|
211
|
-
}
|
|
212
|
-
};
|
|
213
|
-
initializeViewController();
|
|
214
|
-
}
|
|
215
|
-
}, []);
|
|
216
|
-
|
|
217
242
|
return (
|
|
218
243
|
<View style={styles.container}>
|
|
219
|
-
<Text
|
|
244
|
+
<Text style={styles.title}>EasyMerchant SDK</Text>
|
|
245
|
+
<Text style={styles.version}>Platform Version: {version}</Text>
|
|
220
246
|
<Button title="Get Platform Version" onPress={getPlatformVersion} />
|
|
221
|
-
<
|
|
222
|
-
|
|
223
|
-
|
|
247
|
+
<View style={styles.space} />
|
|
248
|
+
<Button title="Start Billing" onPress={handleBilling} />
|
|
249
|
+
<View style={styles.space} />
|
|
250
|
+
{response ? <Text style={styles.response}>{response}</Text> : null}
|
|
224
251
|
</View>
|
|
225
252
|
);
|
|
226
253
|
};
|
|
227
254
|
|
|
255
|
+
export default App;
|
|
256
|
+
|
|
228
257
|
const styles = StyleSheet.create({
|
|
229
258
|
container: {
|
|
230
259
|
flex: 1,
|
|
231
|
-
|
|
260
|
+
backgroundColor: '#F9FAFB',
|
|
232
261
|
alignItems: 'center',
|
|
233
|
-
|
|
262
|
+
justifyContent: 'center',
|
|
263
|
+
padding: 24
|
|
264
|
+
},
|
|
265
|
+
title: {
|
|
266
|
+
fontSize: 20,
|
|
267
|
+
fontWeight: 'bold',
|
|
268
|
+
marginBottom: 16
|
|
269
|
+
},
|
|
270
|
+
version: {
|
|
271
|
+
fontSize: 14,
|
|
272
|
+
marginBottom: 8
|
|
273
|
+
},
|
|
274
|
+
response: {
|
|
275
|
+
marginTop: 20,
|
|
276
|
+
paddingHorizontal: 12,
|
|
277
|
+
textAlign: 'center',
|
|
278
|
+
fontSize: 14,
|
|
279
|
+
color: '#333'
|
|
234
280
|
},
|
|
281
|
+
space: {
|
|
282
|
+
height: 16
|
|
283
|
+
}
|
|
235
284
|
});
|
|
236
285
|
|
|
237
|
-
export default App;
|
|
238
|
-
|
|
239
286
|
```
|
|
240
287
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
288
|
You can send `null` if billing info not available.
|
|
245
289
|
|
|
246
290
|
|
|
@@ -8,6 +8,15 @@
|
|
|
8
8
|
|
|
9
9
|
RCT_EXPORT_MODULE()
|
|
10
10
|
|
|
11
|
+
|
|
12
|
+
RCT_EXPORT_METHOD(configureEnvironment:(NSString *)env
|
|
13
|
+
apiKey:(NSString *)apiKey
|
|
14
|
+
apiSecret:(NSString *)apiSecret)
|
|
15
|
+
{
|
|
16
|
+
EasyMerchantSdkPlugin *sdkPlugin = [[EasyMerchantSdkPlugin alloc] init];
|
|
17
|
+
[sdkPlugin configureEnvironment:env apiKey:apiKey apiSecret:apiSecret];
|
|
18
|
+
}
|
|
19
|
+
|
|
11
20
|
RCT_EXPORT_METHOD(
|
|
12
21
|
billing:(NSString *)amount
|
|
13
22
|
billingInfo:(NSString *)billingInfo
|
|
@@ -50,3 +59,67 @@ RCT_EXPORT_METHOD(getPlatformVersion:(RCTPromiseResolveBlock)resolve
|
|
|
50
59
|
}
|
|
51
60
|
|
|
52
61
|
@end
|
|
62
|
+
|
|
63
|
+
//
|
|
64
|
+
//#import "EasyMerchantSdk.h"
|
|
65
|
+
//#import <React/RCTLog.h>
|
|
66
|
+
//#import <React/RCTBridgeModule.h>
|
|
67
|
+
////#import <easymerchantsdk/easymerchantsdk-Swift.h>
|
|
68
|
+
//#import <easymerchantsdk-Swift.h>
|
|
69
|
+
//
|
|
70
|
+
//
|
|
71
|
+
//@implementation EasyMerchantSdk
|
|
72
|
+
//
|
|
73
|
+
//RCT_EXPORT_MODULE()
|
|
74
|
+
//
|
|
75
|
+
//RCT_EXPORT_METHOD(
|
|
76
|
+
// billing:(NSString *)amount
|
|
77
|
+
// billingInfo:(NSString *)billingInfo
|
|
78
|
+
// paymentMethods:(NSArray *)paymentMethods
|
|
79
|
+
// themeConfiguration:(NSDictionary *)themeConfiguration
|
|
80
|
+
// tokenOnly:(BOOL)tokenOnly
|
|
81
|
+
// saveCard:(BOOL)saveCard
|
|
82
|
+
// saveAccount:(BOOL)saveAccount
|
|
83
|
+
// resolver:(RCTPromiseResolveBlock)resolve
|
|
84
|
+
// rejecter:(RCTPromiseRejectBlock)reject
|
|
85
|
+
//)
|
|
86
|
+
//{
|
|
87
|
+
// EasyMerchantSdkPlugin *sdkPlugin = [[EasyMerchantSdkPlugin alloc] init];
|
|
88
|
+
//
|
|
89
|
+
// [sdkPlugin billing:amount
|
|
90
|
+
// billinginfo:billingInfo
|
|
91
|
+
// paymentMethods:paymentMethods
|
|
92
|
+
// themeConfiguration:themeConfiguration
|
|
93
|
+
// tokenOnly:tokenOnly
|
|
94
|
+
// saveCard:saveCard
|
|
95
|
+
// saveAccount:saveAccount
|
|
96
|
+
// resolver:resolve
|
|
97
|
+
// rejecter:reject];
|
|
98
|
+
//}
|
|
99
|
+
//
|
|
100
|
+
//RCT_EXPORT_METHOD(setViewController:(RCTPromiseResolveBlock)resolve
|
|
101
|
+
// rejecter:(RCTPromiseRejectBlock)reject)
|
|
102
|
+
//{
|
|
103
|
+
// UIViewController *rootViewController = [UIApplication sharedApplication].delegate.window.rootViewController;
|
|
104
|
+
// EasyMerchantSdkPlugin *sdkPlugin = [[EasyMerchantSdkPlugin alloc] init];
|
|
105
|
+
// [sdkPlugin setViewController:rootViewController];
|
|
106
|
+
// resolve(@"ViewController set successfully");
|
|
107
|
+
//}
|
|
108
|
+
//
|
|
109
|
+
//RCT_EXPORT_METHOD(getPlatformVersion:(RCTPromiseResolveBlock)resolve
|
|
110
|
+
// rejecter:(RCTPromiseRejectBlock)reject)
|
|
111
|
+
//{
|
|
112
|
+
// NSString *platformVersion = [NSString stringWithFormat:@"iOS %@", [[UIDevice currentDevice] systemVersion]];
|
|
113
|
+
// resolve(platformVersion);
|
|
114
|
+
//}
|
|
115
|
+
//
|
|
116
|
+
//RCT_EXPORT_METHOD(configureEnvironment:(NSString *)env
|
|
117
|
+
// apiKey:(NSString *)apiKey
|
|
118
|
+
// apiSecret:(NSString *)apiSecret)
|
|
119
|
+
//{
|
|
120
|
+
// EasyMerchantSdkPlugin *sdkPlugin = [[EasyMerchantSdkPlugin alloc] init];
|
|
121
|
+
// [sdkPlugin configureEnvironment:env apiKey:apiKey apiSecret:apiSecret];
|
|
122
|
+
//}
|
|
123
|
+
//
|
|
124
|
+
//
|
|
125
|
+
//@end
|
|
@@ -1,3 +1,130 @@
|
|
|
1
|
+
//
|
|
2
|
+
//import Foundation
|
|
3
|
+
//import UIKit
|
|
4
|
+
//import React
|
|
5
|
+
//
|
|
6
|
+
//@objc(EasyMerchantSdkPlugin)
|
|
7
|
+
//public class EasyMerchantSdkPlugin: NSObject {
|
|
8
|
+
//
|
|
9
|
+
// private var viewController: UIViewController?
|
|
10
|
+
// private let viewControllerQueue = DispatchQueue(label: "com.easymerchantsdk.viewController")
|
|
11
|
+
//
|
|
12
|
+
// @objc public func setViewController(_ viewController: UIViewController) {
|
|
13
|
+
// viewControllerQueue.sync {
|
|
14
|
+
// self.viewController = viewController
|
|
15
|
+
// }
|
|
16
|
+
// print("ViewController set: \(String(describing: self.viewController))")
|
|
17
|
+
// }
|
|
18
|
+
//
|
|
19
|
+
//
|
|
20
|
+
//@objc public func billing(
|
|
21
|
+
// _ amount: String,
|
|
22
|
+
// billinginfo: String,
|
|
23
|
+
// paymentMethods: [String],
|
|
24
|
+
// themeConfiguration: [String: Any],
|
|
25
|
+
// tokenOnly: Bool,
|
|
26
|
+
// saveCard: Bool,
|
|
27
|
+
// saveAccount: Bool,
|
|
28
|
+
// resolver: @escaping RCTPromiseResolveBlock,
|
|
29
|
+
// rejecter: @escaping RCTPromiseRejectBlock
|
|
30
|
+
//) {
|
|
31
|
+
// guard let amountValue = Double(amount), amountValue > 0 else {
|
|
32
|
+
// rejecter("INVALID_AMOUNT", "Amount must be a positive number", nil)
|
|
33
|
+
// return
|
|
34
|
+
// }
|
|
35
|
+
//
|
|
36
|
+
// guard !billinginfo.isEmpty,
|
|
37
|
+
// let billingInfoData = billinginfo.data(using: .utf8),
|
|
38
|
+
// let _ = try? JSONSerialization.jsonObject(with: billingInfoData, options: []) as? [String: Any] else {
|
|
39
|
+
// rejecter("INVALID_BILLING_INFO", "Billing info must be valid JSON", nil)
|
|
40
|
+
// return
|
|
41
|
+
// }
|
|
42
|
+
//
|
|
43
|
+
// let methods: [PaymentMethod] = paymentMethods.compactMap {
|
|
44
|
+
// switch $0.lowercased() {
|
|
45
|
+
// case "card": return .Card
|
|
46
|
+
// case "bank": return .Bank
|
|
47
|
+
// case "crypto": return .Crypto
|
|
48
|
+
// default: return nil
|
|
49
|
+
// }
|
|
50
|
+
// }
|
|
51
|
+
//
|
|
52
|
+
// let request = Request(
|
|
53
|
+
// amount: amountValue,
|
|
54
|
+
// billingInfoData: billingInfoData,
|
|
55
|
+
// paymentMethods: methods,
|
|
56
|
+
// themeConfiguration: themeConfiguration,
|
|
57
|
+
// tokenOnly: tokenOnly,
|
|
58
|
+
// saveCard: saveCard,
|
|
59
|
+
// saveAccount: saveAccount
|
|
60
|
+
// )
|
|
61
|
+
//
|
|
62
|
+
// let paymentController = EasyPayViewController(request: request, delegate: self)
|
|
63
|
+
//
|
|
64
|
+
// DispatchQueue.main.async {
|
|
65
|
+
// if let rootViewController = UIApplication.shared.windows.first(where: { $0.isKeyWindow })?.rootViewController {
|
|
66
|
+
// rootViewController.present(paymentController, animated: true) {
|
|
67
|
+
// resolver("Payment process started for amount \(amount)")
|
|
68
|
+
// }
|
|
69
|
+
// } else {
|
|
70
|
+
// rejecter("VIEW_CONTROLLER_NOT_FOUND", "Root ViewController not found", nil)
|
|
71
|
+
// }
|
|
72
|
+
// }
|
|
73
|
+
//}
|
|
74
|
+
//
|
|
75
|
+
// @objc public func getPlatformVersion(
|
|
76
|
+
// _ resolver: @escaping RCTPromiseResolveBlock,
|
|
77
|
+
// rejecter: @escaping RCTPromiseRejectBlock
|
|
78
|
+
// ) {
|
|
79
|
+
// resolver("iOS \(UIDevice.current.systemVersion)")
|
|
80
|
+
// }
|
|
81
|
+
//}
|
|
82
|
+
//
|
|
83
|
+
//
|
|
84
|
+
//
|
|
85
|
+
//
|
|
86
|
+
//
|
|
87
|
+
//
|
|
88
|
+
//
|
|
89
|
+
//@objc(EasyMerchantSdkPlugin)
|
|
90
|
+
//extension EasyMerchantSdkPlugin: RCTBridgeModule {
|
|
91
|
+
// public static func moduleName() -> String {
|
|
92
|
+
// return "EasyMerchantSdk"
|
|
93
|
+
// }
|
|
94
|
+
//
|
|
95
|
+
// public static func requiresMainQueueSetup() -> Bool {
|
|
96
|
+
// return true
|
|
97
|
+
// }
|
|
98
|
+
//}
|
|
99
|
+
//
|
|
100
|
+
//extension EasyMerchantSdkPlugin: EasyPayViewControllerDelegate {
|
|
101
|
+
// public func easyPayController(_ controller: EasyPayViewController, didFinishWith result: Result) {
|
|
102
|
+
// DispatchQueue.main.async {
|
|
103
|
+
// switch result.type {
|
|
104
|
+
// case .cancelled:
|
|
105
|
+
// print("Payment Cancelled by user.")
|
|
106
|
+
// case .success:
|
|
107
|
+
// if let chargeData = result.chargeData {
|
|
108
|
+
// self.handleSuccess(with: chargeData)
|
|
109
|
+
// } else {
|
|
110
|
+
// print("Payment succeeded but no charge data received.")
|
|
111
|
+
// }
|
|
112
|
+
// case .error:
|
|
113
|
+
// if let chargeData = result.chargeData,
|
|
114
|
+
// let errorMessage = chargeData["errorMessage"] as? String {
|
|
115
|
+
// print("Payment Error: \(errorMessage)")
|
|
116
|
+
// } else {
|
|
117
|
+
// print("Unknown Payment Error.")
|
|
118
|
+
// }
|
|
119
|
+
// }
|
|
120
|
+
// }
|
|
121
|
+
// }
|
|
122
|
+
//
|
|
123
|
+
// private func handleSuccess(with chargeData: [String: Any]) {
|
|
124
|
+
// print("Payment Successful. Charge Data: \(chargeData)")
|
|
125
|
+
// }
|
|
126
|
+
//}
|
|
127
|
+
|
|
1
128
|
import Foundation
|
|
2
129
|
import UIKit
|
|
3
130
|
import React
|
|
@@ -12,115 +139,123 @@ public class EasyMerchantSdkPlugin: NSObject {
|
|
|
12
139
|
viewControllerQueue.sync {
|
|
13
140
|
self.viewController = viewController
|
|
14
141
|
}
|
|
15
|
-
|
|
16
|
-
}
|
|
142
|
+
print("ViewController set: \(String(describing: self.viewController))")
|
|
17
143
|
|
|
18
|
-
|
|
19
|
-
@objc public func billing(
|
|
20
|
-
_ amount: String,
|
|
21
|
-
billinginfo: String,
|
|
22
|
-
paymentMethods: [String],
|
|
23
|
-
themeConfiguration: [String: Any],
|
|
24
|
-
tokenOnly: Bool,
|
|
25
|
-
saveCard: Bool,
|
|
26
|
-
saveAccount: Bool,
|
|
27
|
-
resolver: @escaping RCTPromiseResolveBlock,
|
|
28
|
-
rejecter: @escaping RCTPromiseRejectBlock
|
|
29
|
-
) {
|
|
30
|
-
guard let amountValue = Double(amount), amountValue > 0 else {
|
|
31
|
-
rejecter("INVALID_AMOUNT", "Amount must be a positive number", nil)
|
|
32
|
-
return
|
|
33
144
|
}
|
|
34
145
|
|
|
35
|
-
guard !billinginfo.isEmpty,
|
|
36
|
-
let billingInfoData = billinginfo.data(using: .utf8),
|
|
37
|
-
let _ = try? JSONSerialization.jsonObject(with: billingInfoData, options: []) as? [String: Any] else {
|
|
38
|
-
rejecter("INVALID_BILLING_INFO", "Billing info must be valid JSON", nil)
|
|
39
|
-
return
|
|
40
|
-
}
|
|
41
146
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
147
|
+
|
|
148
|
+
@objc public func billing(
|
|
149
|
+
_ amount: String,
|
|
150
|
+
billinginfo: String,
|
|
151
|
+
paymentMethods: [String],
|
|
152
|
+
themeConfiguration: [String: Any],
|
|
153
|
+
tokenOnly: Bool,
|
|
154
|
+
saveCard: Bool,
|
|
155
|
+
saveAccount: Bool,
|
|
156
|
+
resolver: @escaping RCTPromiseResolveBlock,
|
|
157
|
+
rejecter: @escaping RCTPromiseRejectBlock
|
|
158
|
+
) {
|
|
159
|
+
guard let amountValue = Double(amount), amountValue > 0 else {
|
|
160
|
+
rejecter("INVALID_AMOUNT", "Amount must be a positive number", nil)
|
|
161
|
+
return
|
|
48
162
|
}
|
|
49
|
-
}
|
|
50
163
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
themeConfiguration: themeConfiguration,
|
|
56
|
-
tokenOnly: tokenOnly,
|
|
57
|
-
saveCard: saveCard,
|
|
58
|
-
saveAccount: saveAccount
|
|
59
|
-
)
|
|
60
|
-
|
|
61
|
-
let paymentController = EasyPayViewController(request: request, delegate: self)
|
|
62
|
-
|
|
63
|
-
DispatchQueue.main.async {
|
|
64
|
-
if let rootViewController = UIApplication.shared.windows.first(where: { $0.isKeyWindow })?.rootViewController {
|
|
65
|
-
rootViewController.present(paymentController, animated: true) {
|
|
66
|
-
resolver("Payment process started for amount \(amount)")
|
|
67
|
-
}
|
|
68
|
-
} else {
|
|
69
|
-
rejecter("VIEW_CONTROLLER_NOT_FOUND", "Root ViewController not found", nil)
|
|
164
|
+
guard let billingInfoData = billinginfo.data(using: .utf8),
|
|
165
|
+
let _ = try? JSONSerialization.jsonObject(with: billingInfoData, options: []) else {
|
|
166
|
+
rejecter("INVALID_BILLING_INFO", "Billing info must be valid JSON", nil)
|
|
167
|
+
return
|
|
70
168
|
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
169
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
170
|
+
let methods: [PaymentMethod] = paymentMethods.compactMap {
|
|
171
|
+
switch $0.lowercased() {
|
|
172
|
+
case "card": return .Card
|
|
173
|
+
case "bank": return .Bank
|
|
174
|
+
case "crypto": return .Crypto
|
|
175
|
+
default: return nil
|
|
176
|
+
}
|
|
177
|
+
}
|
|
81
178
|
|
|
179
|
+
let request = Request(
|
|
180
|
+
amount: amountValue,
|
|
181
|
+
billingInfoData: billingInfoData,
|
|
182
|
+
paymentMethods: methods,
|
|
183
|
+
themeConfiguration: themeConfiguration,
|
|
184
|
+
tokenOnly: tokenOnly,
|
|
185
|
+
saveCard: saveCard,
|
|
186
|
+
saveAccount: saveAccount
|
|
187
|
+
)
|
|
82
188
|
|
|
189
|
+
DispatchQueue.main.async {
|
|
190
|
+
let controller = EasyPayViewController(request: request, delegate: self)
|
|
191
|
+
if let vc = self.viewController {
|
|
192
|
+
vc.present(controller, animated: true) {
|
|
193
|
+
resolver("Payment UI presented")
|
|
194
|
+
}
|
|
195
|
+
} else if let rootVC = UIApplication.shared.windows.first(where: { $0.isKeyWindow })?.rootViewController {
|
|
196
|
+
rootVC.present(controller, animated: true) {
|
|
197
|
+
resolver("Payment UI presented (fallback)")
|
|
198
|
+
}
|
|
199
|
+
} else {
|
|
200
|
+
rejecter("NO_VIEW_CONTROLLER", "No view controller available to present payment screen.", nil)
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
83
204
|
|
|
84
205
|
|
|
206
|
+
@objc public func configureEnvironment(_ env: String, apiKey: String, apiSecret: String) {
|
|
207
|
+
switch env.lowercased() {
|
|
208
|
+
case "production":
|
|
209
|
+
EnvironmentConfig.setEnvironment(.production)
|
|
210
|
+
case "sandbox":
|
|
211
|
+
EnvironmentConfig.setEnvironment(.sandbox)
|
|
212
|
+
default:
|
|
213
|
+
EnvironmentConfig.setEnvironment(.staging)
|
|
214
|
+
}
|
|
85
215
|
|
|
216
|
+
EnvironmentConfig.configure(apiKey: apiKey, apiSecret: apiSecret)
|
|
217
|
+
}
|
|
86
218
|
|
|
219
|
+
@objc public func getPlatformVersion(
|
|
220
|
+
_ resolver: @escaping RCTPromiseResolveBlock,
|
|
221
|
+
rejecter: @escaping RCTPromiseRejectBlock
|
|
222
|
+
) {
|
|
223
|
+
resolver("iOS \(UIDevice.current.systemVersion)")
|
|
224
|
+
}
|
|
225
|
+
}
|
|
87
226
|
|
|
227
|
+
// MARK: - React Native Bridge
|
|
88
228
|
@objc(EasyMerchantSdkPlugin)
|
|
89
229
|
extension EasyMerchantSdkPlugin: RCTBridgeModule {
|
|
90
|
-
public static func moduleName() -> String {
|
|
91
|
-
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
public static func requiresMainQueueSetup() -> Bool {
|
|
95
|
-
return true
|
|
96
|
-
}
|
|
230
|
+
public static func moduleName() -> String { "EasyMerchantSdk" }
|
|
231
|
+
public static func requiresMainQueueSetup() -> Bool { true }
|
|
97
232
|
}
|
|
98
233
|
|
|
234
|
+
// MARK: - Payment Delegate
|
|
99
235
|
extension EasyMerchantSdkPlugin: EasyPayViewControllerDelegate {
|
|
100
236
|
public func easyPayController(_ controller: EasyPayViewController, didFinishWith result: Result) {
|
|
101
237
|
DispatchQueue.main.async {
|
|
102
238
|
switch result.type {
|
|
103
239
|
case .cancelled:
|
|
104
|
-
|
|
240
|
+
self.sendEvent(name: "EasyPayCancelled", body: ["message": "User cancelled"])
|
|
105
241
|
case .success:
|
|
106
|
-
if let chargeData = result.chargeData
|
|
107
|
-
|
|
242
|
+
if let chargeData = result.chargeData,
|
|
243
|
+
let clientToken = chargeData["clientToken"] as? String {
|
|
244
|
+
self.sendEvent(name: "EasyPaySuccess", body: ["clientToken": clientToken])
|
|
108
245
|
} else {
|
|
109
|
-
|
|
246
|
+
self.sendEvent(name: "EasyPaySuccess", body: ["chargeData": result.chargeData ?? [:]])
|
|
110
247
|
}
|
|
111
248
|
case .error:
|
|
112
|
-
if let
|
|
113
|
-
|
|
114
|
-
print("Payment Error: \(errorMessage)")
|
|
249
|
+
if let error = result.chargeData?["errorMessage"] as? String {
|
|
250
|
+
self.sendEvent(name: "EasyPayError", body: ["error": error])
|
|
115
251
|
} else {
|
|
116
|
-
|
|
252
|
+
self.sendEvent(name: "EasyPayError", body: ["error": "Unknown error"])
|
|
117
253
|
}
|
|
118
254
|
}
|
|
119
255
|
}
|
|
120
256
|
}
|
|
121
257
|
|
|
122
|
-
private func
|
|
123
|
-
|
|
258
|
+
private func sendEvent(name: String, body: [String: Any]) {
|
|
259
|
+
NotificationCenter.default.post(name: NSNotification.Name(name), object: nil, userInfo: body)
|
|
124
260
|
}
|
|
125
261
|
}
|
|
126
|
-
|
|
@@ -1,124 +1,124 @@
|
|
|
1
|
-
import UIKit
|
|
2
|
-
|
|
3
|
-
class ViewController: UIViewController {
|
|
4
|
-
|
|
5
|
-
@IBOutlet weak var lblResponseShow: UILabel!
|
|
6
|
-
@IBOutlet private var payButton: UIButton!
|
|
7
|
-
|
|
8
|
-
override func viewDidLoad() {
|
|
9
|
-
super.viewDidLoad()
|
|
10
|
-
|
|
11
|
-
/// Developer selects the environment
|
|
12
|
-
EnvironmentConfig.setEnvironment(.staging) /// Or .sandbox, .production
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
@IBAction private func payAction() {
|
|
1
|
+
//import UIKit
|
|
2
|
+
//
|
|
3
|
+
//class ViewController: UIViewController {
|
|
4
|
+
//
|
|
5
|
+
// @IBOutlet weak var lblResponseShow: UILabel!
|
|
6
|
+
// @IBOutlet private var payButton: UIButton!
|
|
7
|
+
//
|
|
8
|
+
// override func viewDidLoad() {
|
|
9
|
+
// super.viewDidLoad()
|
|
10
|
+
//
|
|
11
|
+
// /// Developer selects the environment
|
|
12
|
+
// EnvironmentConfig.setEnvironment(.staging) /// Or .sandbox, .production
|
|
13
|
+
// }
|
|
14
|
+
//
|
|
15
|
+
// @IBAction private func payAction() {
|
|
16
|
+
//// let apiKey = "mobilesdk1980IUuCzwWl"
|
|
17
|
+
//// let apiSecret = "mobilesdk1980LVHnN0Oh"
|
|
18
|
+
//
|
|
16
19
|
// let apiKey = "mobilesdk1980IUuCzwWl"
|
|
17
20
|
// let apiSecret = "mobilesdk1980LVHnN0Oh"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
lblResponseShow.isHidden = false
|
|
112
|
-
lblResponseShow.text = "
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
lblResponseShow.text = "Received Charge Data: \(chargeData)"
|
|
123
|
-
}
|
|
124
|
-
}
|
|
21
|
+
//
|
|
22
|
+
// EnvironmentConfig.configure(apiKey: apiKey, apiSecret: apiSecret)
|
|
23
|
+
//
|
|
24
|
+
// /// Theme configuration dictionary
|
|
25
|
+
// let themeConfiguration: [String: Any] = [
|
|
26
|
+
// "bodyBackgroundColor": "#EEEFF2",
|
|
27
|
+
// "containerBackgroundColor": "#FFFF00",
|
|
28
|
+
// "primaryFontColor": "#000000",
|
|
29
|
+
// "secondaryFontColor": "#666666",
|
|
30
|
+
// "primaryButtonBackgroundColor": "#1757D9",
|
|
31
|
+
// "primaryButtonHoverColor": "#3A70DF",
|
|
32
|
+
// "primaryButtonFontColor": "#FFFFFF",
|
|
33
|
+
// "secondaryButtonBackgroundColor": "#FFFFFF",
|
|
34
|
+
// "secondaryButtonHoverColor": "#1757D9",
|
|
35
|
+
// "secondaryButtonFontColor": "#1757D9",
|
|
36
|
+
// "borderRadius": "8",
|
|
37
|
+
// "fontSize": "16"
|
|
38
|
+
// ]
|
|
39
|
+
//
|
|
40
|
+
// let additionalInfoRequest = [
|
|
41
|
+
// "name": "Test User",
|
|
42
|
+
// "email": "test@gmail.com",
|
|
43
|
+
// "phone_number": "9465351125",
|
|
44
|
+
// "country_code": "91",
|
|
45
|
+
// "description": "Test"
|
|
46
|
+
// ]
|
|
47
|
+
//
|
|
48
|
+
// let json: [String: Any] = [
|
|
49
|
+
// "address": "Mohali, Punjab",
|
|
50
|
+
// "country": "India",
|
|
51
|
+
// "state": "Punjab",
|
|
52
|
+
// "city": "Anandpur Sahib",
|
|
53
|
+
// "postal_code": "140118",
|
|
54
|
+
// "additional_info": additionalInfoRequest
|
|
55
|
+
// ]
|
|
56
|
+
//
|
|
57
|
+
// guard let jsonData = try? JSONSerialization.data(withJSONObject: json, options: []) else {
|
|
58
|
+
// print("Failed to serialize JSON")
|
|
59
|
+
// return
|
|
60
|
+
// }
|
|
61
|
+
//
|
|
62
|
+
// let request = Request(
|
|
63
|
+
// amount: 99,
|
|
64
|
+
// billingInfoData: jsonData,
|
|
65
|
+
// paymentMethods: [.Card, .Bank, .Crypto],
|
|
66
|
+
// themeConfiguration: themeConfiguration,
|
|
67
|
+
// tokenOnly: false,
|
|
68
|
+
// saveCard: false,
|
|
69
|
+
// saveAccount: false
|
|
70
|
+
// // submitButtonText: "Submit"
|
|
71
|
+
// )
|
|
72
|
+
//
|
|
73
|
+
// // If tokenOnly is true, wait for the clientToken and show it in lblResponseShow
|
|
74
|
+
// if request.tokenOnly == true {
|
|
75
|
+
// NotificationCenter.default.addObserver(forName: NSNotification.Name("ClientTokenReceived"), object: nil, queue: .main) { notification in
|
|
76
|
+
// if let clientToken = notification.object as? String {
|
|
77
|
+
// self.lblResponseShow.isHidden = false
|
|
78
|
+
// self.lblResponseShow.text = "Client Token: \(clientToken)"
|
|
79
|
+
// }
|
|
80
|
+
// }
|
|
81
|
+
// } else {
|
|
82
|
+
// let controller = EasyPayViewController(request: request, delegate: self)
|
|
83
|
+
// self.present(controller, animated: true)
|
|
84
|
+
// }
|
|
85
|
+
//
|
|
86
|
+
// }
|
|
87
|
+
//
|
|
88
|
+
//}
|
|
89
|
+
//
|
|
90
|
+
//extension ViewController: EasyPayViewControllerDelegate {
|
|
91
|
+
//
|
|
92
|
+
// func easyPayController(_ controller: EasyPayViewController, didFinishWith result: Result) {
|
|
93
|
+
// switch result.type {
|
|
94
|
+
// case .cancelled:
|
|
95
|
+
// print("Cancelled")
|
|
96
|
+
// case .success:
|
|
97
|
+
// // if let chargeData = result.chargeData {
|
|
98
|
+
// // handleSuccess(with: chargeData)
|
|
99
|
+
// // }
|
|
100
|
+
// if let chargeData = result.chargeData {
|
|
101
|
+
// if let clientToken = chargeData["clientToken"] as? String {
|
|
102
|
+
// // If tokenOnly was true, display the token
|
|
103
|
+
// lblResponseShow.isHidden = false
|
|
104
|
+
// lblResponseShow.text = "Client Token: \(clientToken)"
|
|
105
|
+
// } else {
|
|
106
|
+
// handleSuccess(with: chargeData)
|
|
107
|
+
// }
|
|
108
|
+
// }
|
|
109
|
+
// case .error:
|
|
110
|
+
// if let chargeData = result.chargeData, let errorMessage = chargeData["errorMessage"] as? String {
|
|
111
|
+
// lblResponseShow.isHidden = false
|
|
112
|
+
// lblResponseShow.text = "Error: \(errorMessage)"
|
|
113
|
+
// } else {
|
|
114
|
+
// lblResponseShow.isHidden = false
|
|
115
|
+
// lblResponseShow.text = "An unknown error occurred."
|
|
116
|
+
// }
|
|
117
|
+
// }
|
|
118
|
+
// }
|
|
119
|
+
//
|
|
120
|
+
// private func handleSuccess(with chargeData: [String: Any]) {
|
|
121
|
+
// lblResponseShow.isHidden = false
|
|
122
|
+
// lblResponseShow.text = "Received Charge Data: \(chargeData)"
|
|
123
|
+
// }
|
|
124
|
+
//}
|