@jimrising/easymerchantsdk-react-native 2.1.1 → 2.1.3

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 (28) hide show
  1. package/README.md +185 -119
  2. package/android/.gradle/8.10/fileHashes/fileHashes.lock +0 -0
  3. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  4. package/android/.gradle/buildOutputCleanup/cache.properties +2 -2
  5. package/android/build/.transforms/15b6a8a60a6b32d0dcaf609723cf365b/transformed/classes/classes_dex/classes.dex +0 -0
  6. package/android/build/.transforms/8508f1428f740032c45a43f48b1bbe1e/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkModule$1$1.dex +0 -0
  7. package/android/build/.transforms/8508f1428f740032c45a43f48b1bbe1e/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkModule$1.dex +0 -0
  8. package/android/build/.transforms/8508f1428f740032c45a43f48b1bbe1e/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkModule$2.dex +0 -0
  9. package/android/build/.transforms/8508f1428f740032c45a43f48b1bbe1e/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkModule.dex +0 -0
  10. package/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
  11. package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +1 -1
  12. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule$1$1.class +0 -0
  13. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule$1.class +0 -0
  14. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule$2.class +0 -0
  15. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule.class +0 -0
  16. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/RNEasymerchantsdkModule$1$1.class +0 -0
  17. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/RNEasymerchantsdkModule$1.class +0 -0
  18. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/RNEasymerchantsdkModule$2.class +0 -0
  19. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/RNEasymerchantsdkModule.class +0 -0
  20. package/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
  21. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/RNEasymerchantsdkModule$1$1.class.uniqueId1 +0 -0
  22. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/RNEasymerchantsdkModule$1.class.uniqueId0 +0 -0
  23. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/RNEasymerchantsdkModule$2.class.uniqueId3 +0 -0
  24. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/RNEasymerchantsdkModule.class.uniqueId2 +0 -0
  25. package/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
  26. package/android/src/main/java/com/reactlibrary/RNEasymerchantsdkModule.java +19 -5
  27. package/ios/easymerchantsdk.podspec +1 -1
  28. package/package.json +1 -1
package/README.md CHANGED
@@ -1,28 +1,29 @@
1
- # EasyMerchantSdk React Native Implementation
1
+ # EasyMerchant SDK React Native Integration
2
2
 
3
- This guide provides step-by-step instructions to integrate the EasyMerchantSdk into your React Native application for both Android and iOS platforms. The SDK supports identical parameters for both platforms, with differences only in the method calls for initiating payments and handling responses.
3
+ This guide provides step-by-step instructions for integrating the EasyMerchant SDK into a React Native application for Android and iOS platforms. The SDK supports identical configuration parameters for both platforms, with slight differences in method calls for initiating payments and handling responses. This project includes a sample implementation (`App.js`) that demonstrates a fully configurable payment interface with support for card payments, ACH transfers, recurring payments, 3D Secure authentication, and customizable billing/additional information fields.
4
4
 
5
5
  ## Prerequisites
6
6
 
7
- - Node.js and npm installed
8
- - React Native development environment set up
9
- - Ruby 3.2.8 (for iOS setup)
10
- - Xcode (for iOS development)
11
- - Android Studio (for Android development)
7
+ - **Node.js and npm**: Ensure Node.js (v16 or higher) and npm are installed.
8
+ - **React Native Environment**: Set up a React Native development environment as per the [official documentation](https://reactnative.dev/docs/environment-setup).
9
+ - **Ruby**: Version 3.2.8 or higher for iOS setup (required for CocoaPods).
10
+ - **Xcode**: Version 14 or higher for iOS development.
11
+ - **Android Studio**: For Android development, with Gradle configured.
12
+ - **EasyMerchant SDK Credentials**: Obtain API keys and secret keys for `sandbox` and `staging` environments from your EasyMerchant account.
12
13
 
13
14
  ## Installation
14
15
 
15
16
  ### 1. Add the SDK to Your Project
16
17
 
17
- Add the EasyMerchantSdk to your project by including it in your `package.json` file under the `dependencies` section:
18
+ Add the EasyMerchant SDK to your project by including it in your `package.json` under the `dependencies` section:
18
19
 
19
20
  ```json
20
21
  "dependencies": {
21
- "@jimrising/easymerchantsdk-react-native": "^2.1.1"
22
+ "@jimrising/easymerchantsdk-react-native": "^2.1.3"
22
23
  }
23
24
  ```
24
25
 
25
- Alternatively, install it using the following command:
26
+ Alternatively, install it using npm:
26
27
 
27
28
  ```bash
28
29
  npm install @jimrising/easymerchantsdk-react-native
@@ -31,7 +32,7 @@ npm install @jimrising/easymerchantsdk-react-native
31
32
  ### 2. Android Configuration
32
33
 
33
34
  1. Open the `android/build.gradle` file in your project.
34
- 2. Add the following code to the `allprojects.repositories` section to ensure the SDK can access required dependencies:
35
+ 2. Add the following to the `allprojects.repositories` section to include the SDK's dependencies:
35
36
 
36
37
  ```gradle
37
38
  allprojects {
@@ -50,12 +51,13 @@ allprojects {
50
51
  }
51
52
  ```
52
53
 
53
- 3. Sync your project with Gradle to apply the changes.
54
+ 3. Ensure `GITHUB_URL`, `GITHUB_USERNAME`, and `GITHUB_PASSWORD` are defined in your `gradle.properties` file or provided via your CI/CD system.
55
+ 4. Sync your project with Gradle to apply the changes.
54
56
 
55
57
  ### 3. iOS Configuration
56
58
 
57
59
  1. **Update AppDelegate.swift**
58
- Create or modify the `AppDelegate.swift` file in your iOS project to include the following code:
60
+ Modify or create the `ios/AppDelegate.swift` file to initialize the React Native bridge and set up the EasyMerchant SDK:
59
61
 
60
62
  ```swift
61
63
  import UIKit
@@ -90,7 +92,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
90
92
 
91
93
  let rootView = RCTRootView(
92
94
  bridge: validBridge,
93
- moduleName: "EasyMerchantTestApp", // Replace with your app name
95
+ moduleName: "EasyMerchantTestApp", // Replace with your app's module name
94
96
  initialProperties: nil
95
97
  )
96
98
 
@@ -111,7 +113,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
111
113
  ```
112
114
 
113
115
  2. **Update Podfile**
114
- Open your `ios/Podfile` and add the following to include the EasyMerchantSdk pod:
116
+ In your `ios/Podfile`, add the EasyMerchant SDK pod:
115
117
 
116
118
  ```ruby
117
119
  require_relative '../node_modules/react-native/scripts/react_native_pods'
@@ -119,34 +121,34 @@ require_relative '../node_modules/@react-native-community/cli-platform-ios/nativ
119
121
 
120
122
  platform :ios, '16.0'
121
123
 
122
- pod 'easymerchantsdk', :path => '../node_modules/easymerchantsdk-react-native/ios'
124
+ pod 'easymerchantsdk', :path => '../node_modules/@jimrising/easymerchantsdk-react-native/ios'
123
125
  ```
124
126
 
125
- 3. Run `pod install` in the `ios` directory to install the dependencies:
127
+ 3. Install the pod dependencies by running:
126
128
 
127
129
  ```bash
128
130
  cd ios
129
- pod install
131
+ pod install --repo-update
130
132
  ```
131
133
 
132
- ## Usage in Your React Native App
134
+ ## Usage
133
135
 
134
- To integrate the EasyMerchantSdk into your React Native application, you can use the provided `App.js` as a reference. The parameters for Android and iOS are identical, but the method calls differ slightly.
136
+ The sample `App.js` provides a complete implementation for integrating the EasyMerchant SDK, including a user interface for configuring payment settings and handling responses. Below is a guide to using the SDK in your React Native application.
135
137
 
136
- ### 1. Import Necessary Modules
138
+ ### 1. Import Required Modules
137
139
 
138
- Ensure you import the required React Native components and the EasyMerchantSdk NativeModules:
140
+ Ensure you import the necessary React Native components and the EasyMerchant SDK NativeModules:
139
141
 
140
142
  ```javascript
141
143
  import React, { useState, useEffect } from 'react';
142
- import { StyleSheet, Text, View, TextInput, Button, Alert, ScrollView, Platform, NativeModules, Switch, TouchableOpacity, NativeEventEmitter, KeyboardAvoidingView, Keyboard, TouchableWithoutFeedback, Modal } from 'react-native';
144
+ import { StyleSheet, Text, View, TextInput, Switch, TouchableOpacity, NativeModules, NativeEventEmitter, Platform, Alert, ScrollView, KeyboardAvoidingView, Modal, TouchableWithoutFeedback } from 'react-native';
143
145
 
144
146
  const { RNEasymerchantsdk, EasyMerchantSdk } = NativeModules;
145
147
  ```
146
148
 
147
- ### 2. Set Up Configuration
149
+ ### 2. Define Configuration
148
150
 
149
- Define the configuration object for the SDK, which is shared between Android and iOS. The provided `App.js` includes a comprehensive `externalConfig` object that you can customize:
151
+ Use a configuration object to define payment settings. The `externalConfig` in `App.js` is a comprehensive example that supports both platforms:
150
152
 
151
153
  ```javascript
152
154
  const externalConfig = {
@@ -157,16 +159,16 @@ const externalConfig = {
157
159
  isSecureAuthentication: false,
158
160
  isBillingVisible: false,
159
161
  isAdditionalVisible: false,
160
- emailEditable: true,
161
- isEmail: true,
162
+ emailEditable: true, // Android-specific
163
+ isEmail: true, // iOS-specific
162
164
  billingInfo: {
163
165
  visibility: { billing: false, additional: false },
164
166
  billing: {
165
- address: 'Address',
166
- country: 'Country',
167
- state: 'State',
168
- city: 'City',
169
- postal_code: '000000',
167
+ address: 'San Fran',
168
+ country: 'USA',
169
+ state: 'California',
170
+ city: 'Paris',
171
+ postal_code: '234234',
170
172
  },
171
173
  billingRequired: {
172
174
  address: true,
@@ -178,7 +180,7 @@ const externalConfig = {
178
180
  additional: {
179
181
  name: 'Test User',
180
182
  email_address: 'test@gmail.com',
181
- phone_number: '2140871329',
183
+ phone_number: '0000000',
182
184
  description: 'Test',
183
185
  },
184
186
  additionalRequired: {
@@ -213,10 +215,10 @@ const externalConfig = {
213
215
  recurringData: {
214
216
  allowCycles: 2,
215
217
  intervals: ['daily', 'weekly', 'monthly'],
216
- recurringStartType: Platform.OS === 'android' ? 'Custom' : 'custom',
218
+ recurringStartType: 'custom',
217
219
  recurringStartDate: new Date().toLocaleDateString('en-US', { month: '2-digit', day: '2-digit', year: 'numeric' }),
218
220
  },
219
- configur: {
221
+ androidConfig: {
220
222
  currency: 'usd',
221
223
  saveCard: true,
222
224
  saveAccount: true,
@@ -224,7 +226,7 @@ const externalConfig = {
224
226
  showDonate: false,
225
227
  showTotal: true,
226
228
  showSubmitButton: true,
227
- paymentMethod: ['card', 'ach'],
229
+ paymentMethods: ['card', 'ach'],
228
230
  name: '',
229
231
  fields: {
230
232
  visibility: { billing: false, additional: false },
@@ -263,17 +265,88 @@ const externalConfig = {
263
265
  };
264
266
  ```
265
267
 
266
- ### 3. Handle Payments
268
+ This configuration includes:
269
+ - **Basic Info**: `amount`, `email`, `name`.
270
+ - **Payment Options**: Toggles for recurring payments, authenticated ACH, 3D Secure, and visibility of billing/additional fields.
271
+ - **Billing Info**: Configurable billing and additional fields with required flags.
272
+ - **Theming**: Separate `themeConfiguration` (iOS) and `androidConfig.appearanceSettings` (Android) for UI customization.
273
+ - **GrailPay Params**: Settings for bank search UI (e.g., role, timeout, branding).
274
+ - **Recurring Data**: Options for recurring payment cycles and intervals.
275
+ - **Android Config**: Android-specific settings, including payment methods and fields.
267
276
 
268
- The `handlePayment` function validates inputs and calls platform-specific billing functions. The parameters are identical for both platforms, but the method calls differ.
277
+ ### 3. Initialize Environment
269
278
 
270
- #### Android: `handleAndroidBilling`
279
+ Configure the SDK environment (`sandbox` or `staging`) with API keys and secret keys:
280
+
281
+ ```javascript
282
+ const [apiKeys, setApiKeys] = useState({
283
+ sandbox: {
284
+ apiKey: 'apiKey',
285
+ secretKey: 'secretKey',
286
+ },
287
+ staging: {
288
+ apiKey: 'apiKey',
289
+ secretKey: 'secretKey',
290
+ },
291
+ });
292
+
293
+ useEffect(() => {
294
+ const updateEnvironment = async () => {
295
+ const { apiKey, secretKey } = apiKeys[environment];
296
+ if (Platform.OS === 'ios') {
297
+ try {
298
+ await EasyMerchantSdk.setViewController();
299
+ await EasyMerchantSdk.configureEnvironment(environment, apiKey, secretKey);
300
+ } catch (err) {
301
+ Alert.alert('Error', `Failed to configure iOS environment: ${err.message}`);
302
+ }
303
+ }
304
+ };
305
+ updateEnvironment();
306
+ }, [environment, apiKeys]);
307
+ ```
308
+
309
+ **Note**: Replace the placeholder API keys with your actual credentials. Store them securely (e.g., in environment variables) rather than hardcoding.
310
+
311
+ ### 4. Handle Payments
312
+
313
+ The `handlePayment` function validates inputs and delegates to platform-specific billing handlers. At least one payment method (`card` or `ach`) must be selected, and recurring payments require at least one interval.
314
+
315
+ #### Main Payment Handler
316
+
317
+ ```javascript
318
+ const handlePayment = async () => {
319
+ if (!amount || isNaN(parseFloat(amount)) || parseFloat(amount) <= 0) {
320
+ return Alert.alert('Error', 'Please enter a valid amount');
321
+ }
322
+ if (isRecurring && (!recurringData.intervals || recurringData.intervals.length === 0)) {
323
+ return Alert.alert('Error', 'Please select at least one interval for recurring payment');
324
+ }
325
+ if (!androidConfig.paymentMethods || androidConfig.paymentMethods.length === 0) {
326
+ return Alert.alert('Error', 'Please select at least one payment method');
327
+ }
328
+
329
+ setLoading(true);
330
+ const timeoutId = setTimeout(() => setLoading(false), 3000);
331
+ try {
332
+ if (Platform.OS === 'android') {
333
+ await handleAndroidBilling();
334
+ } else {
335
+ await handleIosBilling();
336
+ }
337
+ } finally {
338
+ clearTimeout(timeoutId);
339
+ setLoading(false);
340
+ }
341
+ };
342
+ ```
343
+
344
+ #### Android Billing
271
345
 
272
346
  ```javascript
273
347
  const handleAndroidBilling = async () => {
274
348
  const { apiKey, secretKey } = apiKeys[environment];
275
- const selectedPaymentMethods = [...configur.paymentMethod];
276
-
349
+ const selectedPaymentMethods = [...androidConfig.paymentMethods];
277
350
  const config = {
278
351
  amount,
279
352
  apiKey,
@@ -282,27 +355,30 @@ const handleAndroidBilling = async () => {
282
355
  environment,
283
356
  amount,
284
357
  tokenOnly: false,
285
- currency: configur.currency,
286
- saveCard: configur.saveCard,
287
- saveAccount: configur.saveAccount,
358
+ currency: androidConfig.currency,
359
+ saveCard: androidConfig.saveCard,
360
+ saveAccount: androidConfig.saveAccount,
288
361
  authenticatedACH: isAuthenticatedACH,
289
362
  secureAuthentication: isSecureAuthentication,
290
- showReceipt: configur.showReceipt,
291
- showDonate: configur.showDonate,
292
- showTotal: configur.showTotal,
293
- showSubmitButton: configur.showSubmitButton,
294
- paymentMethod: selectedPaymentMethods,
363
+ showReceipt: androidConfig.showReceipt,
364
+ showDonate: androidConfig.showDonate,
365
+ showTotal: androidConfig.showTotal,
366
+ showSubmitButton: androidConfig.showSubmitButton,
367
+ paymentMethods: selectedPaymentMethods,
295
368
  emailEditable,
296
369
  email,
297
370
  name,
298
371
  fields: {
299
- ...configur.fields,
300
- visibility: {
301
- billing: isBillingVisible,
302
- additional: isAdditionalVisible,
303
- },
372
+ ...androidConfig.fields,
373
+ visibility: { billing: isBillingVisible, additional: isAdditionalVisible },
374
+ },
375
+ metadata: {
376
+ metaKey: 'metaValue',
377
+ metaKLey1: 'metaValue1',
378
+ metaKLey2: 'metaValue2',
379
+ metaKLey3: 'metaValue3',
380
+ metaKLey4: 'metaValue4',
304
381
  },
305
- metadata,
306
382
  ...(isRecurring && {
307
383
  recurring: {
308
384
  enableRecurring: true,
@@ -310,7 +386,7 @@ const handleAndroidBilling = async () => {
310
386
  },
311
387
  }),
312
388
  grailPayParams,
313
- appearanceSettings: configur.appearanceSettings,
389
+ appearanceSettings: androidConfig.appearanceSettings,
314
390
  },
315
391
  };
316
392
 
@@ -323,32 +399,29 @@ const handleAndroidBilling = async () => {
323
399
  };
324
400
  setResult(JSON.stringify(parsedResponse, null, 2));
325
401
  } catch (error) {
326
- setResult(`Error: ${error.message ?? JSON.stringify(error)}`);
327
- Alert.alert('Payment Error', error.message ?? 'Unknown error');
328
- } finally {
329
- setLoading(false);
402
+ setResult(`Error: ${error.message || 'Unknown error'}`);
403
+ Alert.alert('Payment Error', error.message || 'An error occurred during payment');
330
404
  }
331
405
  };
332
406
  ```
333
407
 
334
- #### iOS: `handleIosBilling`
408
+ #### iOS Billing
335
409
 
336
410
  ```javascript
337
411
  const handleIosBilling = async () => {
338
- const selectedPaymentMethodsIOS = [...configur.paymentMethod].map(method =>
412
+ const selectedPaymentMethodsIOS = androidConfig.paymentMethods.map(method =>
339
413
  method === 'card' ? 'Card' : method === 'ach' ? 'Bank' : method
340
414
  );
341
-
342
415
  try {
343
416
  const result = await EasyMerchantSdk.billing(
344
417
  amount,
345
- 'usd', // Default currency
418
+ androidConfig.currency || 'usd',
346
419
  billingInfo,
347
420
  selectedPaymentMethodsIOS,
348
421
  themeConfiguration,
349
- false, // tokenOnly
350
- true, // saveCard
351
- true, // saveAccount
422
+ false,
423
+ androidConfig.saveCard,
424
+ androidConfig.saveAccount,
352
425
  isAuthenticatedACH,
353
426
  grailPayParams,
354
427
  'Submit',
@@ -358,74 +431,71 @@ const handleIosBilling = async () => {
358
431
  isRecurring ? recurringData.recurringStartType : '',
359
432
  isRecurring ? recurringData.recurringStartDate : '',
360
433
  isSecureAuthentication,
361
- true, // showReceipt
362
- true, // showTotal
363
- true, // showSubmitButton
434
+ androidConfig.showReceipt,
435
+ androidConfig.showTotal,
436
+ androidConfig.showSubmitButton,
364
437
  isEmail,
365
438
  email,
366
439
  name,
367
- metadata
440
+ {
441
+ metaKey: 'metaValue',
442
+ metaKLey1: 'metaValue1',
443
+ metaKLey2: 'metaValue2',
444
+ metaKLey3: 'metaValue3',
445
+ metaKLey4: 'metaValue4',
446
+ }
368
447
  );
369
-
370
448
  const refToken = result?.additionalInfo?.threeDSecureStatus?.data?.ref_token;
371
449
  if (refToken) setReferenceToken(refToken);
372
450
  setResult(JSON.stringify(result, null, 2));
373
451
  } catch (error) {
374
- setResult(`Billing Error: ${error.message || JSON.stringify(error)}`);
375
- } finally {
376
- setLoading(false);
452
+ setResult(`Billing Error: ${error.message || 'Unknown error'}`);
453
+ Alert.alert('Billing Error', error.message || 'An error occurred during billing');
377
454
  }
378
455
  };
379
456
  ```
380
457
 
381
- #### Main Payment Handler
458
+ #### Helper Function for JSON Parsing
382
459
 
383
460
  ```javascript
384
- const handlePayment = async () => {
385
- if (!amount || isNaN(parseFloat(amount)) || parseFloat(amount) <= 0) {
386
- return Alert.alert('Error', 'Please enter a valid amount');
387
- }
388
-
389
- if (isRecurring && (!recurringData.intervals || recurringData.intervals.length === 0)) {
390
- return Alert.alert('Error', 'Please select at least one interval for recurring payment');
391
- }
392
-
393
- setLoading(true);
394
- const timeoutId = setTimeout(() => setLoading(false), 3000);
395
-
396
- try {
397
- if (Platform.OS === 'android') {
398
- await handleAndroidBilling();
399
- } else {
400
- await handleIosBilling();
461
+ const safeParseMaybeJSON = (value) => {
462
+ if (typeof value === 'string') {
463
+ try {
464
+ return JSON.parse(value);
465
+ } catch (e) {
466
+ console.warn('Failed to parse JSON string:', value);
467
+ return value;
401
468
  }
402
- } finally {
403
- clearTimeout(timeoutId);
404
- setLoading(false);
405
469
  }
470
+ return value;
406
471
  };
407
472
  ```
408
473
 
409
- ### 4. Event Listeners for Android
474
+ ### 5. Android Event Listeners
410
475
 
411
- Set up event listeners for payment success, status, and errors using `NativeEventEmitter` (Android only):
476
+ For Android, set up event listeners to handle payment success, status, and errors:
412
477
 
413
478
  ```javascript
414
479
  useEffect(() => {
415
480
  if (Platform.OS !== 'android') return;
481
+ if (!RNEasymerchantsdk) {
482
+ console.warn('RNEasymerchantsdk native module is not available.');
483
+ return;
484
+ }
416
485
 
417
486
  const easyMerchantEvents = new NativeEventEmitter(RNEasymerchantsdk);
418
-
419
487
  const successSub = easyMerchantEvents.addListener('PaymentSuccess', (data) => {
420
- const parsed = JSON.parse(data.response);
421
- setResult(JSON.stringify(parsed, null, 2));
488
+ const parsed = JSON.parse(data.response || '{}');
489
+ setResult(JSON.stringify({
490
+ ...parsed,
491
+ billingInfo: safeParseMaybeJSON(parsed.billingInfo),
492
+ additional_info: safeParseMaybeJSON(parsed.additional_info),
493
+ }, null, 2));
422
494
  });
423
-
424
495
  const statusSub = easyMerchantEvents.addListener('PaymentStatus', (data) => {
425
- const parsed = JSON.parse(data.statusResponse);
496
+ const parsed = JSON.parse(data.statusResponse || '{}');
426
497
  setResult(JSON.stringify(parsed, null, 2));
427
498
  });
428
-
429
499
  const statusErrorSub = easyMerchantEvents.addListener('PaymentStatusError', (data) => {
430
500
  setResult(`Status Error: ${JSON.stringify(data.error, null, 2)}`);
431
501
  });
@@ -438,24 +508,20 @@ useEffect(() => {
438
508
  }, []);
439
509
  ```
440
510
 
441
- ### 5. UI Components
442
-
443
- The provided `App.js` includes custom components like `Dropdown` and `FilledButton` for a user-friendly interface. Customize the styles in the `StyleSheet` to match your app's design.
444
-
445
511
  ## Notes
446
512
 
447
- - **Billing Info**: You can send `null` for `billingInfo` if it is not available.
448
- - **Environment Configuration**: The SDK supports `sandbox` and `staging` environments. Ensure you configure the correct API keys for each environment.
449
- - **Payment Methods**: The SDK supports `card` and `ach` payment methods (mapped to `Card` and `Bank` on iOS). Toggle them in the UI as needed.
450
- - **Recurring Payments**: Ensure at least one interval (`daily`, `weekly`, `monthly`) is selected when enabling recurring payments.
451
- - **Theming**: Customize the appearance using `themeConfiguration` for iOS or `configur.appearanceSettings` for Android to match your app's branding. The parameters are identical for both platforms.
452
- - **Method Differences**:
453
- - **Android**: Use `RNEasymerchantsdk.makePayment(config)` with a JSON configuration object.
454
- - **iOS**: Use `EasyMerchantSdk.billing(...)` with parameters passed directly.
455
- - iOS supports an additional `paymentReference` method for checking payment status using a reference token.
513
+ - **Billing Info**: Set `billingInfo` to `null` if not needed. Required fields are configurable via `billingRequired` and `additionalRequired`.
514
+ - **Payment Methods**: Supported methods are `card` and `ach` (mapped to `Card` and `Bank` on iOS). Ensure at least one is selected in `androidConfig.paymentMethods`.
515
+ - **Recurring Payments**: Requires at least one interval (`daily`, `weekly`, `monthly`) when enabled.
516
+ - **Security**: Store API keys and secret keys securely (e.g., in environment variables or secure storage) rather than hardcoding.
517
+ - **Platform Differences**:
518
+ - **Android**: Uses `RNEasymerchantsdk.makePayment(config)` with a JSON config object. Payment methods are lowercase (`['card', 'ach']`).
519
+ - **iOS**: Uses `EasyMerchantSdk.billing(...)` with parameters passed directly. Payment methods are capitalized (`['Card', 'Bank']`).
520
+ - iOS supports `paymentReference` for status checks; Android uses `checkPaymentStatus`.
456
521
 
457
522
  ## Troubleshooting
458
523
 
459
- - **iOS Bridge Initialization**: If you see "Failed to retrieve EasyMerchantSdkPlugin instance" in the console, ensure the `easymerchantsdk` pod is correctly installed and linked.
460
- - **Android Payment Issues**: Verify that `paymentMethod` is correctly formatted (`['card', 'ach']`) and that API keys are valid. Ensure `GITHUB_URL`, `GITHUB_USERNAME`, and `GITHUB_PASSWORD` are correctly set in your Gradle properties.
524
+ - **iOS Bridge Initialization**: If you see "Failed to retrieve EasyMerchantSdkPlugin instance" in the console, verify that the `easymerchantsdk` pod is installed and linked correctly. Run `pod install --repo-update` and check `AppDelegate.swift`.
525
+ - **Android Payment Issues**: Ensure `paymentMethods` is formatted as `['card', 'ach']` and that API keys are valid. Verify `GITHUB_URL`, `GITHUB_USERNAME`, and `GITHUB_PASSWORD` in `gradle.properties`.
461
526
  - **Pod Installation**: If `pod install` fails, ensure Ruby 3.2.8 is installed and run `pod install --repo-update`.
527
+ - **Payment Failures**: Check console logs for detailed errors. Validate that `amount` is a positive number, payment methods are selected, and API keys are correct.
@@ -1,2 +1,2 @@
1
- #Fri Aug 08 13:51:00 IST 2025
2
- gradle.version=8.9
1
+ #Tue Aug 19 19:48:34 IST 2025
2
+ gradle.version=8.10
@@ -1 +1 @@
1
- #Fri Aug 15 11:27:45 IST 2025
1
+ #Wed Aug 20 09:54:15 IST 2025
@@ -118,12 +118,26 @@ public class RNEasymerchantsdkModule extends ReactContextBaseJavaModule {
118
118
  }
119
119
 
120
120
 
121
- JSONArray paymentMethods = new JSONArray();
122
- ReadableArray methods = jsonConfigMap.getArray("paymentMethod");
123
- for (int i = 0; i < methods.size(); i++) {
124
- paymentMethods.put(methods.getString(i));
121
+ // Payment Methods
122
+ if (jsonConfigMap.hasKey("paymentMethods") && !jsonConfigMap.isNull("paymentMethods")) {
123
+ ReadableArray methods = jsonConfigMap.getArray("paymentMethods");
124
+ JSONArray paymentMethods = new JSONArray();
125
+
126
+ for (int i = 0; i < methods.size(); i++) {
127
+ if (methods.getType(i) == ReadableType.String) {
128
+ // Case: simple array of strings
129
+ paymentMethods.put(methods.getString(i));
130
+ } else if (methods.getType(i) == ReadableType.Map) {
131
+ // Case: array of objects
132
+ ReadableMap item = methods.getMap(i);
133
+ JSONObject obj = new JSONObject(item.toHashMap());
134
+ paymentMethods.put(obj);
135
+ }
136
+ }
137
+
138
+ jsonConfig.put("paymentMethods", paymentMethods);
125
139
  }
126
- jsonConfig.put("paymentMethod", paymentMethods);
140
+
127
141
 
128
142
  // Recurring (flattened to match SDK)
129
143
  if (jsonConfigMap.hasKey("recurring")) {
@@ -1,6 +1,6 @@
1
1
  Pod::Spec.new do |s|
2
2
  s.name = 'easymerchantsdk'
3
- s.version = '2.1.1'
3
+ s.version = '2.1.3'
4
4
  s.summary = 'A React Native SDK for Easy Merchant.'
5
5
  s.description = <<-DESC
6
6
  A React Native SDK to enable Easy Merchant functionality in mobile applications.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jimrising/easymerchantsdk-react-native",
3
- "version": "2.1.1",
3
+ "version": "2.1.3",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {