@jimrising/easymerchantsdk-react-native 2.0.7 → 2.1.0

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 (121) hide show
  1. package/README.md +248 -1801
  2. package/android/build/.transforms/15b6a8a60a6b32d0dcaf609723cf365b/transformed/classes/classes_dex/classes.dex +0 -0
  3. package/android/build/.transforms/8508f1428f740032c45a43f48b1bbe1e/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkModule$1$1.dex +0 -0
  4. package/android/build/.transforms/8508f1428f740032c45a43f48b1bbe1e/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkModule$1.dex +0 -0
  5. package/android/build/.transforms/8508f1428f740032c45a43f48b1bbe1e/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkModule$2.dex +0 -0
  6. package/android/build/.transforms/8508f1428f740032c45a43f48b1bbe1e/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkModule.dex +0 -0
  7. package/android/build/.transforms/eef2d06269ef2e204b4f065513034fca/transformed/classes/classes_dex/classes.dex +0 -0
  8. package/android/build/.transforms/ffabb40f9809b32eb9546ce76fc51764/transformed/bundleLibRuntimeToDirRelease/bundleLibRuntimeToDirRelease_dex/com/reactlibrary/RNEasymerchantsdkModule$1$1.dex +0 -0
  9. package/android/build/.transforms/ffabb40f9809b32eb9546ce76fc51764/transformed/bundleLibRuntimeToDirRelease/bundleLibRuntimeToDirRelease_dex/com/reactlibrary/RNEasymerchantsdkModule$1.dex +0 -0
  10. package/android/build/.transforms/ffabb40f9809b32eb9546ce76fc51764/transformed/bundleLibRuntimeToDirRelease/bundleLibRuntimeToDirRelease_dex/com/reactlibrary/RNEasymerchantsdkModule$2.dex +0 -0
  11. package/android/build/.transforms/ffabb40f9809b32eb9546ce76fc51764/transformed/bundleLibRuntimeToDirRelease/bundleLibRuntimeToDirRelease_dex/com/reactlibrary/RNEasymerchantsdkModule.dex +0 -0
  12. package/android/build/intermediates/aar_main_jar/release/syncReleaseLibJars/classes.jar +0 -0
  13. package/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
  14. package/android/build/intermediates/compile_library_classes_jar/release/bundleLibCompileToJarRelease/classes.jar +0 -0
  15. package/android/build/intermediates/full_jar/release/createFullJarRelease/full.jar +0 -0
  16. package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +1 -1
  17. package/android/build/intermediates/incremental/lintVitalAnalyzeRelease/release-artifact-dependencies.xml +4 -4
  18. package/android/build/intermediates/incremental/lintVitalAnalyzeRelease/release-artifact-libraries.xml +4 -4
  19. package/android/build/intermediates/incremental/release/mergeReleaseResources/compile-file-map.properties +838 -838
  20. package/android/build/intermediates/incremental/release/mergeReleaseResources/merger.xml +3 -3
  21. package/android/build/intermediates/incremental/release/packageReleaseResources/compile-file-map.properties +1 -1
  22. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule$1$1.class +0 -0
  23. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule$1.class +0 -0
  24. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule$2.class +0 -0
  25. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule.class +0 -0
  26. package/android/build/intermediates/javac/release/compileReleaseJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule$1$1.class +0 -0
  27. package/android/build/intermediates/javac/release/compileReleaseJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule$1.class +0 -0
  28. package/android/build/intermediates/javac/release/compileReleaseJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule$2.class +0 -0
  29. package/android/build/intermediates/javac/release/compileReleaseJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule.class +0 -0
  30. package/android/build/intermediates/lint-cache/lintVitalAnalyzeRelease/maven.google/androidx/core/group-index.xml +4 -3
  31. package/android/build/intermediates/lint-cache/lintVitalAnalyzeRelease/maven.google/androidx/lifecycle/group-index.xml +165 -165
  32. package/android/build/intermediates/lint-cache/lintVitalAnalyzeRelease/maven.google/com/android/tools/build/group-index.xml +15 -15
  33. package/android/build/intermediates/lint-cache/lintVitalAnalyzeRelease/sdk_index/snapshot.gz +0 -0
  34. package/android/build/intermediates/lint_model/release/generateReleaseLintModel/release-artifact-dependencies.xml +4 -4
  35. package/android/build/intermediates/lint_model/release/generateReleaseLintModel/release-artifact-libraries.xml +4 -4
  36. package/android/build/intermediates/lint_vital_lint_model/release/generateReleaseLintVitalModel/release-artifact-dependencies.xml +4 -4
  37. package/android/build/intermediates/lint_vital_lint_model/release/generateReleaseLintVitalModel/release-artifact-libraries.xml +4 -4
  38. package/android/build/intermediates/local_aar_for_lint/release/out.aar +0 -0
  39. package/android/build/intermediates/merged_res/release/mergeReleaseResources/layout/activity_card_addition_ifo.xml +1 -0
  40. package/android/build/intermediates/merged_res/release/mergeReleaseResources/layout/activity_card_billing_info.xml +1 -0
  41. package/android/build/intermediates/merged_res/release/mergeReleaseResources/layout/activity_card_scan.xml +1 -0
  42. package/android/build/intermediates/merged_res/release/mergeReleaseResources/layout/activity_payment_done.xml +1 -0
  43. package/android/build/intermediates/merged_res/release/mergeReleaseResources/layout/activity_payment_done_url.xml +1 -0
  44. package/android/build/intermediates/merged_res/release/mergeReleaseResources/layout/activity_payment_error.xml +1 -0
  45. package/android/build/intermediates/merged_res/release/mergeReleaseResources/layout/activity_select_payment_method.xml +1 -0
  46. package/android/build/intermediates/merged_res/release/mergeReleaseResources/layout/activity_verify_email.xml +1 -0
  47. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/multi-v2/values-night-v8.json +19 -19
  48. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/multi-v2/values.json +38 -38
  49. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/anim-v21.json +9 -9
  50. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/anim.json +24 -24
  51. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/animator-v21.json +1 -1
  52. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/animator.json +34 -34
  53. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/color-night-v8.json +3 -3
  54. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/color-v31.json +10 -10
  55. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/color.json +153 -153
  56. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/drawable-hdpi-v4.json +1 -1
  57. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/drawable-mdpi-v4.json +1 -1
  58. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/drawable-v21.json +3 -3
  59. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/drawable-v23.json +7 -7
  60. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/drawable-xhdpi-v4.json +1 -1
  61. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/drawable-xxhdpi-v4.json +1 -1
  62. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/drawable-xxxhdpi-v4.json +1 -1
  63. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/drawable.json +391 -391
  64. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/font.json +9 -9
  65. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/interpolator-v21.json +10 -10
  66. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/interpolator.json +11 -11
  67. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/layout-land.json +3 -3
  68. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/layout-sw600dp-v13.json +2 -2
  69. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/layout-v26.json +1 -1
  70. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/layout.json +98 -98
  71. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/mipmap-anydpi-v26.json +2 -2
  72. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/mipmap-hdpi-v4.json +2 -2
  73. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/mipmap-mdpi-v4.json +2 -2
  74. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/mipmap-xhdpi-v4.json +2 -2
  75. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/mipmap-xxhdpi-v4.json +2 -2
  76. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/mipmap-xxxhdpi-v4.json +2 -2
  77. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/raw.json +46 -46
  78. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/xml.json +3 -3
  79. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/RNEasymerchantsdkModule$1$1.class +0 -0
  80. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/RNEasymerchantsdkModule$1.class +0 -0
  81. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/RNEasymerchantsdkModule$2.class +0 -0
  82. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/RNEasymerchantsdkModule.class +0 -0
  83. package/android/build/intermediates/runtime_library_classes_dir/release/bundleLibRuntimeToDirRelease/com/reactlibrary/RNEasymerchantsdkModule$1$1.class +0 -0
  84. package/android/build/intermediates/runtime_library_classes_dir/release/bundleLibRuntimeToDirRelease/com/reactlibrary/RNEasymerchantsdkModule$1.class +0 -0
  85. package/android/build/intermediates/runtime_library_classes_dir/release/bundleLibRuntimeToDirRelease/com/reactlibrary/RNEasymerchantsdkModule$2.class +0 -0
  86. package/android/build/intermediates/runtime_library_classes_dir/release/bundleLibRuntimeToDirRelease/com/reactlibrary/RNEasymerchantsdkModule.class +0 -0
  87. package/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
  88. package/android/build/intermediates/runtime_library_classes_jar/release/bundleLibRuntimeToJarRelease/classes.jar +0 -0
  89. package/android/build/intermediates/source_set_path_map/release/mapReleaseSourceSetPaths/file-map.txt +24 -24
  90. package/android/build/intermediates/verified_library_resources/release/verifyReleaseResources/compiled/layout_activity_card_addition_ifo.xml.flat +0 -0
  91. package/android/build/intermediates/verified_library_resources/release/verifyReleaseResources/compiled/layout_activity_card_billing_info.xml.flat +0 -0
  92. package/android/build/intermediates/verified_library_resources/release/verifyReleaseResources/compiled/layout_activity_card_scan.xml.flat +0 -0
  93. package/android/build/intermediates/verified_library_resources/release/verifyReleaseResources/compiled/layout_activity_payment_done.xml.flat +0 -0
  94. package/android/build/intermediates/verified_library_resources/release/verifyReleaseResources/compiled/layout_activity_payment_done_url.xml.flat +0 -0
  95. package/android/build/intermediates/verified_library_resources/release/verifyReleaseResources/compiled/layout_activity_payment_error.xml.flat +0 -0
  96. package/android/build/intermediates/verified_library_resources/release/verifyReleaseResources/compiled/layout_activity_select_payment_method.xml.flat +0 -0
  97. package/android/build/intermediates/verified_library_resources/release/verifyReleaseResources/compiled/layout_activity_verify_email.xml.flat +0 -0
  98. package/android/build/outputs/aar/jimrising_easymerchantsdk-react-native-release.aar +0 -0
  99. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/RNEasymerchantsdkModule$1$1.class.uniqueId1 +0 -0
  100. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/RNEasymerchantsdkModule$1.class.uniqueId0 +0 -0
  101. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/RNEasymerchantsdkModule$2.class.uniqueId3 +0 -0
  102. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/RNEasymerchantsdkModule.class.uniqueId2 +0 -0
  103. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/RNEasymerchantsdkPackage.class.uniqueId4 +0 -0
  104. package/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
  105. package/android/build/tmp/compileReleaseJavaWithJavac/previous-compilation-data.bin +0 -0
  106. package/android/build.gradle +1 -1
  107. package/android/src/main/java/com/reactlibrary/RNEasymerchantsdkModule.java +93 -26
  108. package/ios/Classes/EasyMerchantSdk.m +6 -6
  109. package/ios/Classes/EasyMerchantSdk.swift +116 -60
  110. package/ios/Classes/EasyPayViewController.swift +3 -5
  111. package/ios/CustomComponents/CheckboxButton.swift +66 -0
  112. package/ios/Helper/GrailPayHelper.swift +1 -0
  113. package/ios/Models/Request.swift +8 -8
  114. package/ios/Pods/ViewControllers/AdditionalInfoVC.swift +233 -97
  115. package/ios/Pods/ViewControllers/BillingInfoVC/BillingInfoVC.swift +376 -104
  116. package/ios/Pods/ViewControllers/OTPVerificationVC.swift +28 -27
  117. package/ios/Pods/ViewControllers/PaymentErrorVC.swift +22 -25
  118. package/ios/Pods/ViewControllers/PaymentInformation/PaymentInfoVC.swift +575 -190
  119. package/ios/easymerchantsdk.podspec +1 -1
  120. package/ios/easymerchantsdk.storyboard +15 -15
  121. package/package.json +1 -1
@@ -8,6 +8,8 @@ import com.app.paysdk.service.EasyPaymentService;
8
8
  import com.facebook.react.bridge.*;
9
9
  import org.json.*;
10
10
  import java.util.Map;
11
+ import java.util.Iterator;
12
+
11
13
 
12
14
  import java.io.File;
13
15
  import java.io.FileInputStream;
@@ -123,28 +125,61 @@ public class RNEasymerchantsdkModule extends ReactContextBaseJavaModule {
123
125
  }
124
126
  jsonConfig.put("paymentMethod", paymentMethods);
125
127
 
126
- // Recurring
128
+ // Recurring (flattened to match SDK)
127
129
  if (jsonConfigMap.hasKey("recurring")) {
128
130
  ReadableMap recurringMap = jsonConfigMap.getMap("recurring");
129
- JSONObject recurring = new JSONObject();
130
- recurring.put("enableRecurring", recurringMap.getBoolean("enableRecurring"));
131
- if (recurringMap.hasKey("recurringData")) {
132
- ReadableMap data = recurringMap.getMap("recurringData");
133
- JSONObject recurringData = new JSONObject();
134
- recurringData.put("allowCycles", data.getInt("allowCycles"));
135
- JSONArray intervals = new JSONArray();
136
- ReadableArray intervalArray = data.getArray("intervals");
137
- for (int i = 0; i < intervalArray.size(); i++) {
138
- intervals.put(intervalArray.getString(i));
131
+
132
+ if (recurringMap.hasKey("enableRecurring") && recurringMap.getBoolean("enableRecurring")) {
133
+ jsonConfig.put("is_recurring", true);
134
+
135
+ if (recurringMap.hasKey("recurringData")) {
136
+ ReadableMap data = recurringMap.getMap("recurringData");
137
+
138
+ if (data.hasKey("allowCycles")) {
139
+ jsonConfig.put("numOfCycle", data.getInt("allowCycles"));
140
+ }
141
+
142
+ if (data.hasKey("intervals")) {
143
+ JSONArray intervals = new JSONArray();
144
+ ReadableArray intervalArray = data.getArray("intervals");
145
+ for (int i = 0; i < intervalArray.size(); i++) {
146
+ intervals.put(intervalArray.getString(i));
147
+ }
148
+ jsonConfig.put("recurringIntervals", intervals);
149
+ }
150
+
151
+ if (data.hasKey("recurringStartType")) {
152
+ jsonConfig.put("recurringStartDateType", data.getString("recurringStartType"));
153
+ }
154
+
155
+ if (data.hasKey("recurringStartDate")) {
156
+ jsonConfig.put("recurringStartDate", data.getString("recurringStartDate"));
157
+ }
139
158
  }
140
- recurringData.put("intervals", intervals);
141
- recurringData.put("recurringStartType", data.getString("recurringStartType"));
142
- recurringData.put("recurringStartDate", data.getString("recurringStartDate"));
143
- recurring.put("recurringData", recurringData);
144
159
  }
145
- jsonConfig.put("recurring", recurring);
146
160
  }
147
161
 
162
+ // Appearance settings (fix typo handling)
163
+ if (jsonConfigMap.hasKey("appearanceSettings")) {
164
+ JSONObject appearance = new JSONObject();
165
+ ReadableMap appMap = jsonConfigMap.getMap("appearanceSettings");
166
+ for (Map.Entry<String, Object> entry : appMap.toHashMap().entrySet()) {
167
+ appearance.put(entry.getKey(), entry.getValue());
168
+ }
169
+ jsonConfig.put("appearanceSettings", appearance);
170
+ jsonConfig.put("apperanceSettings", appearance); // duplicate for SDK compatibility
171
+ } else if (jsonConfigMap.hasKey("apperanceSettings")) {
172
+ // backwards case: copy typo version into correct key
173
+ JSONObject appearance = new JSONObject();
174
+ ReadableMap appMap = jsonConfigMap.getMap("apperanceSettings");
175
+ for (Map.Entry<String, Object> entry : appMap.toHashMap().entrySet()) {
176
+ appearance.put(entry.getKey(), entry.getValue());
177
+ }
178
+ jsonConfig.put("appearanceSettings", appearance);
179
+ jsonConfig.put("apperanceSettings", appearance);
180
+ }
181
+
182
+
148
183
  // Fields
149
184
  if (jsonConfigMap.hasKey("fields")) {
150
185
  ReadableMap fieldsMap = jsonConfigMap.getMap("fields");
@@ -194,15 +229,8 @@ public class RNEasymerchantsdkModule extends ReactContextBaseJavaModule {
194
229
  jsonConfig.put("grailPayParams", grail);
195
230
  }
196
231
 
197
- // Appearance Settings
198
- if (jsonConfigMap.hasKey("appearanceSettings")) {
199
- ReadableMap a = jsonConfigMap.getMap("appearanceSettings");
200
- JSONObject appearance = new JSONObject();
201
- for (Map.Entry<String, Object> entry : a.toHashMap().entrySet()) {
202
- appearance.put(entry.getKey(), entry.getValue());
203
- }
204
- jsonConfig.put("appearanceSettings", appearance);
205
- }
232
+
233
+
206
234
 
207
235
  EasyPaymentFactory factory = EasyPaymentFactory.INSTANCE;
208
236
  EasyPaymentService service = factory.create(currentActivity);
@@ -276,12 +304,15 @@ public class RNEasymerchantsdkModule extends ReactContextBaseJavaModule {
276
304
  @Override
277
305
  public void onFailure(JSONObject error) {
278
306
  WritableMap statusError = Arguments.createMap();
279
- statusError.putString("statusError", error.toString());
307
+
308
+ // Convert JSONObject → WritableMap
309
+ statusError.putMap("statusError", convertJsonToMap(error));
280
310
 
281
311
  reactContext
282
312
  .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
283
313
  .emit("PaymentStatusError", statusError);
284
314
  }
315
+
285
316
  });
286
317
 
287
318
  }
@@ -295,7 +326,15 @@ public class RNEasymerchantsdkModule extends ReactContextBaseJavaModule {
295
326
  @Override
296
327
  public void onError(String error) {
297
328
  promise.reject("PAYMENT_ERROR", error);
329
+
330
+ WritableMap errorResult = Arguments.createMap();
331
+ errorResult.putString("error", error);
332
+
333
+ reactContext
334
+ .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
335
+ .emit("PaymentStatusError", errorResult);
298
336
  }
337
+
299
338
  });
300
339
 
301
340
 
@@ -307,6 +346,34 @@ public class RNEasymerchantsdkModule extends ReactContextBaseJavaModule {
307
346
  });
308
347
  }
309
348
 
349
+ private WritableMap convertJsonToMap(JSONObject jsonObject) {
350
+ WritableMap map = Arguments.createMap();
351
+ Iterator<String> keys = jsonObject.keys();
352
+
353
+ while (keys.hasNext()) {
354
+ String key = keys.next();
355
+ try {
356
+ Object value = jsonObject.get(key);
357
+ if (value instanceof JSONObject) {
358
+ map.putMap(key, convertJsonToMap((JSONObject) value));
359
+ } else if (value instanceof Boolean) {
360
+ map.putBoolean(key, (Boolean) value);
361
+ } else if (value instanceof Integer) {
362
+ map.putInt(key, (Integer) value);
363
+ } else if (value instanceof Double) {
364
+ map.putDouble(key, (Double) value);
365
+ } else {
366
+ map.putString(key, value.toString());
367
+ }
368
+ } catch (Exception e) {
369
+ e.printStackTrace();
370
+ }
371
+ }
372
+
373
+ return map;
374
+ }
375
+
376
+
310
377
  @ReactMethod
311
378
  public void checkPaymentStatus(Promise promise) {
312
379
  Activity currentActivity = getCurrentActivity();
@@ -2,8 +2,8 @@
2
2
  #import <React/RCTLog.h>
3
3
  #import <React/RCTBridgeModule.h>
4
4
 
5
- //#import <easymerchantsdk-Swift.h>
6
- #import <easymerchantsdk/easymerchantsdk-Swift.h>
5
+ #import <easymerchantsdk-Swift.h>
6
+ //#import <easymerchantsdk/easymerchantsdk-Swift.h>
7
7
 
8
8
 
9
9
  @interface EasyMerchantSdk ()
@@ -31,9 +31,9 @@ RCT_EXPORT_METHOD(configureEnvironment:(NSString *)env
31
31
  RCT_EXPORT_METHOD(
32
32
  billing:(NSString *)amount
33
33
  currency:(NSString *)currency
34
- billingInfo:(NSDictionary *)billingInfo
34
+ fields:(NSDictionary *)fields
35
35
  paymentMethods:(NSArray *)paymentMethods
36
- themeConfiguration:(NSDictionary *)themeConfiguration
36
+ appearanceSettings:(NSDictionary *)appearanceSettings
37
37
  tokenOnly:(BOOL)tokenOnly
38
38
  saveCard:(BOOL)saveCard
39
39
  saveAccount:(BOOL)saveAccount
@@ -63,9 +63,9 @@ RCT_EXPORT_METHOD(
63
63
  @try {
64
64
  [self.sdkPluginInstance billing:amount
65
65
  currency:currency
66
- billingInfo:billingInfo
66
+ fields:fields
67
67
  paymentMethods:paymentMethods
68
- themeConfiguration:themeConfiguration
68
+ appearanceSettings:appearanceSettings
69
69
  tokenOnly:tokenOnly
70
70
  saveCard:saveCard
71
71
  saveAccount:saveAccount
@@ -1,7 +1,6 @@
1
1
  import Foundation
2
2
  import UIKit
3
3
  import React
4
- //import EasyPay // Import the EasyPay module
5
4
 
6
5
  @objc(EasyMerchantSdkPlugin)
7
6
  public class EasyMerchantSdkPlugin: NSObject, RCTBridgeModule {
@@ -10,8 +9,9 @@ public class EasyMerchantSdkPlugin: NSObject, RCTBridgeModule {
10
9
  public static func moduleName() -> String! {
11
10
  return "EasyMerchantSdk"
12
11
  }
13
-
12
+
14
13
  public static func requiresMainQueueSetup() -> Bool {
14
+ // We present view controllers and touch UIKit; main queue required.
15
15
  return true
16
16
  }
17
17
 
@@ -23,9 +23,12 @@ public class EasyMerchantSdkPlugin: NSObject, RCTBridgeModule {
23
23
  private var paymentReferenceResolver: RCTPromiseResolveBlock?
24
24
  private var paymentReferenceRejecter: RCTPromiseRejectBlock?
25
25
 
26
+ // MARK: - Notification tokens (so we can remove safely)
27
+ private var clientTokenObserver: NSObjectProtocol?
28
+ private var referenceObserver: NSObjectProtocol?
29
+
26
30
  // MARK: - View Controller Reference
27
- private let viewControllerQueue = DispatchQueue(label: "com.easymerchantsdk.viewController")
28
- private var viewController: UIViewController?
31
+ private weak var viewController: UIViewController?
29
32
 
30
33
  // MARK: - Init
31
34
  @objc public override init() {
@@ -40,8 +43,9 @@ public class EasyMerchantSdkPlugin: NSObject, RCTBridgeModule {
40
43
 
41
44
  // Expose setter for RN to inject the host view controller
42
45
  @objc public func setViewController(_ vc: UIViewController) {
43
- viewControllerQueue.sync {
44
- self.viewController = vc
46
+ // Always set on main thread; keep a weak ref to avoid retain cycles.
47
+ DispatchQueue.main.async { [weak self] in
48
+ self?.viewController = vc
45
49
  }
46
50
  }
47
51
 
@@ -58,9 +62,9 @@ public class EasyMerchantSdkPlugin: NSObject, RCTBridgeModule {
58
62
  @objc public func billing(
59
63
  _ amount: String,
60
64
  currency: String?,
61
- billingInfo: [String: Any]?,
65
+ fields: [String: Any]?,
62
66
  paymentMethods: [String],
63
- themeConfiguration: [String: Any]?,
67
+ appearanceSettings: [String: Any]?,
64
68
  tokenOnly: Bool,
65
69
  saveCard: Bool,
66
70
  saveAccount: Bool,
@@ -76,11 +80,11 @@ public class EasyMerchantSdkPlugin: NSObject, RCTBridgeModule {
76
80
  showReceipt: Bool,
77
81
  showTotal: Bool,
78
82
  showSubmitButton: Bool,
79
- isEmail : Bool,
83
+ isEmail: Bool,
80
84
  email: String?,
81
85
  name: String?,
82
86
  enable3DS: Bool,
83
- metadata: [String: Any]?,
87
+ metadata: [String: Any]?,
84
88
  resolver: @escaping RCTPromiseResolveBlock,
85
89
  rejecter: @escaping RCTPromiseRejectBlock
86
90
  ) {
@@ -92,7 +96,7 @@ public class EasyMerchantSdkPlugin: NSObject, RCTBridgeModule {
92
96
 
93
97
  // 2) Process billing info into FieldSection
94
98
  var billingInfoData: Data? = nil
95
- if let billingDict = billingInfo {
99
+ if let billingDict = fields {
96
100
  var billingFields: [FieldItem] = []
97
101
  var additionalFields: [FieldItem] = []
98
102
  var billingVisibility = true
@@ -126,14 +130,14 @@ public class EasyMerchantSdkPlugin: NSObject, RCTBridgeModule {
126
130
  additionalVisibility = visibility["additional"] ?? true
127
131
  }
128
132
 
129
- let fields = FieldSection(
133
+ let field = FieldSection(
130
134
  visibility: FieldsVisibility(billing: billingVisibility, additional: additionalVisibility),
131
135
  billing: billingFields,
132
136
  additional: additionalFields
133
137
  )
134
138
 
135
139
  do {
136
- billingInfoData = try JSONEncoder().encode(fields)
140
+ billingInfoData = try JSONEncoder().encode(field)
137
141
  } catch {
138
142
  rejecter("INVALID_BILLING_INFO", "Failed to encode billing info: \(error.localizedDescription)", nil)
139
143
  return
@@ -155,8 +159,6 @@ public class EasyMerchantSdkPlugin: NSObject, RCTBridgeModule {
155
159
  var grailParams: GrailPayRequest? = nil
156
160
  if authenticatedACH, let params = grailPayParams {
157
161
  grailParams = GrailPayRequest(
158
- // accessToken: params["accessToken"] as? String ?? "251|uTijpDGfrS88UR2V1cZNMQ8S4hUJA0sVzsnsoUZF",
159
- // vendorId: params["vendorId"] as? String ?? "251",
160
162
  role: params["role"] as? String ?? "business",
161
163
  timeout: params["timeout"] as? Int ?? 10,
162
164
  isSandbox: params["isSandbox"] as? Bool ?? true,
@@ -168,20 +170,20 @@ public class EasyMerchantSdkPlugin: NSObject, RCTBridgeModule {
168
170
 
169
171
  // 5) Build theme config
170
172
  let themeConfig = ThemeConfiguration(
171
- bodyBackgroundColor: themeConfiguration?["bodyBackgroundColor"] as? String ?? "#121212",
172
- containerBackgroundColor: themeConfiguration?["containerBackgroundColor"] as? String ?? "#1E1E1E",
173
- primaryFontColor: themeConfiguration?["primaryFontColor"] as? String ?? "#FFFFFF",
174
- secondaryFontColor: themeConfiguration?["secondaryFontColor"] as? String ?? "#B0B0B0",
175
- primaryButtonBackgroundColor: themeConfiguration?["primaryButtonBackgroundColor"] as? String ?? "#2563EB",
176
- primaryButtonHoverColor: themeConfiguration?["primaryButtonHoverColor"] as? String ?? "#1D4ED8",
177
- primaryButtonFontColor: themeConfiguration?["primaryButtonFontColor"] as? String ?? "#FFFFFF",
178
- secondaryButtonBackgroundColor: themeConfiguration?["secondaryButtonBackgroundColor"] as? String ?? "#374151",
179
- secondaryButtonHoverColor: themeConfiguration?["secondaryButtonHoverColor"] as? String ?? "#4B5563",
180
- secondaryButtonFontColor: themeConfiguration?["secondaryButtonFontColor"] as? String ?? "#E5E7EB",
181
- borderRadius: themeConfiguration?["borderRadius"] as? String ?? "8",
182
- fontSize: themeConfiguration?["fontSize"] as? String ?? "14",
183
- fontWeight: themeConfiguration?["fontWeight"] as? Int ?? 500,
184
- fontFamily: themeConfiguration?["fontFamily"] as? String ?? "\"Inter\", sans-serif"
173
+ bodyBackgroundColor: appearanceSettings?["bodyBackgroundColor"] as? String ?? "#121212",
174
+ containerBackgroundColor: appearanceSettings?["containerBackgroundColor"] as? String ?? "#1E1E1E",
175
+ primaryFontColor: appearanceSettings?["primaryFontColor"] as? String ?? "#FFFFFF",
176
+ secondaryFontColor: appearanceSettings?["secondaryFontColor"] as? String ?? "#B0B0B0",
177
+ primaryButtonBackgroundColor: appearanceSettings?["primaryButtonBackgroundColor"] as? String ?? "#2563EB",
178
+ primaryButtonHoverColor: appearanceSettings?["primaryButtonHoverColor"] as? String ?? "#1D4ED8",
179
+ primaryButtonFontColor: appearanceSettings?["primaryButtonFontColor"] as? String ?? "#FFFFFF",
180
+ secondaryButtonBackgroundColor: appearanceSettings?["secondaryButtonBackgroundColor"] as? String ?? "#374151",
181
+ secondaryButtonHoverColor: appearanceSettings?["secondaryButtonHoverColor"] as? String ?? "#4B5563",
182
+ secondaryButtonFontColor: appearanceSettings?["secondaryButtonFontColor"] as? String ?? "#E5E7EB",
183
+ borderRadius: appearanceSettings?["borderRadius"] as? String ?? "8",
184
+ fontSize: appearanceSettings?["fontSize"] as? String ?? "14",
185
+ fontWeight: appearanceSettings?["fontWeight"] as? Int ?? 500,
186
+ fontFamily: appearanceSettings?["fontFamily"] as? String ?? "\"Inter\", sans-serif"
185
187
  )
186
188
 
187
189
  // 6) Map recurring intervals
@@ -209,9 +211,9 @@ public class EasyMerchantSdkPlugin: NSObject, RCTBridgeModule {
209
211
  let request = Request(
210
212
  amount: amountValue,
211
213
  currency: currency ?? "usd",
212
- billingInfoData: billingInfoData,
214
+ fields: billingInfoData,
213
215
  paymentMethods: methods.isEmpty ? [.Card, .Bank] : methods,
214
- themeConfiguration: themeConfig,
216
+ appearanceSettings: themeConfig,
215
217
  tokenOnly: tokenOnly,
216
218
  saveCard: saveCard,
217
219
  saveAccount: saveAccount,
@@ -229,8 +231,8 @@ public class EasyMerchantSdkPlugin: NSObject, RCTBridgeModule {
229
231
  showSubmitButton: showSubmitButton,
230
232
  referenceID: enable3DS,
231
233
  referenceToken: nil,
232
- isEmail : isEmail,
233
- email:email,
234
+ isEmail: isEmail,
235
+ email: email,
234
236
  name: name,
235
237
  metadata: metadata
236
238
  )
@@ -241,7 +243,9 @@ public class EasyMerchantSdkPlugin: NSObject, RCTBridgeModule {
241
243
 
242
244
  // Handle tokenOnly or present EasyPayViewController
243
245
  if tokenOnly {
244
- NotificationCenter.default.addObserver(
246
+ // Register observer directly (no extra Dispatch wrapper).
247
+ // Store the token so we can remove it later.
248
+ clientTokenObserver = NotificationCenter.default.addObserver(
245
249
  forName: NSNotification.Name("ClientTokenReceived"),
246
250
  object: nil,
247
251
  queue: .main
@@ -255,11 +259,14 @@ public class EasyMerchantSdkPlugin: NSObject, RCTBridgeModule {
255
259
  self.clearResolvers()
256
260
  }
257
261
  } else {
258
- DispatchQueue.main.async {
262
+ // Always present on main thread
263
+ DispatchQueue.main.async { [weak self] in
264
+ guard let self = self else { return }
259
265
  let vc = EasyPayViewController(request: request, delegate: self)
266
+
260
267
  if let host = self.viewController {
261
268
  host.present(vc, animated: true, completion: nil)
262
- } else if let root = UIApplication.shared.windows.first(where: { $0.isKeyWindow })?.rootViewController {
269
+ } else if let root = Self.topMostViewController() {
263
270
  root.present(vc, animated: true, completion: nil)
264
271
  } else {
265
272
  rejecter("NO_VIEW_CONTROLLER", "Cannot find a view controller to present.", nil)
@@ -285,27 +292,25 @@ public class EasyMerchantSdkPlugin: NSObject, RCTBridgeModule {
285
292
  self.paymentReferenceResolver = resolver
286
293
  self.paymentReferenceRejecter = rejecter
287
294
 
288
- // Build the request object
289
- let request = Request(
295
+ // Build the request object (kept for parity; actual flow listens for a notification)
296
+ _ = Request(
290
297
  referenceID: true,
291
298
  referenceToken: referenceToken
292
299
  )
293
300
 
294
- // Set up notification observer for ReferenceIDResponse
295
- DispatchQueue.main.async {
296
- NotificationCenter.default.addObserver(
297
- forName: NSNotification.Name("ReferenceIDResponse"),
298
- object: nil,
299
- queue: .main
300
- ) { [weak self] notification in
301
- guard let self = self else { return }
302
- if let data = notification.object as? [String: Any] {
303
- self.paymentReferenceResolver?(data)
304
- } else {
305
- self.paymentReferenceRejecter?("INVALID_RESPONSE", "Invalid response data.", nil)
306
- }
307
- self.clearReferenceResolvers()
301
+ // Register observer directly (no outer Dispatch wrapper).
302
+ referenceObserver = NotificationCenter.default.addObserver(
303
+ forName: NSNotification.Name("ReferenceIDResponse"),
304
+ object: nil,
305
+ queue: .main
306
+ ) { [weak self] notification in
307
+ guard let self = self else { return }
308
+ if let data = notification.object as? [String: Any] {
309
+ self.paymentReferenceResolver?(data)
310
+ } else {
311
+ self.paymentReferenceRejecter?("INVALID_RESPONSE", "Invalid response data.", nil)
308
312
  }
313
+ self.clearReferenceResolvers()
309
314
  }
310
315
  }
311
316
 
@@ -321,28 +326,70 @@ public class EasyMerchantSdkPlugin: NSObject, RCTBridgeModule {
321
326
  private func clearResolvers() {
322
327
  billingResolver = nil
323
328
  billingRejecter = nil
329
+ if let token = clientTokenObserver {
330
+ NotificationCenter.default.removeObserver(token)
331
+ clientTokenObserver = nil
332
+ }
324
333
  }
325
334
 
326
335
  private func clearReferenceResolvers() {
327
336
  paymentReferenceResolver = nil
328
337
  paymentReferenceRejecter = nil
329
- NotificationCenter.default.removeObserver(self, name: NSNotification.Name("ReferenceIDResponse"), object: nil)
338
+ if let token = referenceObserver {
339
+ NotificationCenter.default.removeObserver(token)
340
+ referenceObserver = nil
341
+ }
342
+ // (Old approach of removing by name kept out to avoid double-removal.)
343
+ }
344
+
345
+ // Find a top-most VC safely (iOS 13+ friendly)
346
+ private static func topMostViewController(base: UIViewController? = {
347
+ // Use key window from connected scenes
348
+ return UIApplication.shared.connectedScenes
349
+ .compactMap { $0 as? UIWindowScene }
350
+ .flatMap { $0.windows }
351
+ .first(where: { $0.isKeyWindow })?
352
+ .rootViewController
353
+ }()) -> UIViewController? {
354
+ if let nav = base as? UINavigationController {
355
+ return topMostViewController(base: nav.visibleViewController)
356
+ }
357
+ if let tab = base as? UITabBarController, let selected = tab.selectedViewController {
358
+ return topMostViewController(base: selected)
359
+ }
360
+ if let presented = base?.presentedViewController {
361
+ return topMostViewController(base: presented)
362
+ }
363
+ return base
330
364
  }
331
365
  }
332
366
 
333
367
  // MARK: - Delegate Implementation
334
368
  extension EasyMerchantSdkPlugin: EasyPayViewControllerDelegate {
335
369
  public func easyPayController(_ controller: EasyPayViewController, didFinishWith result: SDKResult) {
336
- DispatchQueue.main.async {
370
+ let workItem = DispatchWorkItem { [weak self] in
371
+ guard let self = self else { return }
372
+
337
373
  switch result.type {
338
374
  case .cancelled:
339
- self.billingResolver?(["status": "cancelled", "message": "User cancelled"])
375
+ if let message = result.chargeData?["message"] as? String {
376
+ self.billingResolver?(["status": "cancelled", "message": message])
377
+ } else {
378
+ self.billingResolver?(["status": "cancelled"])
379
+ }
340
380
 
341
381
  case .success:
342
382
  var payload: [String: Any] = ["status": "success"]
343
- if let cd = result.chargeData { payload["chargeData"] = cd }
344
- if let bi = result.billingInfo { payload["billingInfo"] = bi }
345
- if let ai = result.additionalInfo { payload["additionalInfo"] = ai }
383
+
384
+ if let cd = result.chargeData {
385
+ payload["chargeData"] = cd
386
+ }
387
+ if let bi = result.billingInfo {
388
+ payload["billingInfo"] = bi
389
+ }
390
+ if let ai = result.additionalInfo {
391
+ payload["additionalInfo"] = ai
392
+ }
346
393
 
347
394
  // Extract referenceToken for 3DS
348
395
  if let additional = result.additionalInfo,
@@ -355,12 +402,21 @@ extension EasyMerchantSdkPlugin: EasyPayViewControllerDelegate {
355
402
  self.billingResolver?(payload)
356
403
 
357
404
  case .error:
358
- let errMsg = (result.chargeData?["errorMessage"] as? String) ?? "Unknown error"
359
- self.billingRejecter?("PAYMENT_ERROR", errMsg, nil)
405
+ // Check for an errorMessage in chargeData.
406
+ let errorMessage = (result.chargeData?["message"] as? String) ?? "An unknown error occurred."
407
+
408
+ let errorResponse: [String: Any] = [
409
+ "status": false,
410
+ "message": errorMessage
411
+ ]
412
+
413
+ self.billingResolver?(errorResponse)
360
414
  }
361
415
 
362
416
  self.clearResolvers()
363
417
  controller.dismiss(animated: true, completion: nil)
364
418
  }
419
+
420
+ DispatchQueue.main.async(execute: workItem)
365
421
  }
366
422
  }
@@ -45,7 +45,7 @@ public final class EasyPayViewController: UINavigationController {
45
45
  self.easyPayDelegate = delegate
46
46
  super.init(nibName: nil, bundle: nil)
47
47
 
48
- if let themeConfiguration = request.themeConfiguration {
48
+ if let themeConfiguration = request.appearanceSettings {
49
49
  UserStoreSingleton.shared.updateThemeConfiguration(with: themeConfiguration)
50
50
  }
51
51
 
@@ -61,15 +61,13 @@ public final class EasyPayViewController: UINavigationController {
61
61
  let vc = UIStoryboard(name: "easymerchantsdk", bundle: Bundle.easyPayBundle).instantiateViewController(withIdentifier: "PaymentInfoVC") as! PaymentInfoVC
62
62
  vc.modalPresentationStyle = .overFullScreen
63
63
  vc.configureWith(request: request, delegate: easyPayDelegate)
64
- vc.amount = Double(self.request.amount ?? 0)
65
-
64
+ vc.amount = Double(self.request.amount ?? 0) // Set the amount here.
66
65
  vc.selectedPaymentMethod = "Card"
67
66
 
68
- // vc.logOut()
69
67
  self.navigationBar.isHidden = true
70
68
  self.setViewControllers([vc], animated: false)
71
69
  }
72
-
70
+
73
71
  }
74
72
 
75
73
  private extension EasyPayViewController {
@@ -0,0 +1,66 @@
1
+ //
2
+ // CheckboxButton.swift
3
+ // EasyPay
4
+ //
5
+ // Created by iftekhar on 14/07/24.
6
+ //
7
+
8
+ //import Foundation
9
+ //
10
+ //final class CheckboxButton: UIButton {
11
+ //
12
+ // override func awakeFromNib() {
13
+ // super.awakeFromNib()
14
+ // self.addTarget(self, action: #selector(tapAction(_:)), for: .touchUpInside)
15
+ // }
16
+ //
17
+ // @objc private func tapAction(_ sender: UIButton) {
18
+ // self.isSelected.toggle()
19
+ // }
20
+ //}
21
+
22
+
23
+ import UIKit
24
+
25
+ final class CheckboxButton: UIButton {
26
+
27
+ override func awakeFromNib() {
28
+ super.awakeFromNib()
29
+ self.addTarget(self, action: #selector(tapAction(_:)), for: .touchUpInside)
30
+ applyPrimaryColor() // Apply primary color when the button initializes
31
+ applySecondaryFontColor()
32
+ applyFontSize()
33
+ }
34
+
35
+ @objc private func tapAction(_ sender: UIButton) {
36
+ self.isSelected.toggle()
37
+ }
38
+
39
+ private func applyPrimaryColor() {
40
+ if let primaryBtnBackgroundColor = UserStoreSingleton.shared.primary_btn_bg_col,
41
+ let primaryUIColor = UIColor(hex: primaryBtnBackgroundColor) {
42
+
43
+ // Apply tintColor to the image
44
+ self.imageView?.tintColor = primaryUIColor
45
+ self.setImage(self.image(for: .normal)?.withRenderingMode(.alwaysTemplate), for: .normal)
46
+ self.setImage(self.image(for: .selected)?.withRenderingMode(.alwaysTemplate), for: .selected)
47
+ }
48
+ }
49
+
50
+ private func applySecondaryFontColor() {
51
+ if let secondaryFontColor = UserStoreSingleton.shared.secondary_font_col,
52
+ let fontUIColor = UIColor(hex: secondaryFontColor) {
53
+ self.setTitleColor(fontUIColor, for: .normal)
54
+ self.setTitleColor(fontUIColor, for: .selected)
55
+ }
56
+ }
57
+
58
+ private func applyFontSize() {
59
+ if let fontSizeString = UserStoreSingleton.shared.fontSize,
60
+ let fontSizeDouble = Double(fontSizeString) {
61
+ let fontSize = CGFloat(fontSizeDouble)
62
+ self.titleLabel?.font = UIFont.systemFont(ofSize: fontSize) // Apply font size to the button title
63
+ }
64
+ }
65
+
66
+ }
@@ -17,3 +17,4 @@ public class GrailPayHelper {
17
17
  viewController.present(grailPayVC, animated: true)
18
18
  }
19
19
  }
20
+