@jimrising/easymerchantsdk-react-native 1.4.6 → 1.4.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.
Files changed (25) hide show
  1. package/README.md +211 -135
  2. package/android/build/.transforms/20e1216b87bd06eaab3c9e5c68d4267a/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkModule$1.dex +0 -0
  3. package/android/build/.transforms/20e1216b87bd06eaab3c9e5c68d4267a/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkModule$2.dex +0 -0
  4. package/android/build/.transforms/20e1216b87bd06eaab3c9e5c68d4267a/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkModule.dex +0 -0
  5. package/android/build/.transforms/e9a664a11ce12edf79cd87b1e07aa243/transformed/classes/classes_dex/classes.dex +0 -0
  6. package/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
  7. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule$1.class +0 -0
  8. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule$2.class +0 -0
  9. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule.class +0 -0
  10. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/RNEasymerchantsdkModule$1.class +0 -0
  11. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/RNEasymerchantsdkModule$2.class +0 -0
  12. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/RNEasymerchantsdkModule.class +0 -0
  13. package/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
  14. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/RNEasymerchantsdkModule$1.class.uniqueId2 +0 -0
  15. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/RNEasymerchantsdkModule$2.class.uniqueId0 +0 -0
  16. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/RNEasymerchantsdkModule.class.uniqueId3 +0 -0
  17. package/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
  18. package/android/build.gradle +1 -1
  19. package/android/src/main/java/com/reactlibrary/RNEasymerchantsdkModule.java +26 -79
  20. package/ios/Pods/ViewControllers/OTPVerificationVC.swift +7 -0
  21. package/ios/Pods/ViewControllers/PaymentInformation/PaymentInfoVC.swift +19 -1
  22. package/ios/Pods/ViewControllers/ThreeDSecurePaymentDoneVC.swift +2 -2
  23. package/ios/easymerchantsdk.podspec +1 -1
  24. package/ios/easymerchantsdk.storyboard +89 -86
  25. 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.4.6"
10
+ "@jimrising/easymerchantsdk-react-native": "^1.4.8"
11
11
  },
12
12
  ```
13
13
 
@@ -22,20 +22,23 @@ Now open your `android` folder and there is a `build.gradle` file. Open it and a
22
22
  ```gradle
23
23
  allprojects {
24
24
  repositories {
25
- google()
26
- mavenCentral()
27
- maven { url 'https://jitpack.io' }
28
- maven {
29
- url = uri("https://maven.pkg.github.com/EasyMerchant/em-MobileCheckoutSDK-Android")
30
- credentials {
31
- username = "EasyMerchant"
32
- password = "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"
33
- }
34
- }
25
+ google()
26
+ mavenCentral()
27
+ maven { url 'https://jitpack.io' }
28
+ maven { url 'https://maven.microblink.com' }
29
+ maven {
30
+ url = uri("https://maven.pkg.github.com/EasyMerchant/em-MobileCheckoutSDK-Android")
31
+ credentials {
32
+ username = "EasyMerchant"
33
+ password = "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"
35
34
  }
35
+ }
36
36
  }
37
+ }
37
38
  ```
38
39
 
40
+
41
+
39
42
  ## Changes in IOS side.
40
43
  Add below content inside the AppDelegate.swift File :-
41
44
 
@@ -112,42 +115,44 @@ you can call the sdk using below example:
112
115
 
113
116
  ```javascript
114
117
 
115
- import React, { useEffect, useState } from 'react';
118
+ import React, { useState, useEffect } from 'react';
116
119
  import {
117
- View,
120
+ StyleSheet,
118
121
  Text,
122
+ View,
123
+ TextInput,
119
124
  Button,
120
- StyleSheet,
125
+ Alert,
126
+ ScrollView,
121
127
  Platform,
122
128
  NativeModules,
123
- ScrollView,
124
129
  } from 'react-native';
125
130
 
126
131
  const { RNEasymerchantsdk, EasyMerchantSdk } = NativeModules;
127
132
 
128
133
  const App = () => {
134
+ const [amount, setAmount] = useState('');
135
+ const [result, setResult] = useState('');
129
136
  const [version, setVersion] = useState('');
130
- const [response, setResponse] = useState('');
131
137
  const [referenceToken, setReferenceToken] = useState('');
138
+ const [loading, setLoading] = useState(false);
132
139
 
133
140
  useEffect(() => {
134
- const setup = async () => {
135
- try {
136
- if (Platform.OS === 'ios') {
141
+ const setupIOS = async () => {
142
+ if (Platform.OS === 'ios') {
143
+ try {
137
144
  await EasyMerchantSdk.setViewController();
138
145
  await EasyMerchantSdk.configureEnvironment(
139
146
  'staging',
140
- 'c4dd6319f905ee4d17f202e3d',
141
- '615e339659f2657ae01452561'
147
+ 'apiKey',
148
+ 'secretKey'
142
149
  );
150
+ } catch (err) {
151
+ console.error('iOS Initialization Error:', err);
143
152
  }
144
- } catch (err) {
145
- console.error('Initialization Error:', err);
146
- setResponse(`❌ Initialization Error: ${err.message || JSON.stringify(err)}`);
147
153
  }
148
154
  };
149
-
150
- setup();
155
+ setupIOS();
151
156
  }, []);
152
157
 
153
158
  const getPlatformVersion = async () => {
@@ -163,6 +168,104 @@ const App = () => {
163
168
  }
164
169
  };
165
170
 
171
+ const handlePayment = async () => {
172
+ if (!amount || isNaN(parseFloat(amount)) || parseFloat(amount) <= 0) {
173
+ return Alert.alert('Error', 'Please enter a valid amount');
174
+ }
175
+
176
+ setLoading(true);
177
+
178
+ if (Platform.OS === 'android') {
179
+ const config = {
180
+ amount,
181
+ apiKey: '13bcb1f54b894ddbbd75a86d5',
182
+ secretKey: '94f7ebd5384f6985f23920c13',
183
+ jsonConfig: {
184
+ environment: 'STAGING',
185
+ amount,
186
+ tokenOnly: false,
187
+ currency: 'USD',
188
+ saveCard: true,
189
+ saveAccount: true,
190
+ authenticatedACH: true,
191
+ secureAuthentication: true,
192
+ showReceipt: true,
193
+ showDonate: false,
194
+ showTotal: true,
195
+ showSubmitButton: true,
196
+ paymentMethods: ['card', 'ach'],
197
+ email: 'pavan@hotmail.com',
198
+ name: 'Pavan',
199
+ fields: {
200
+ visibility: { billing: false, additional: false },
201
+ billing: [
202
+ { name: 'address', required: true, value: '' },
203
+ { name: 'country', required: false, value: 'India' },
204
+ { name: 'state', required: true, value: '' },
205
+ { name: 'city', required: true, value: '' },
206
+ { name: 'postal_code', required: true, value: '' },
207
+ ],
208
+ additional: [
209
+ { name: 'name', required: true, value: '' },
210
+ { name: 'email_address', required: true, value: '' },
211
+ { name: 'phone_number', required: false, value: '' },
212
+ { name: 'description', required: true, value: '' },
213
+ ],
214
+ },
215
+ recurring: {
216
+ enableRecurring: true,
217
+ recurringData: {
218
+ allowCycles: 2,
219
+ intervals: ['Weekly', 'Monthly'],
220
+ recurringStartType: 'Custom',
221
+ recurringStartDate: '2025-12-31',
222
+ },
223
+ },
224
+ grailPayParams: {
225
+ accessToken: '251|uTijpDGfrS88UR2V1cZNMQ8S4hUJA0sVzsnsoUZF',
226
+ vendorId: '251',
227
+ role: 'business',
228
+ timeout: 10,
229
+ isSandbox: true,
230
+ brandingName: 'Lyfecycle Payments',
231
+ finderSubtitle: 'Search for your bank',
232
+ searchPlaceholder: 'Enter bank name',
233
+ },
234
+ appearanceSettings: {
235
+ theme: 'light',
236
+ bodyBackgroundColor: '#eeeff2',
237
+ containerBackgroundColor: '#ffffff',
238
+ primaryFontColor: '#000000',
239
+ secondaryFontColor: '#666666',
240
+ primaryButtonBackgroundColor: '#1757d9',
241
+ primaryButtonHoverColor: '#3a70df',
242
+ primaryButtonFontColor: '#ffffff',
243
+ secondaryButtonBackgroundColor: '#ffffff',
244
+ secondaryButtonHoverColor: '#a3b1cc',
245
+ secondaryButtonFontColor: '#1757d9',
246
+ borderRadius: '8',
247
+ fontSize: '16',
248
+ fontWeight: '500',
249
+ fontFamily: 'Inter, sans-serif',
250
+ },
251
+ },
252
+ };
253
+
254
+ try {
255
+ const response = await RNEasymerchantsdk.makePayment(config);
256
+ setResult(response.response || JSON.stringify(response, null, 2));
257
+ } catch (error) {
258
+ setResult(`Error: ${error.message}`);
259
+ Alert.alert('Payment Error', error.message);
260
+ } finally {
261
+ setLoading(false);
262
+ }
263
+ }
264
+ else {
265
+ handleBilling();
266
+ }
267
+ };
268
+
166
269
  const handleBilling = async () => {
167
270
  const billingInfo = {
168
271
  visibility: { billing: false, additional: false },
@@ -208,12 +311,10 @@ const App = () => {
208
311
  borderRadius: '8',
209
312
  fontSize: '14',
210
313
  fontWeight: 500,
211
- fontFamily: '"Inter", sans-serif',
314
+ fontFamily: 'Inter, sans-serif',
212
315
  };
213
316
 
214
- const authConfig = {
215
- // accessToken: '251|uTijpDGfrS88UR2V1cZNMQ8S4hUJA0sVzsnsoUZF',
216
- // vendorId: '251',
317
+ const authConfig = {
217
318
  role: 'business',
218
319
  timeout: 10,
219
320
  isSandbox: true,
@@ -221,86 +322,71 @@ const authConfig = {
221
322
  finderSubtitle: 'Search for your bank',
222
323
  searchPlaceholder: 'Enter bank name',
223
324
  };
224
- try {
225
- if (Platform.OS === 'android') {
226
- const result = await RNEasymerchantsdk.billing('72', null);
227
- setResponse(`✅ Android Payment Success: ${result}`);
228
- } else {
229
- const result = await EasyMerchantSdk.billing(
230
- '99',
231
- 'usd',
232
- billingInfo,
233
- ['card', 'bank'],
234
- themeConfiguration,
235
- false, // tokenOnly
236
- true, // saveCard
237
- true, // saveAccount
238
- true, // authenticatedACH
239
- authConfig, // grailPayParams
240
- 'Submit',
241
- false, // isRecurring
242
- 2, // if isRecurring == true then numOfCycle required
243
- ['weekly', 'monthly'],
244
- 'custom',
245
- '07/07/2025',
246
- true, // secureAuthentication
247
- true, // showReceipt
248
- true, // showTotal
249
- true,// showSubmitButton
250
- "davindersingh@gmail.com",
251
- "Davinder Singh"
252
- );
253
-
254
- console.log('Billing success (full response):', JSON.stringify(result, null, 2));
255
325
 
256
- try {
257
- const refToken = result?.additionalInfo?.threeDSecureStatus?.data?.ref_token;
258
- if (refToken) {
259
- setReferenceToken(refToken);
260
- setResponse(`✅ Ref Token: ${refToken}\nFull Response:\n${JSON.stringify(result, null, 2)}`);
261
- } else {
262
- setResponse(`✅ iOS Payment Success (no ref_token):\n${JSON.stringify(result, null, 2)}`);
263
- }
264
- } catch (err) {
265
- console.error('Error parsing ref_token:', err);
266
- setResponse(`✅ iOS Payment Success (error parsing ref_token):\n${JSON.stringify(result, null, 2)}`);
267
- }
268
- }
326
+ try {
327
+ const result = await EasyMerchantSdk.billing(
328
+ amount,
329
+ 'usd',
330
+ billingInfo,
331
+ ['card', 'bank'],
332
+ themeConfiguration,
333
+ false, // tokenOnly
334
+ true, // saveCard
335
+ true, // saveAccount
336
+ true, // authenticatedACH
337
+ authConfig, // grailPayParams
338
+ 'Submit',
339
+ false, // isRecurring
340
+ 2, // if isRecurring == true then numOfCycle required
341
+ ['weekly', 'monthly'],
342
+ 'custom',
343
+ '07/07/2025',
344
+ true, // secureAuthentication
345
+ true, // showReceipt
346
+ true, // showTotal
347
+ true,// showSubmitButton
348
+ "davindersingh@gmail.com",
349
+ "Davinder Singh"
350
+ );
351
+
352
+ const refToken = result?.additionalInfo?.threeDSecureStatus?.data?.ref_token;
353
+ if (refToken) setReferenceToken(refToken);
354
+
355
+ setResult(JSON.stringify(result, null, 2));
269
356
  } catch (error) {
270
357
  console.error('Billing Error:', error);
271
- let errorMessage = 'Unknown error';
272
- if (error.code && error.message) {
273
- errorMessage = `Code: ${error.code}, Message: ${error.message}`;
274
- } else if (error.message) {
275
- errorMessage = error.message;
276
- }
277
- setResponse(`❌ Billing Error: ${errorMessage}`);
358
+ setResult(`❌ Billing Error: ${error.message || JSON.stringify(error)}`);
359
+ }
360
+ };
361
+
362
+ const handleCheckStatus = async () => {
363
+ setLoading(true);
364
+ try {
365
+ const response = await RNEasymerchantsdk.checkPaymentStatus();
366
+ setResult(response.response || JSON.stringify(response, null, 2));
367
+ } catch (error) {
368
+ setResult(`Error: ${error.message}`);
369
+ Alert.alert('Status Check Error', error.message);
370
+ } finally {
371
+ setLoading(false);
278
372
  }
279
373
  };
280
374
 
281
375
  const handlePaymentReference = async () => {
376
+ if (Platform.OS === 'android') {
377
+ setResult('❌ Payment Reference not supported on Android');
378
+ return;
379
+ }
282
380
  if (!referenceToken) {
283
- setResponse('❌ No reference token available from billing');
381
+ setResult('❌ No reference token available from billing');
284
382
  return;
285
383
  }
286
-
287
384
  try {
288
- if (Platform.OS === 'android') {
289
- setResponse('❌ Payment Reference not supported on Android');
290
- } else {
291
- const result = await EasyMerchantSdk.paymentReference(referenceToken);
292
- console.log('Payment Reference success:', JSON.stringify(result, null, 2));
293
- setResponse(`✅ iOS Payment Reference Success:\n${JSON.stringify(result, null, 2)}`);
294
- }
385
+ const result = await EasyMerchantSdk.paymentReference(referenceToken);
386
+ setResult(`✅ Payment Reference:
387
+ ${JSON.stringify(result, null, 2)}`);
295
388
  } catch (error) {
296
- console.error('Payment Reference Error:', error);
297
- let errorMessage = 'Unknown error';
298
- if (error.code && error.message) {
299
- errorMessage = `Code: ${error.code}, Message: ${error.message}`;
300
- } else if (error.message) {
301
- errorMessage = error.message;
302
- }
303
- setResponse(`❌ Payment Reference Error: ${errorMessage}`);
389
+ setResult(`❌ Payment Reference Error: ${error.message || JSON.stringify(error)}`);
304
390
  }
305
391
  };
306
392
 
@@ -309,15 +395,20 @@ const authConfig = {
309
395
  <ScrollView contentContainerStyle={styles.scrollContent}>
310
396
  <Text style={styles.title}>EasyMerchant SDK</Text>
311
397
  <Text style={styles.version}>Platform Version: {version}</Text>
312
-
313
- <Button title="Get Platform Version" onPress={getPlatformVersion} />
314
- <View style={styles.space} />
315
- <Button title="Start Billing" onPress={handleBilling} />
316
- <View style={styles.space} />
317
- <Button title="Start Payment Reference" onPress={handlePaymentReference} />
318
- <View style={styles.space} />
319
-
320
- <Text style={styles.response}>{response}</Text>
398
+ <Button title="Get Platform Version" onPress={getPlatformVersion} disabled={loading} />
399
+ <TextInput
400
+ style={styles.input}
401
+ placeholder="Enter amount (e.g., 10.00)"
402
+ keyboardType="decimal-pad"
403
+ value={amount}
404
+ onChangeText={setAmount}
405
+ />
406
+ <View style={styles.buttonGroup}>
407
+ <Button title="Pay" onPress={handlePayment} disabled={loading} />
408
+ <Button title="Check Status" onPress={handleCheckStatus} disabled={loading} />
409
+ <Button title="Payment Ref" onPress={handlePaymentReference} disabled={loading} />
410
+ </View>
411
+ <Text selectable style={styles.result}>{result}</Text>
321
412
  </ScrollView>
322
413
  </View>
323
414
  );
@@ -326,35 +417,20 @@ const authConfig = {
326
417
  export default App;
327
418
 
328
419
  const styles = StyleSheet.create({
329
- container: {
330
- flex: 1,
331
- backgroundColor: '#F9FAFB',
332
- },
333
- scrollContent: {
334
- flexGrow: 1,
335
- alignItems: 'center',
336
- justifyContent: 'center',
337
- padding: 24,
338
- },
339
- title: {
340
- fontSize: 20,
341
- fontWeight: 'bold',
342
- marginBottom: 16,
343
- },
344
- version: {
345
- fontSize: 14,
346
- marginBottom: 8,
347
- },
348
- response: {
349
- marginTop: 20,
350
- paddingHorizontal: 12,
351
- textAlign: 'center',
352
- fontSize: 14,
353
- color: '#333',
354
- },
355
- space: {
356
- height: 16,
420
+ container: { flex: 1, backgroundColor: '#F9FAFB' },
421
+ scrollContent: { flexGrow: 1, padding: 20 },
422
+ title: { fontSize: 24, fontWeight: 'bold', marginBottom: 16, textAlign: 'center' },
423
+ version: { fontSize: 14, marginBottom: 10, textAlign: 'center' },
424
+ input: {
425
+ height: 40,
426
+ borderColor: '#ccc',
427
+ borderWidth: 1,
428
+ borderRadius: 5,
429
+ paddingHorizontal: 10,
430
+ marginBottom: 20,
357
431
  },
432
+ buttonGroup: { marginBottom: 20, gap: 10 },
433
+ result: { fontSize: 14, fontFamily: 'monospace', color: '#333' },
358
434
  });
359
435
 
360
436
  ```
@@ -39,7 +39,7 @@ repositories {
39
39
  }
40
40
 
41
41
  dependencies {
42
- implementation 'com.app:paysdk:1.2.3'
42
+ implementation 'com.app:paysdk:1.2.7'
43
43
  implementation 'com.hbb20:ccp:2.7.3'
44
44
  implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.1"
45
45
  implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.1"
@@ -9,15 +9,9 @@ import com.facebook.react.bridge.ReactContextBaseJavaModule;
9
9
  import com.facebook.react.bridge.ReactMethod;
10
10
  import com.facebook.react.bridge.Promise;
11
11
  import com.facebook.react.bridge.ReadableMap;
12
- import com.facebook.react.bridge.ReadableArray;
13
12
  import com.facebook.react.bridge.WritableMap;
14
13
  import com.facebook.react.bridge.Arguments;
15
14
  import org.json.JSONObject;
16
- import org.json.JSONArray;
17
- import org.json.JSONException;
18
- import java.util.HashMap;
19
- import java.util.ArrayList;
20
- import java.util.List;
21
15
 
22
16
  public class RNEasymerchantsdkModule extends ReactContextBaseJavaModule {
23
17
  private final ReactApplicationContext reactContext;
@@ -39,7 +33,7 @@ public class RNEasymerchantsdkModule extends ReactContextBaseJavaModule {
39
33
  String platformVersion = "Android " + android.os.Build.VERSION.RELEASE;
40
34
  promise.resolve(platformVersion);
41
35
  } catch (Exception e) {
42
- promise.reject("ERROR", "Failed to get platform version: " + e.getMessage());
36
+ promise.reject("PLATFORM_ERROR", "Failed to get platform version: " + e.getMessage());
43
37
  }
44
38
  }
45
39
 
@@ -47,99 +41,52 @@ public class RNEasymerchantsdkModule extends ReactContextBaseJavaModule {
47
41
  public void makePayment(ReadableMap configMap, Promise promise) {
48
42
  Activity currentActivity = getCurrentActivity();
49
43
  if (currentActivity == null) {
50
- promise.reject("ERROR", "Activity is not initialized.");
44
+ promise.reject("ACTIVITY_ERROR", "Activity is not initialized.");
51
45
  return;
52
46
  }
53
47
 
54
48
  try {
55
49
  // Validate required fields
56
- if (!configMap.hasKey("amount") || configMap.getString("amount").isEmpty() || Float.parseFloat(configMap.getString("amount")) <= 0) {
57
- promise.reject("ERROR", "Invalid or missing amount.");
50
+ if (!configMap.hasKey("amount") || configMap.getString("amount") == null || configMap.getString("amount").isEmpty() || Float.parseFloat(configMap.getString("amount")) <= 0) {
51
+ promise.reject("VALIDATION_ERROR", "Invalid or missing amount.");
58
52
  return;
59
53
  }
60
-
61
- if (!configMap.hasKey("apiKey") || !configMap.hasKey("secretKey")) {
62
- promise.reject("ERROR", "Missing apiKey or secretKey.");
54
+ if (!configMap.hasKey("apiKey") || configMap.getString("apiKey") == null || configMap.getString("apiKey").isEmpty()) {
55
+ promise.reject("VALIDATION_ERROR", "Missing or empty apiKey.");
56
+ return;
57
+ }
58
+ if (!configMap.hasKey("secretKey") || configMap.getString("secretKey") == null || configMap.getString("secretKey").isEmpty()) {
59
+ promise.reject("VALIDATION_ERROR", "Missing or empty secretKey.");
60
+ return;
61
+ }
62
+ if (!configMap.hasKey("jsonConfig") || configMap.getMap("jsonConfig") == null) {
63
+ promise.reject("VALIDATION_ERROR", "Missing jsonConfig.");
63
64
  return;
64
65
  }
65
66
 
66
67
  // Extract configurations
67
- String amountStr = configMap.getString("amount");
68
+ String amount = configMap.getString("amount");
68
69
  String apiKey = configMap.getString("apiKey");
69
70
  String secretKey = configMap.getString("secretKey");
70
71
  JSONObject jsonConfig = new JSONObject(configMap.getMap("jsonConfig").toHashMap());
71
- ReadableMap hashMapConfig = configMap.getMap("hashMapConfig");
72
-
73
- // Build hashMap configuration
74
- HashMap<String, Object> hashMap = new HashMap<>();
75
- hashMap.put("amount", hashMapConfig.getString("amount"));
76
- hashMap.put("currency", hashMapConfig.getString("currency"));
77
- hashMap.put("tokenOnly", hashMapConfig.getBoolean("tokenOnly"));
78
- hashMap.put("saveCard", hashMapConfig.getBoolean("saveCard"));
79
- hashMap.put("saveAccount", hashMapConfig.getBoolean("saveAccount"));
80
-
81
- // Handle payment methods
82
- ReadableArray paymentMethodsArray = hashMapConfig.getArray("paymentMethods");
83
- List<String> paymentMethods = new ArrayList<>();
84
- for (int i = 0; i < paymentMethodsArray.size(); i++) {
85
- paymentMethods.add(paymentMethodsArray.getString(i));
86
- }
87
- hashMap.put("paymentMethods", paymentMethods);
88
-
89
- hashMap.put("fontSize", (float) hashMapConfig.getDouble("fontSize"));
90
- hashMap.put("showDonate", hashMapConfig.getBoolean("showDonate"));
91
- hashMap.put("enableRecurring", hashMapConfig.getBoolean("enableRecurring"));
92
72
 
93
- // Handle recurring data
94
- ReadableMap recurringDataMap = hashMapConfig.getMap("recurringData");
95
- JSONObject recurringInfo = new JSONObject();
96
- recurringInfo.put("allowCycles", recurringDataMap.getInt("allowCycles"));
97
- ReadableArray intervalsArray = recurringDataMap.getArray("intervals");
98
- JSONArray intervals = new JSONArray();
99
- for (int i = 0; i < intervalsArray.size(); i++) {
100
- intervals.put(intervalsArray.getString(i));
101
- }
102
- recurringInfo.put("intervals", intervals);
103
- recurringInfo.put("recurringStartType", recurringDataMap.getString("recurringStartType"));
104
- hashMap.put("recurringData", recurringInfo);
105
- hashMap.put("authenticateBank", hashMapConfig.getBoolean("authenticateBank"));
106
-
107
- // Handle GrailPayParams
108
- ReadableMap grailPayParamsMap = hashMapConfig.getMap("grailPayParams");
109
- JSONObject grailPayParamsJson = new JSONObject();
110
- grailPayParamsJson.put("accessToken", grailPayParamsMap.getString("accessToken"));
111
- grailPayParamsJson.put("vendorId", grailPayParamsMap.getString("vendorId"));
112
- grailPayParamsJson.put("role", grailPayParamsMap.getString("role"));
113
- grailPayParamsJson.put("timeout", grailPayParamsMap.getInt("timeout"));
114
- grailPayParamsJson.put("isSandbox", grailPayParamsMap.getBoolean("isSandbox"));
115
- grailPayParamsJson.put("brandingName", grailPayParamsMap.getString("brandingName"));
116
- grailPayParamsJson.put("finderSubtitle", grailPayParamsMap.getString("finderSubtitle"));
117
- grailPayParamsJson.put("searchPlaceholder", grailPayParamsMap.getString("searchPlaceholder"));
118
- hashMap.put("grailPayParams", grailPayParamsJson);
119
-
120
- hashMap.put("is3DSecureEnable", hashMapConfig.getBoolean("is3DSecureEnable"));
121
- hashMap.put("showPrice", hashMapConfig.getBoolean("showPrice"));
122
-
123
- // Handle billing info
124
- if (hashMapConfig.hasKey("billingInfo")) {
125
- JSONObject billingInfo = new JSONObject(hashMapConfig.getMap("billingInfo").toHashMap());
126
- hashMap.put("billingInfo", billingInfo);
73
+ String environment = jsonConfig.optString("environment", "STAGING");
74
+ if (!environment.equals("STAGING") && !environment.equals("SANDBOX") && !environment.equals("PRODUCTION")) {
75
+ promise.reject("CONFIG_ERROR", "Invalid environment: " + environment);
76
+ return;
127
77
  }
128
78
 
129
-
130
-
131
79
  EasyPaymentFactory easyPaymentFactory = EasyPaymentFactory.INSTANCE;
132
- EasyPaymentService easyPaymentService = easyPaymentFactory.create(
80
+ EasyPaymentService easyPaymentService = easyPaymentFactory.create(
133
81
  currentActivity,
134
- jsonConfig.getString("environment"),
82
+ environment,
135
83
  apiKey,
136
- secretKey);
137
-
84
+ secretKey
85
+ );
138
86
 
139
87
  // Make payment
140
88
  easyPaymentService.makePayment(
141
89
  jsonConfig,
142
- hashMap,
143
90
  new EasyPaymentFactory.OnTransactionListener() {
144
91
  @Override
145
92
  public void onSuccess(String response) {
@@ -154,8 +101,8 @@ public class RNEasymerchantsdkModule extends ReactContextBaseJavaModule {
154
101
  }
155
102
  }
156
103
  );
157
- } catch (JSONException ex) {
158
- promise.reject("JSON_ERROR", "Invalid JSON configuration: " + ex.getMessage());
104
+ } catch (NumberFormatException ex) {
105
+ promise.reject("VALIDATION_ERROR", "Invalid amount format: " + ex.getMessage());
159
106
  } catch (Exception ex) {
160
107
  promise.reject("ERROR", "Payment failed: " + ex.getMessage());
161
108
  }
@@ -165,7 +112,7 @@ public class RNEasymerchantsdkModule extends ReactContextBaseJavaModule {
165
112
  public void checkPaymentStatus(Promise promise) {
166
113
  Activity currentActivity = getCurrentActivity();
167
114
  if (currentActivity == null) {
168
- promise.reject("ERROR", "Activity is not initialized.");
115
+ promise.reject("ACTIVITY_ERROR", "Activity is not initialized.");
169
116
  return;
170
117
  }
171
118