nimbbl-mobile-react-native-sdk 1.3.4 → 1.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Nimbbl React Native SDK
2
2
 
3
- **✅ Stable Release v1.3.4 - Production Ready!**
3
+ **✅ Stable Release v1.3.5 - Production Ready!**
4
4
 
5
5
  A comprehensive React Native SDK for integrating Nimbbl payment gateway into your mobile applications. This SDK provides a seamless bridge between React Native and native payment functionality, offering a unified API for both iOS and Android platforms.
6
6
 
@@ -36,23 +36,21 @@ const nimbblSDK = NimbblSDK.getSharedInstance();
36
36
  // Initialize with default production configuration
37
37
  await nimbblSDK.initialize();
38
38
 
39
- // Set up payment response handler
40
- nimbblSDK.addCheckoutResponseListener((data) => {
41
- if (data.status === 'success') {
42
- console.log('Payment successful:', data);
43
- } else {
44
- console.log('Payment failed:', data);
45
- }
46
- });
47
-
48
39
  // Start payment with all optional parameters
49
- await nimbblSDK.checkout({
40
+ const result = await nimbblSDK.checkout({
50
41
  orderToken: 'YOUR_ORDER_TOKEN',
51
42
  paymentModeCode: '<OPTIONAL>',
52
43
  bankCode: '<OPTIONAL>',
53
44
  walletCode: '<OPTIONAL>',
54
45
  paymentFlow: '<OPTIONAL>'
55
46
  });
47
+
48
+ // `checkout()` resolves with the native SDK response payload
49
+ if (result?.status === 'success') {
50
+ console.log('Payment successful:', result);
51
+ } else {
52
+ console.log('Payment result:', result);
53
+ }
56
54
  ```
57
55
 
58
56
  **That's it! Your payment integration is complete.** 🎉
@@ -78,7 +76,12 @@ await nimbblSDK.checkout({
78
76
  | `^0.73.0` | ✅ Supported | Latest stable version |
79
77
  | `^0.74.0` | ✅ Supported | Latest stable version |
80
78
  | `^0.75.0` | ✅ Supported | Latest stable version |
81
- | `^0.76.0` | ✅ **Recommended** | **Latest stable version** |
79
+ | `^0.76.0` | ✅ Supported | Previously tested |
80
+ | `^0.81.0` | ✅ Tested | iOS 26 toolchain verified |
81
+
82
+ ### iOS 26 note
83
+
84
+ - Tested by building the sample app against the iOS 26 simulator SDK with React Native `0.81.x`.
82
85
 
83
86
  ### Node.js Version Support
84
87
 
@@ -135,16 +138,7 @@ await nimbblSDK.initialize({
135
138
  ### 3. Set Up Payment Response Handler
136
139
 
137
140
  ```javascript
138
- // Set up unified payment response handler
139
- nimbblSDK.addCheckoutResponseListener((data) => {
140
- if (data.status === 'success') {
141
- console.log('Payment successful:', data);
142
- // Handle successful payment
143
- } else {
144
- console.log('Payment failed:', data);
145
- // Handle failed payment
146
- }
147
- });
141
+ // `checkout()` returns the payment response payload (resolve) or throws if checkout couldn't start (reject)
148
142
  ```
149
143
 
150
144
  ### 4. Start Payment
@@ -323,7 +317,7 @@ class PaymentManager {
323
317
  **Problem**: WebView opens and closes, but payment status screen doesn't appear.
324
318
 
325
319
  **Solution**:
326
- - Ensure you're using the latest SDK version (`^1.3.4`)
320
+ - Ensure you're using the latest SDK version (`^1.3.5`)
327
321
  - The SDK automatically manages event listeners - no manual setup required
328
322
  - Check that your app properly handles the payment success/failure events
329
323
 
@@ -434,14 +428,14 @@ For production applications, consider locking to specific versions:
434
428
  ```json
435
429
  {
436
430
  "dependencies": {
437
- "nimbbl-mobile-react-native-sdk": "1.3.4"
431
+ "nimbbl-mobile-react-native-sdk": "1.3.5"
438
432
  }
439
433
  }
440
434
  ```
441
435
 
442
436
  ## 📝 Release Notes
443
437
 
444
- ### v1.3.4 - Stable Release ✅
438
+ ### v1.3.5 - Stable Release ✅
445
439
 
446
440
  **🚀 Stable Production-Ready React Native SDK for Nimbbl Payments**
447
441
 
@@ -7,10 +7,6 @@ RCT_EXTERN_METHOD(initialize:(NSDictionary *)config
7
7
  resolver:(RCTPromiseResolveBlock)resolve
8
8
  rejecter:(RCTPromiseRejectBlock)reject)
9
9
 
10
- RCT_EXTERN_METHOD(createShopOrder:(NSDictionary *)orderData
11
- resolver:(RCTPromiseResolveBlock)resolve
12
- rejecter:(RCTPromiseRejectBlock)reject)
13
-
14
10
  RCT_EXTERN_METHOD(checkout:(NSDictionary *)options
15
11
  resolver:(RCTPromiseResolveBlock)resolve
16
12
  rejecter:(RCTPromiseRejectBlock)reject)
@@ -7,7 +7,6 @@ import UIKit
7
7
  class NimbblReactNativeSDK: RCTEventEmitter, NimbblCheckoutSDKDelegate {
8
8
 
9
9
  private var config: [String: Any] = [:]
10
- private var isInitialized = false
11
10
  private var checkoutCallback: RCTResponseSenderBlock?
12
11
 
13
12
  override init() {
@@ -57,8 +56,6 @@ class NimbblReactNativeSDK: RCTEventEmitter, NimbblCheckoutSDKDelegate {
57
56
  let appCode = self.config["app_code"] as? String
58
57
  NimbblCheckoutSDK.shared.initialize(appCode: appCode)
59
58
 
60
- isInitialized = true
61
-
62
59
  let result: [String: Any] = [
63
60
  "success": true,
64
61
  "message": "SDK initialized successfully"
@@ -95,8 +92,7 @@ class NimbblReactNativeSDK: RCTEventEmitter, NimbblCheckoutSDKDelegate {
95
92
  paymentFlow: paymentFlow
96
93
  )
97
94
 
98
- // Get the root view controller
99
- guard let rootViewController = UIApplication.shared.windows.first?.rootViewController else {
95
+ guard let rootViewController = self.findPresentingViewController() else {
100
96
  reject("NO_VIEW_CONTROLLER", "Could not find root view controller", nil)
101
97
  return
102
98
  }
@@ -111,6 +107,21 @@ class NimbblReactNativeSDK: RCTEventEmitter, NimbblCheckoutSDKDelegate {
111
107
  reject("CHECKOUT_FAILED", error.localizedDescription, error)
112
108
  }
113
109
  }
110
+
111
+ private func findPresentingViewController() -> UIViewController? {
112
+ if #available(iOS 13.0, *) {
113
+ let windowScenes = UIApplication.shared.connectedScenes.compactMap { $0 as? UIWindowScene }
114
+ for scene in windowScenes {
115
+ let candidateWindow = scene.windows.first(where: { $0.isKeyWindow }) ?? scene.windows.first
116
+ if let root = candidateWindow?.rootViewController {
117
+ return root.topMostViewController()
118
+ }
119
+ }
120
+ return nil
121
+ } else {
122
+ return UIApplication.shared.keyWindow?.rootViewController?.topMostViewController()
123
+ }
124
+ }
114
125
 
115
126
  // MARK: - NimbblCheckoutSDKDelegate
116
127
 
@@ -122,3 +133,18 @@ class NimbblReactNativeSDK: RCTEventEmitter, NimbblCheckoutSDKDelegate {
122
133
  // Note: Removed fallback to event emitter for cleaner implementation
123
134
  }
124
135
  }
136
+
137
+ private extension UIViewController {
138
+ func topMostViewController() -> UIViewController {
139
+ if let presented = self.presentedViewController {
140
+ return presented.topMostViewController()
141
+ }
142
+ if let nav = self as? UINavigationController, let visible = nav.visibleViewController {
143
+ return visible.topMostViewController()
144
+ }
145
+ if let tab = self as? UITabBarController, let selected = tab.selectedViewController {
146
+ return selected.topMostViewController()
147
+ }
148
+ return self
149
+ }
150
+ }
@@ -15,6 +15,7 @@ export default class NimbblSDK {
15
15
  private static shared;
16
16
  private config;
17
17
  private isInitialized;
18
+ private checkoutInProgress;
18
19
  constructor();
19
20
  /**
20
21
  * Get shared instance (matching iOS pattern)
package/lib/NimbblSDK.js CHANGED
@@ -23,6 +23,7 @@ class NimbblSDK {
23
23
  }
24
24
  this.config = null;
25
25
  this.isInitialized = false;
26
+ this.checkoutInProgress = false;
26
27
  }
27
28
  /**
28
29
  * Get shared instance (matching iOS pattern)
@@ -62,46 +63,40 @@ class NimbblSDK {
62
63
  if (!this.isInitialized) {
63
64
  throw new Error(constants_1.ERROR_MESSAGES[constants_1.ERROR_CODES.SDK_NOT_INITIALIZED]);
64
65
  }
65
- try {
66
- const checkoutPayload = {
67
- order_token: options.orderToken,
68
- payment_mode_code: options.paymentModeCode || '',
69
- bank_code: options.bankCode || '',
70
- wallet_code: options.walletCode || '',
71
- payment_flow: options.paymentFlow || '',
72
- checkout_experience: options.checkoutExperience || 'redirect',
73
- upi_id: options.upiId || '',
74
- upi_app_code: options.upiAppCode || '',
75
- emi_code: options.emiCode || '',
76
- };
77
- // Use callback-based approach - SDK will always return a response
78
- return new Promise((resolve) => {
79
- // Store the resolve function for the native module to call
80
- const nativeModule = NimbblReactNativeSDK;
81
- nativeModule.setCheckoutCallback((result) => {
82
- // Return the raw JSON response from native SDK directly
83
- resolve(result);
84
- });
85
- // Start the checkout process
86
- nativeModule
87
- .checkout(checkoutPayload)
88
- .then(() => {
89
- // Native checkout initiated successfully
90
- })
91
- .catch((error) => {
92
- resolve({
93
- status: 'error',
94
- message: error.message || 'Failed to initiate native checkout',
95
- });
96
- });
97
- });
98
- }
99
- catch (error) {
100
- return {
101
- status: 'error',
102
- message: error instanceof Error ? error.message : 'Checkout failed',
103
- };
66
+ if (this.checkoutInProgress) {
67
+ throw new Error('Checkout already in progress.');
104
68
  }
69
+ const checkoutPayload = {
70
+ order_token: options.orderToken,
71
+ payment_mode_code: options.paymentModeCode || '',
72
+ bank_code: options.bankCode || '',
73
+ wallet_code: options.walletCode || '',
74
+ payment_flow: options.paymentFlow || '',
75
+ checkout_experience: options.checkoutExperience || 'redirect',
76
+ upi_id: options.upiId || '',
77
+ upi_app_code: options.upiAppCode || '',
78
+ emi_code: options.emiCode || '',
79
+ };
80
+ const nativeModule = NimbblReactNativeSDK;
81
+ // Callback-based: resolve on native response; reject if checkout cannot be initiated.
82
+ return new Promise((resolve, reject) => {
83
+ this.checkoutInProgress = true;
84
+ let settled = false;
85
+ nativeModule.setCheckoutCallback((result) => {
86
+ if (settled)
87
+ return;
88
+ settled = true;
89
+ this.checkoutInProgress = false;
90
+ resolve(result);
91
+ });
92
+ nativeModule.checkout(checkoutPayload).catch((error) => {
93
+ if (settled)
94
+ return;
95
+ settled = true;
96
+ this.checkoutInProgress = false;
97
+ reject(error);
98
+ });
99
+ });
105
100
  }
106
101
  }
107
102
  NimbblSDK.shared = null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nimbbl-mobile-react-native-sdk",
3
- "version": "1.3.4",
3
+ "version": "1.3.5",
4
4
  "description": "Nimbbl React Native SDK for payment integration",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -52,14 +52,9 @@
52
52
  "publishConfig": {
53
53
  "access": "public"
54
54
  },
55
- "peerDependencies": {
56
- "react": ">=16.8.0",
57
- "react-native": ">=0.60.0"
58
- },
59
55
  "devDependencies": {
60
56
  "@types/jest": "^29.5.0",
61
- "@types/react": "^18.0.24",
62
- "@types/react-native": "^0.72.0",
57
+ "@types/react": "^19.1.0",
63
58
  "@typescript-eslint/eslint-plugin": "^6.0.0",
64
59
  "@typescript-eslint/parser": "^6.0.0",
65
60
  "eslint": "^8.19.0",
@@ -68,8 +63,8 @@
68
63
  "jest": "^29.2.1",
69
64
  "npm-run-all": "^4.1.5",
70
65
  "prettier": "^3.0.0",
71
- "react": "18.2.0",
72
- "react-native": "0.76.0",
66
+ "react": "19.1.0",
67
+ "react-native": "0.81.0",
73
68
  "ts-jest": "^29.1.0",
74
69
  "typescript": "^5.0.0",
75
70
  "@react-navigation/native": "^7.1.18",