@jimrising/easymerchantsdk-react-native 1.2.6 → 1.2.8
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 +130 -85
- package/ios/Classes/EasyMerchantSdk.m +75 -2
- package/ios/Classes/EasyMerchantSdk.swift +211 -76
- package/ios/Example/ViewController.swift +124 -121
- 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.8"
|
|
11
11
|
},
|
|
12
12
|
```
|
|
13
13
|
|
|
@@ -112,130 +112,175 @@ 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
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
186
|
+
const amount = '72';
|
|
187
|
+
const billingInfo = {
|
|
188
|
+
address: 'Chandigarh, Punjab',
|
|
189
|
+
country: 'India',
|
|
190
|
+
state: 'Punjab',
|
|
191
|
+
city: 'Hoshiarpur',
|
|
192
|
+
postal_code: '144520',
|
|
193
|
+
additional_info: {
|
|
194
|
+
name: 'SDK User',
|
|
195
|
+
email: 'davinder@gmail.com',
|
|
196
|
+
phone_number: '7888821587',
|
|
197
|
+
country_code: '91',
|
|
198
|
+
description: 'SDK Test'
|
|
199
|
+
}
|
|
148
200
|
};
|
|
149
201
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
202
|
+
const theme = {
|
|
203
|
+
bodyBackgroundColor: '#F0FDF4',
|
|
204
|
+
containerBackgroundColor: '#FFFFFF',
|
|
205
|
+
primaryFontColor: '#14532D',
|
|
206
|
+
secondaryFontColor: '#4D7C0F',
|
|
207
|
+
primaryButtonBackgroundColor: '#22C55E',
|
|
208
|
+
primaryButtonHoverColor: '#16A34A',
|
|
209
|
+
primaryButtonFontColor: '#FFFFFF',
|
|
210
|
+
secondaryButtonBackgroundColor: '#DCFCE7',
|
|
211
|
+
secondaryButtonHoverColor: '#BBF7D0',
|
|
212
|
+
secondaryButtonFontColor: '#166534',
|
|
213
|
+
borderRadius: '12',
|
|
214
|
+
fontSize: '16'
|
|
215
|
+
};
|
|
216
|
+
|
|
158
217
|
|
|
159
|
-
const themeConfiguration = {
|
|
160
|
-
bodyBackgroundColor: "#EEEFF2",
|
|
161
|
-
containerBackgroundColor: "#FFFF00",
|
|
162
|
-
primaryFontColor: "#000000",
|
|
163
|
-
secondaryFontColor: "#666666",
|
|
164
|
-
primaryButtonBackgroundColor: "#1757D9",
|
|
165
|
-
primaryButtonHoverColor: "#3A70DF",
|
|
166
|
-
primaryButtonFontColor: "#FFFFFF",
|
|
167
|
-
secondaryButtonBackgroundColor: "#FFFFFF",
|
|
168
|
-
secondaryButtonHoverColor: "#1757D9",
|
|
169
|
-
secondaryButtonFontColor: "#1757D9",
|
|
170
|
-
borderRadius: "8",
|
|
171
|
-
fontSize: "16"
|
|
172
|
-
};
|
|
173
218
|
|
|
174
219
|
try {
|
|
175
220
|
if (Platform.OS === 'android') {
|
|
176
|
-
const
|
|
177
|
-
|
|
178
|
-
} else
|
|
179
|
-
|
|
221
|
+
const result = await RNEasymerchantsdk.billing(amount, null);
|
|
222
|
+
setResponse(`✅ Android Payment Success: ${result}`);
|
|
223
|
+
} else {
|
|
224
|
+
await EasyMerchantSdk.billing(
|
|
180
225
|
amount,
|
|
181
|
-
JSON.stringify(
|
|
182
|
-
['Card', 'Bank', 'Crypto'],
|
|
183
|
-
|
|
184
|
-
false,
|
|
185
|
-
false,
|
|
186
|
-
false
|
|
226
|
+
JSON.stringify(billingInfo),
|
|
227
|
+
['Card', 'Bank', 'Crypto'],
|
|
228
|
+
theme,
|
|
229
|
+
false,
|
|
230
|
+
false,
|
|
231
|
+
false
|
|
187
232
|
);
|
|
188
|
-
|
|
233
|
+
setResponse('🔁 Billing started on iOS. Awaiting response...');
|
|
189
234
|
}
|
|
190
235
|
} catch (error) {
|
|
191
|
-
|
|
192
|
-
setPaymentResponse(`Payment Error: ${error}`);
|
|
193
|
-
} else if (Platform.OS === 'ios') {
|
|
194
|
-
setBillingResult(`Billing Error: ${error.message || error}`);
|
|
195
|
-
}
|
|
236
|
+
setResponse(`❌ Billing Error: ${error.message || error}`);
|
|
196
237
|
}
|
|
197
238
|
};
|
|
198
239
|
|
|
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
240
|
return (
|
|
218
241
|
<View style={styles.container}>
|
|
219
|
-
<Text
|
|
242
|
+
<Text style={styles.title}>EasyMerchant SDK</Text>
|
|
243
|
+
<Text style={styles.version}>Platform Version: {version}</Text>
|
|
220
244
|
<Button title="Get Platform Version" onPress={getPlatformVersion} />
|
|
221
|
-
<
|
|
222
|
-
|
|
223
|
-
|
|
245
|
+
<View style={styles.space} />
|
|
246
|
+
<Button title="Start Billing" onPress={handleBilling} />
|
|
247
|
+
<View style={styles.space} />
|
|
248
|
+
{response ? <Text style={styles.response}>{response}</Text> : null}
|
|
224
249
|
</View>
|
|
225
250
|
);
|
|
226
251
|
};
|
|
227
252
|
|
|
253
|
+
export default App;
|
|
254
|
+
|
|
228
255
|
const styles = StyleSheet.create({
|
|
229
256
|
container: {
|
|
230
257
|
flex: 1,
|
|
231
|
-
|
|
258
|
+
backgroundColor: '#F9FAFB',
|
|
232
259
|
alignItems: 'center',
|
|
233
|
-
|
|
260
|
+
justifyContent: 'center',
|
|
261
|
+
padding: 24
|
|
262
|
+
},
|
|
263
|
+
title: {
|
|
264
|
+
fontSize: 20,
|
|
265
|
+
fontWeight: 'bold',
|
|
266
|
+
marginBottom: 16
|
|
234
267
|
},
|
|
268
|
+
version: {
|
|
269
|
+
fontSize: 14,
|
|
270
|
+
marginBottom: 8
|
|
271
|
+
},
|
|
272
|
+
response: {
|
|
273
|
+
marginTop: 20,
|
|
274
|
+
paddingHorizontal: 12,
|
|
275
|
+
textAlign: 'center',
|
|
276
|
+
fontSize: 14,
|
|
277
|
+
color: '#333'
|
|
278
|
+
},
|
|
279
|
+
space: {
|
|
280
|
+
height: 16
|
|
281
|
+
}
|
|
235
282
|
});
|
|
236
283
|
|
|
237
|
-
export default App;
|
|
238
|
-
|
|
239
284
|
```
|
|
240
285
|
|
|
241
286
|
|
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
#import "EasyMerchantSdk.h"
|
|
2
2
|
#import <React/RCTLog.h>
|
|
3
3
|
#import <React/RCTBridgeModule.h>
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
#import <easymerchantsdk/easymerchantsdk-Swift.h>
|
|
5
|
+
//#import <easymerchantsdk-Swift.h>
|
|
6
6
|
|
|
7
7
|
@implementation EasyMerchantSdk
|
|
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,121 +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() {
|
|
16
|
-
let apiKey = "mobilesdk1980IUuCzwWl"
|
|
17
|
-
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
|
-
if let chargeData = result.chargeData {
|
|
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
|
-
|
|
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
|
+
//
|
|
19
|
+
// let apiKey = "mobilesdk1980IUuCzwWl"
|
|
20
|
+
// let apiSecret = "mobilesdk1980LVHnN0Oh"
|
|
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
|
+
//}
|