@glomopay/react-native-sdk 2.0.2 โ†’ 3.0.1

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 (70) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/README.md +261 -310
  3. package/lib/config/base.d.ts +17 -11
  4. package/lib/config/base.d.ts.map +1 -1
  5. package/lib/config/base.js +19 -7
  6. package/lib/config/segment.js +3 -3
  7. package/lib/glomo-checkout.d.ts +8 -0
  8. package/lib/glomo-checkout.d.ts.map +1 -0
  9. package/lib/glomo-checkout.js +69 -0
  10. package/lib/glomo-lrs-checkout.js +9 -9
  11. package/lib/glomo-standard-checkout.d.ts +5 -0
  12. package/lib/glomo-standard-checkout.d.ts.map +1 -0
  13. package/lib/glomo-standard-checkout.js +218 -0
  14. package/lib/index.d.ts +5 -4
  15. package/lib/index.d.ts.map +1 -1
  16. package/lib/index.js +7 -5
  17. package/lib/injections/index.d.ts +1 -0
  18. package/lib/injections/index.d.ts.map +1 -1
  19. package/lib/injections/index.js +2 -0
  20. package/lib/injections/webview-flow.injection.d.ts.map +1 -1
  21. package/lib/injections/webview-flow.injection.js +106 -69
  22. package/lib/injections/webview-main.injection.d.ts.map +1 -1
  23. package/lib/injections/webview-main.injection.js +112 -77
  24. package/lib/injections/webview-standard.injection.d.ts +3 -0
  25. package/lib/injections/webview-standard.injection.d.ts.map +1 -0
  26. package/lib/injections/webview-standard.injection.js +214 -0
  27. package/lib/services/order-type-fetcher.d.ts +28 -0
  28. package/lib/services/order-type-fetcher.d.ts.map +1 -0
  29. package/lib/services/order-type-fetcher.js +99 -0
  30. package/lib/types/checkout.d.ts +53 -0
  31. package/lib/types/checkout.d.ts.map +1 -0
  32. package/lib/types/checkout.js +3 -0
  33. package/lib/types/standard-checkout.d.ts +40 -0
  34. package/lib/types/standard-checkout.d.ts.map +1 -0
  35. package/lib/types/standard-checkout.js +3 -0
  36. package/lib/use-glomo-checkout.d.ts +24 -0
  37. package/lib/use-glomo-checkout.d.ts.map +1 -0
  38. package/lib/use-glomo-checkout.js +182 -0
  39. package/lib/use-lrs-checkout.d.ts +9 -4
  40. package/lib/use-lrs-checkout.d.ts.map +1 -1
  41. package/lib/use-lrs-checkout.js +76 -93
  42. package/lib/use-standard-checkout.d.ts +65 -0
  43. package/lib/use-standard-checkout.d.ts.map +1 -0
  44. package/lib/use-standard-checkout.js +832 -0
  45. package/lib/utils/analytics.d.ts +102 -1
  46. package/lib/utils/analytics.d.ts.map +1 -1
  47. package/lib/utils/analytics.js +294 -21
  48. package/lib/utils/device-compliance.js +3 -3
  49. package/lib/utils/validation.d.ts.map +1 -1
  50. package/lib/utils/validation.js +7 -6
  51. package/package.json +3 -2
  52. package/src/config/base.ts +36 -17
  53. package/src/config/segment.ts +3 -3
  54. package/src/glomo-checkout.tsx +73 -0
  55. package/src/glomo-lrs-checkout.tsx +9 -9
  56. package/src/glomo-standard-checkout.tsx +324 -0
  57. package/src/index.ts +13 -7
  58. package/src/injections/index.ts +2 -0
  59. package/src/injections/webview-flow.injection.ts +106 -69
  60. package/src/injections/webview-main.injection.ts +112 -77
  61. package/src/injections/webview-standard.injection.ts +211 -0
  62. package/src/services/order-type-fetcher.ts +86 -0
  63. package/src/types/checkout.ts +65 -0
  64. package/src/types/standard-checkout.ts +49 -0
  65. package/src/use-glomo-checkout.tsx +228 -0
  66. package/src/use-lrs-checkout.tsx +91 -111
  67. package/src/use-standard-checkout.tsx +1185 -0
  68. package/src/utils/analytics.ts +431 -22
  69. package/src/utils/device-compliance.ts +3 -3
  70. package/src/utils/validation.ts +7 -8
package/README.md CHANGED
@@ -7,129 +7,121 @@ Official React Native SDK for integrating GlomoPay payment checkout flows into y
7
7
 
8
8
  ## โœจ Features
9
9
 
10
- - ๐Ÿ“ฑ **Cross-Platform** - Works seamlessly on both iOS and Android
11
- - ๐Ÿ”ท **TypeScript Support** - Full type definitions included
12
- - โšก **Simple Integration** - Minimal configuration required
13
- - ๐Ÿ”’ **Secure** - WebView-based checkout with signature verification
14
- - ๐Ÿ›ก๏ธ **Device Security Compliance** - Prevents unsafe/non-compliant devices from initiating checkouts as per regulatory policies
15
- - ๐Ÿ’ฐ **Flexible** - Support for multiple payment methods through GlomoPay
10
+ - ๐Ÿ“ฑ **Cross-platform** - works on both iOS and Android
11
+ - ๐Ÿ”ท **TypeScript** - full type definitions for all exports
12
+ - โšก **Unified checkout** - renders the correct checkout flow automatically based on your order
13
+ - ๐Ÿ’ฐ **Bank transfer support** - callback for bank transfer submission events
14
+ - ๐Ÿฆ **Pay via bank** - bank payment flow completion and connection callbacks
15
+ - ๐Ÿ“ท **Camera permissions** - built-in handling for bank authentication
16
+ - ๐Ÿ”’ **Device security** - optional **(but strongly recommended)** `jail-monkey` integration for rooted/jailbroken device detection
17
+ - ๐Ÿ›ก๏ธ **Input validation** - publicKey and orderId format enforcement before checkout starts
18
+ - ๐Ÿงช **Mock mode** - test with `test_` / `mock_` prefixed keys without hitting production
16
19
 
17
20
  ## ๐Ÿ“‹ Prerequisites
18
21
 
19
- Before using this SDK, you need:
20
-
21
22
  - API credentials (Public Key) from your GlomoPay dashboard
23
+ - An order ID created via the GlomoPay API
22
24
 
23
25
  ## ๐Ÿ› ๏ธ System Requirements
24
26
 
25
- - React Native >= 0.68.0
26
- - React >= 17.0.0
27
- - Node.js >= 16.0.0
28
- - npm >= 8.0.0
27
+ | Requirement | Version |
28
+ | ---------------------- | ------------ |
29
+ | Node.js | >= 16.0.0 |
30
+ | npm | >= 8.0.0 |
31
+ | React | >= 17.0.0 |
32
+ | React Native | >= 0.68.0 |
33
+ | react-native-webview | ^13.0.0 |
34
+ | jail-monkey (optional) | ^2.6.0 |
29
35
 
30
- ## ๐Ÿ“ฆ Installation
36
+ ## โš ๏ธ Breaking Changes (v3)
31
37
 
32
- ### ๐Ÿ“ฒ 1. Standard React Native CLI project
38
+ - `GlomoLrsCheckout` has been replaced by `GlomoCheckout` - the new component now works for all checkout orders (including LRS)
39
+ - `start()` is now async - returns `Promise<boolean>` instead of `boolean`
40
+ - All LRS-specific exports have been renamed (e.g. `GlomoLrsCheckoutRef` -> `GlomoCheckoutRef`)
33
41
 
34
- For standard installations, this SDK requires `react-native-webview` as a peer dependency. Install it first:
42
+ For the full list of changes and migration details, see [CHANGELOG.md](./CHANGELOG.md) and [Migration from v2](#-migration-from-v2).
35
43
 
36
- ```bash
37
- npm install react-native-webview
38
- ```
44
+ ## ๐Ÿ“ฆ Installation
39
45
 
40
- Then install the SDK
46
+ ### React Native CLI
41
47
 
42
48
  ```bash
43
- npm install @glomopay/react-native-sdk
49
+ npm install @glomopay/react-native-sdk react-native-webview
50
+ cd ios && pod install
44
51
  ```
45
52
 
46
- **๐Ÿ”’ Recommended: Enhanced Security Compliance**
47
-
48
- For enhanced device security compliance (rooted/jailbroken device detection), we HIGHLY recommend installing the peer dependency `jail-monkey`:
53
+ ### Expo
49
54
 
50
55
  ```bash
51
- npm install jail-monkey
56
+ npx expo install @glomopay/react-native-sdk react-native-webview
52
57
  ```
53
58
 
54
- **Note:** The SDK works without `jail-monkey`, but installing it enables automatic device security compliance checks that help meet regulatory requirements. See [Device Security Compliance](#device-security-compliance-) section for more details.
55
-
56
- ### ๐Ÿ”ง 2. Expo Projects
59
+ ### Recommended: Device Security Compliance
57
60
 
58
- This SDK is compatible with Expo projects. Install with:
61
+ For rooted/jailbroken device detection (strongly recommended for regulated flows):
59
62
 
60
63
  ```bash
61
- npx expo install react-native-webview
62
- npx expo install @glomopay/react-native-sdk
64
+ npm install jail-monkey
63
65
  ```
64
66
 
65
- **Note**: Requires custom dev client or EAS Build. Not compatible with Expo Go app.
66
-
67
- For Expo Go limitations, see [Expo documentation](https://docs.expo.dev/workflow/customizing/).
67
+ The SDK works without `jail-monkey`, but installing it enables automatic device security checks. Without it, the SDK logs a warning on every `start()` call.
68
68
 
69
69
  ## ๐Ÿš€ Quick Start
70
70
 
71
- Before start the checkout flow, you'll need to create an LRS order using other Glomo SDKs and obtain the Order ID (Alphanumeric, starts with `order_`).
72
-
73
- ### Breaking Changes (latest)
74
-
75
- - `educationURL` has been removed from the public API. The SDK now manages any educational content behavior internally.
76
-
77
- ### 1. Import the SDK
78
-
79
71
  ```tsx
72
+ import React, { useRef } from "react";
73
+ import { View, Button } from "react-native";
80
74
  import {
81
- GlomoLrsCheckout,
82
- type GlomoLrsCheckoutRef,
75
+ GlomoCheckout,
76
+ type GlomoCheckoutRef,
77
+ type GlomoCheckoutPayload,
83
78
  type SdkError,
84
- } from '@glomopay/react-native-sdk';
85
- ```
79
+ } from "@glomopay/react-native-sdk";
86
80
 
87
- ### 2. Add the Component to Your App
81
+ export default function PaymentScreen() {
82
+ const checkoutRef = useRef<GlomoCheckoutRef>(null);
88
83
 
89
- ```tsx
90
- import React, { useState, useRef } from 'react';
91
- import { View } from 'react-native';
92
- import {
93
- GlomoLrsCheckout,
94
- type GlomoLrsCheckoutRef,
95
- } from '@glomopay/react-native-sdk';
96
-
97
- function CheckoutScreen()
98
- {
99
- const [orderId, setOrderId] = useState('YOUR_ORDER_ID');
100
- const checkoutRef = useRef<GlomoLrsCheckoutRef>(null);
101
-
102
- const startLrsCheckout = () => {
103
- const started = checkoutRef.current?.start();
84
+ const handlePay = async () => {
85
+ const started = await checkoutRef.current?.start();
104
86
  if (!started) {
105
- const status = checkoutRef.current?.getStatus();
106
- console.log('Checkout could not be started. Current status:', status);
87
+ console.log("Checkout could not start - check onSdkError for details");
107
88
  }
108
89
  };
109
90
 
110
91
  return (
111
- <View>
112
- <GlomoLrsCheckout
92
+ <View style={{ flex: 1 }}>
93
+ <Button title="Pay Now" onPress={handlePay} />
94
+
95
+ <GlomoCheckout
113
96
  ref={checkoutRef}
114
- publicKey={'YOUR_PUBLIC_KEY'}
115
- orderId={orderId}
116
- onPaymentSuccess={(payload) => {
117
- console.log('Payment successful!', payload);
118
- // Handle successful payment
97
+ publicKey="live_pk_abc123"
98
+ orderId="order_xyz789"
99
+ onPaymentSuccess={(payload: GlomoCheckoutPayload) => {
100
+ console.log("Payment success:", payload.paymentId);
101
+ }}
102
+ onPaymentFailure={(payload: GlomoCheckoutPayload) => {
103
+ console.log("Payment failed:", payload.paymentId);
119
104
  }}
120
- onPaymentFailure={(payload) => {
121
- console.log('Payment failed!', payload);
122
- // Handle failed payment
105
+ onPaymentTerminate={() => {
106
+ console.log("User dismissed checkout");
123
107
  }}
124
108
  onConnectionError={(error) => {
125
- console.log('Could not open LRS checkout!', error);
126
- // Handle connection/network errors
109
+ console.log("Connection error:", error);
110
+ }}
111
+ onBankTransferSubmitted={(payload) => {
112
+ console.log("Bank transfer submitted:", payload?.transactionReference);
127
113
  }}
128
- onSdkError={(errors) => {
129
- errors.forEach((error) => {
130
- console.error('SDK Error:', error.message);
131
- // Handle validation errors
132
- });
114
+ onPayViaBankCompleted={(payload) => {
115
+ console.log("Pay via bank completed:", payload.status);
116
+ }}
117
+ onPayViaBankBankConnectionSuccessful={(payload) => {
118
+ console.log("Bank connected:", payload?.bankName);
119
+ }}
120
+ onUserRefusedCameraPermissions={() => {
121
+ console.log("User refused camera - cannot proceed with bank authentication");
122
+ }}
123
+ onSdkError={(errors: SdkError[]) => {
124
+ errors.forEach((e) => console.error(e.type, e.message, e.field));
133
125
  }}
134
126
  />
135
127
  </View>
@@ -139,312 +131,271 @@ function CheckoutScreen()
139
131
 
140
132
  ## ๐Ÿ“š API Reference
141
133
 
142
- ### `GlomoLrsCheckout` Component
143
-
144
- #### Props
134
+ ### GlomoCheckout Component
145
135
 
146
- | Prop | Type | Required | Description |
147
- |------|------|----------|-------------|
148
- | `publicKey` | `string` | Yes | Your public key. If it starts with `test_`, mock mode will be enabled automatically. Otherwise, live mode is used. |
149
- | `orderId` | `string` | Yes | The order ID for this transaction. Must start with `order_` |
150
- | `onPaymentSuccess` | `(payload: GlomoLrsCheckoutPayload) => void` | Yes | Callback function called when the payment is successful |
151
- | `onPaymentFailure` | `(payload: GlomoLrsCheckoutPayload) => void` | Yes | Callback function called when the payment fails |
152
- | `onConnectionError` | `(error: unknown) => void` | No | Will be called on network connection problems. The checkout modal will automatically close before this is triggered. |
153
- | `onPaymentTerminate` | `() => void` | No | Callback called when checkout is terminated. Triggered when the `checkout.closed` event is received from the WebView or when the user dismisses the modal (iOS swipe down) or presses the back button (Android) |
154
- | `onSdkError` | `(errors: SdkError[]) => void` | No | Callback for SDK validation errors and configuration issues. Receives an array of `SdkError` objects when validation fails. |
155
- | `devMode` | `boolean` | No | Enable debug logging (default: `false`) |
156
- | `visible` | `boolean` | No | Control modal visibility manually (advanced usage only). It is HIGHLY recommended to not use this prop directly. |
157
-
158
- ### Ref Methods
136
+ The unified checkout component. Place it in your render tree and control it via a ref.
159
137
 
160
138
  ```tsx
161
- interface GlomoLrsCheckoutRef {
162
- start: () => boolean; // Starts the checkout flow. Returns true if started, false if it cannot be started.
163
- getStatus: () => LrsCheckoutStatus; // Returns the current checkout status
164
- }
139
+ <GlomoCheckout ref={checkoutRef} {...props} />
165
140
  ```
166
141
 
167
- Usage:
168
- ```tsx
169
- const checkoutRef = useRef<GlomoLrsCheckoutRef>(null);
170
-
171
- // Start checkout - returns true if successful, false otherwise
172
- const started = checkoutRef.current?.start();
173
- if (started) {
174
- console.log('Checkout started successfully');
175
- } else {
176
- console.log('Checkout could not be started. Check the status.');
142
+ #### Props (`GlomoCheckoutProps`)
143
+
144
+ | Prop | Type | Required | Description |
145
+ | -------------------------------- | ----------------------------------------------- | -------- | ------------------------------------------------------------------- |
146
+ | `publicKey` | `string` | Yes | Your GlomoPay public key (must start with `live_`, `mock_`, or `test_`) |
147
+ | `orderId` | `string` | Yes | Order ID from the GlomoPay API (must start with `order_`) |
148
+ | `onPaymentSuccess` | `(payload: GlomoCheckoutPayload) => void` | Yes | Called when payment succeeds |
149
+ | `onPaymentFailure` | `(payload: GlomoCheckoutPayload) => void` | Yes | Called when payment fails |
150
+ | `onConnectionError` | `(error: unknown) => void` | No | Called on network/connection errors |
151
+ | `onPaymentTerminate` | `() => void` | No | Called when user dismisses checkout (back button or swipe) |
152
+ | `onSdkError` | `(errors: SdkError[]) => void` | No | Called on validation errors or device compliance failures |
153
+ | `onBankTransferSubmitted` | `(payload: GlomoBankTransferPayload \| null \| undefined) => void` | No | Called when user submits bank transfer details |
154
+ | `onPayViaBankCompleted` | `(payload: { status: string }) => void` | No | Called when pay via bank flow completes |
155
+ | `onPayViaBankBankConnectionSuccessful` | `(payload: GlomoPayViaBankConnectionPayload \| null \| undefined) => void` | No | Called when bank connection is established during pay via bank flow |
156
+ | `onUserRefusedCameraPermissions` | `() => void` | No | Called when user denies camera access needed for bank authentication |
157
+
158
+ #### Ref Methods (`GlomoCheckoutRef`)
159
+
160
+ | Method | Signature | Description |
161
+ | ------------ | ------------------------ | --------------------------------------------------------------------------------------------------------- |
162
+ | `start()` | `() => Promise<boolean>` | Validates inputs, and opens the checkout modal. Resolves `true` if successful, `false` otherwise. |
163
+ | `getStatus()`| `() => CheckoutStatus` | Returns the current checkout status. |
164
+
165
+ #### CheckoutStatus
166
+
167
+ | Status | Description |
168
+ | -------------------------- | -------------------------------------------------------------- |
169
+ | `ready` | Initial state - checkout can be started |
170
+ | `payment_in_progress` | Checkout modal is open, user is interacting |
171
+ | `payment_successful` | Payment completed successfully. Cannot restart with same order |
172
+ | `payment_failed` | Payment failed. Can retry with same order |
173
+ | `payment_cancelled` | User dismissed checkout mid-flow. Can retry |
174
+ | `bank_transfer_submitted` | User submitted bank transfer details |
175
+ | `pay_via_bank_completed` | Pay via bank flow completed |
176
+
177
+ ### Type Definitions
178
+
179
+ #### GlomoCheckoutPayload
180
+
181
+ ```ts
182
+ interface GlomoCheckoutPayload {
183
+ orderId: string;
184
+ paymentId: string;
185
+ signature: string;
177
186
  }
178
-
179
- // Check status
180
- const currentStatus = checkoutRef.current?.getStatus();
181
187
  ```
182
188
 
183
- **Note:**
184
- - The `start()` method returns `true` if the checkout was started successfully, `false` otherwise
185
- - The `start()` method performs device compliance checks first (before any other validation) **if `jail-monkey` is installed**.
186
- - If the device is rooted or jailbroken and `jail-monkey` is available, it will return `false` and trigger the `onSdkError` callback with a `device_forbidden` error.
187
- - If `jail-monkey` is not installed, compliance checks are skipped and checkout proceeds normally.
188
- - The `start()` method may be used to restart an LRS checkout for an existing order,
189
- - If the user cancelled the payment midway (`"payment_cancelled"` status) by pressing the back button on Android, or dismissing the modal on iOS
190
- - Or if the payment failed or timed-out (`"payment_failed"` status)
191
- - After an LRS checkout for an `orderId` is successful, further calls to the `start()` method will return false, and will not re-trigger an LRS checkout (`"payment_successful"` status)
192
- - Changing the `orderId`/`publicKey` props resets the flow, and `start()` can be triggered again
193
-
194
- #### `GlomoLrsCheckoutPayload`
195
-
196
-
197
- ```typescript
198
- interface GlomoLrsCheckoutPayload {
199
- orderId: string; // Order identifier (e.g., "order_abc123")
200
- paymentId: string; // Payment id from GlomoPay
201
- signature: string; // Signature for verification
189
+ #### GlomoBankTransferPayload
190
+
191
+ ```ts
192
+ interface GlomoBankTransferPayload {
193
+ orderId: string;
194
+ senderAccountNumber: string;
195
+ transactionReference: string;
202
196
  }
203
197
  ```
204
198
 
205
- The payload is returned for both successful and failed LRS payments.
199
+ #### GlomoPayViaBankConnectionPayload
206
200
 
207
- #### `SdkError`
201
+ ```ts
202
+ interface GlomoPayViaBankConnectionPayload {
203
+ bankIdentifier: string;
204
+ cooldownPeriodInMinutes: number;
205
+ bankName: string;
206
+ bankImageSrc: string;
207
+ bankImageAlt: string;
208
+ }
209
+ ```
208
210
 
209
- The SDK provides validation and error reporting through the `onSdkError` callback:
211
+ #### SdkError
210
212
 
211
- ```typescript
213
+ ```ts
212
214
  interface SdkError {
213
215
  type: "validation_error" | "device_forbidden";
214
216
  message: string;
215
- field?: "publicKey" | "orderId" | "baseCheckoutUrl";
217
+ field?: string;
216
218
  }
217
219
  ```
218
220
 
219
- **Error Types:**
220
- - `validation_error`: Input validation failed (invalid publicKey, orderId, or server/baseCheckoutUrl)
221
- - `device_forbidden`: Device does not meet compliance requirements (LRS checkout is not permitted on compromised/rooted devices per regulatory policies).
221
+ ## ๐Ÿ’ฐ Bank Transfer Support
222
+
223
+ When the checkout flow includes a bank transfer option, the user submits transfer details (account number, reference) through the checkout UI. The SDK fires `onBankTransferSubmitted` with a `GlomoBankTransferPayload`:
222
224
 
223
- **Example:**
224
225
  ```tsx
225
- <GlomoLrsCheckout
226
- onSdkError={(errors) => {
227
- errors.forEach((error) => {
228
- console.error(`SDK Error [${error.type}]:`, error.message);
229
- if (error.field) {
230
- console.error(`Field: ${error.field}`);
231
- }
232
- });
233
- // Handle validation errors appropriately
234
- }}
235
- // ... other props
236
- />
226
+ onBankTransferSubmitted={(payload) => {
227
+ // payload may be null/undefined if the checkout page omits it
228
+ console.log("Transfer ref:", payload?.transactionReference);
229
+ }}
237
230
  ```
238
231
 
239
- **Note:** The SDK validates all inputs when `start()` is called. Validation errors are reported through `onSdkError` and `start()` will return `false` if validation fails.
232
+ The checkout status transitions to `bank_transfer_submitted`.
240
233
 
241
- ##### Checkout Status System ๐Ÿ“Š
234
+ ## ๐Ÿฆ Pay via Bank Support
242
235
 
243
- The SDK provides a status system to track the checkout lifecycle. Access the current status using the `getStatus()` method on the component ref:
236
+ The SDK fires `onPayViaBankCompleted` when the pay-via-bank journey completes:
244
237
 
245
238
  ```tsx
246
- const checkoutRef = useRef<GlomoLrsCheckoutRef>(null);
247
- const currentStatus = checkoutRef.current?.getStatus();
239
+ onPayViaBankCompleted={(payload) => {
240
+ // payload.status - e.g. "success", "failed", "unknown"
241
+ console.log("Pay via bank status:", payload.status);
242
+ }}
248
243
  ```
249
244
 
250
- #### Status Values
245
+ The checkout status transitions to `pay_via_bank_completed`. The SDK deduplicates this event internally - the callback fires only once per checkout session.
246
+
247
+ Additionally, `onPayViaBankBankConnectionSuccessful` fires when a bank account is successfully connected when initiating a pay-via-bank checkout, before the actual payment completes. This is informational only - it does not change the checkout status. Can be used to show a "bank connected" confirmation UI if desirable, while the payment continues in the background:
251
248
 
252
- The `LrsCheckoutStatus` type includes the following values:
249
+ ```tsx
250
+ onPayViaBankBankConnectionSuccessful={(payload) => {
251
+ // payload may be null/undefined if the checkout page omits it
252
+ console.log("Connected to:", payload?.bankName);
253
+ console.log("Cooldown:", payload?.cooldownPeriodInMinutes, "minutes");
254
+ }}
255
+ ```
253
256
 
254
- | Status | Description |
255
- |--------|-------------|
256
- | `"ready"` | Checkout is ready to be started |
257
- | `"payment_in_progress"` | Checkout flow is active and ongoing |
258
- | `"payment_successful"` | Payment completed successfully |
259
- | `"payment_failed"` | Payment failed (`glomoLrsCheckoutRef.current?.start()` can be reused with the same `orderId`) |
260
- | `"payment_cancelled"` | User cancelled the checkout midway (`glomoLrsCheckoutRef.current?.start()` can be reused with the same `orderId`) |
257
+ ## ๐Ÿ“ท Camera Permissions for bank authentication
261
258
 
262
- #### Status Lifecycle
259
+ Some checkout flows may require camera access for bank authentication. The SDK handles permission prompts automatically, but you must declare the permissions in your native project config.
263
260
 
261
+ ### Android
262
+
263
+ Add to `android/app/src/main/AndroidManifest.xml`:
264
+
265
+ ```xml
266
+ <uses-permission android:name="android.permission.CAMERA" />
264
267
  ```
265
- ready โ†’ payment_in_progress โ†’ payment_successful (order complete)
266
- โ†“ โ†‘ โ†‘
267
- payment_cancelled (can call start() again to restart) |
268
- โ†“ โ†‘ โ†‘
269
- payment_failed (can call start() again to retry) โ†’ _____โŒŸ
268
+
269
+ ### iOS
270
+
271
+ Add to `ios/<YourApp>/Info.plist`:
272
+
273
+ ```xml
274
+ <key>NSCameraUsageDescription</key>
275
+ <string>Camera access is required for identity verification during checkout</string>
270
276
  ```
271
277
 
272
- ## ๐Ÿ“ฑ Platform-Specific Behavior
278
+ ### Behavior
273
279
 
274
- ### ๐ŸŽ iOS
275
- - Checkout appears inside a modal within a `pageSheet`
276
- - Users can dismiss `GlomoLrsCheckout` component by swiping down
277
- - `onPaymentTerminate` is called when modal is dismissed
280
+ - **Android**: SDK prompts the user via a native permission dialog. If denied, checkout closes and `onUserRefusedCameraPermissions` fires.
281
+ - **iOS**: SDK grants the WebView permission request; iOS shows its own system prompt. If the user denies at the system level, the WebView handles the denial.
278
282
 
279
- ### ๐Ÿค– Android
280
- - Checkout appears in full-screen mode
281
- - Users can press the hardware back button to close the full-screen `GlomoLrsCheckout` component
282
- - Back button triggers `onPaymentTerminate` and closes checkout
283
+ ## ๐Ÿ“ฑ Platform Behavior
283
284
 
284
- ## ๐Ÿ”ง Troubleshooting
285
+ - **iOS**: Checkout opens as a `pageSheet` modal (swipe-down to dismiss). Dismissing fires `onPaymentTerminate`.
286
+ - **Android**: Checkout opens fullscreen. The hardware back button dismisses it and fires `onPaymentTerminate`.
285
287
 
286
- ### Common Issues
288
+ ## ๐Ÿ”’ Device Security Compliance
287
289
 
288
- #### 1. Checkout not appearing
289
- **Solution**:
290
- - Ensure `start()` is called via ref and check its return value
291
- - If `start()` returns `false`, check the current status using `getStatus()`
292
- - The checkout status must be `"ready"`, `"payment_cancelled"`, or `"payment_failed"` for `start()` to succeed
293
- - The checkout status must NOT be `"payment_successful"` (successful payments cannot be restarted)
294
- - **Device Security Compliance**: If peer dependency `jail-monkey` is installed and the device does not meet compliance requirements (the device is rooted/jailbroken), `start()` will return `false`. Check `onSdkError` callback for `device_forbidden` errors.
295
- - However, if `jail-monkey` has not been installed, security compliance checks will be skipped.
296
- - Check that `orderId` is provided and valid (must start with `order_`)
297
- - Ensure `publicKey` is valid (must start with `live_`)
298
- - Implement `onSdkError` callback to receive validation and device compliance error details
290
+ The SDK optionally integrates with `jail-monkey` to detect rooted (Android) or jailbroken (iOS) devices.
299
291
 
300
- #### 2. Expo Go "Invariant Violation" error
301
- **Solution**:
302
- - Expo Go doesn't support native modules
303
- - Use custom dev client: `npx expo prebuild`
304
- - Or use EAS Build for testing
292
+ - If `jail-monkey` is installed and the device is compromised: `start()` returns `false` and `onSdkError` fires with `type: "device_forbidden"`.
293
+ - If `jail-monkey` is installed and the device is clean: checkout proceeds normally.
294
+ - If `jail-monkey` is not installed: SDK logs a warning and proceeds without checking. This is not recommended for production deployments handling regulated transactions.
305
295
 
296
+ ## ๐Ÿงช Mock Mode
306
297
 
307
- ### Debugging Mode ๐Ÿ› ๏ธ
298
+ The SDK infers mock mode from the `publicKey` prefix:
308
299
 
309
- Enable detailed logging:
300
+ | Prefix | Mode | Environment |
301
+ | -------- | ----- | -------------------- |
302
+ | `live_` | Live | Production |
303
+ | `test_` | Mock | Test/sandbox |
304
+ | `mock_` | Mock | Test/sandbox |
310
305
 
311
- ```tsx
312
- <GlomoLrsCheckout
313
- devMode={true}
314
- // ... other props
315
- />
316
- ```
317
- Remember to disable this in production.
306
+ Mock mode keys route to the sandbox backend. No real transactions are created.
318
307
 
319
- ### Mock Mode Testing ๐Ÿงช
308
+ ## ๐ŸŒ Connection Handling
320
309
 
321
- Mock mode is automatically enabled based on your `publicKey`:
310
+ The SDK detects connection errors from the WebView and fires `onConnectionError`:
322
311
 
323
- - If your `publicKey` starts with `test_` (case-insensitive), mock mode is automatically enabled and the checkout URL will include `mode=mock`
324
- - Otherwise, live mode is used and the checkout URL will include `mode=live`
312
+ - **iOS**: NSURLErrorDomain codes (-1001 timeout, -1003 host not found, -1004 connection refused, -1009 offline)
313
+ - **Android**: ERR_EMPTY_RESPONSE, ERR_CONNECTION_REFUSED, ERR_NAME_NOT_RESOLVED, ERR_INTERNET_DISCONNECTED, ERR_CONNECTION_TIMED_OUT, ERR_NETWORK_CHANGED
325
314
 
326
- **Example:**
327
- ```tsx
328
- // Mock mode (publicKey starts with "test_")
329
- <GlomoLrsCheckout
330
- publicKey="test_abc123..."
331
- // ... other props
332
- />
333
-
334
- // Live mode (publicKey does not start with "test_")
335
- <GlomoLrsCheckout
336
- publicKey="live_xyz789..."
337
- // ... other props
338
- />
339
- ```
315
+ The checkout modal is automatically dismissed on connection errors.
340
316
 
341
- Note that `devMode` is separate and only controls console logging, not the payment mode.
317
+ ## ๐Ÿ›ก๏ธ Input Validation
342
318
 
343
- ### Connection Handling ๐Ÿšจ
319
+ The SDK validates inputs before starting the checkout:
344
320
 
345
- The SDK provides an (optional) `onConnectionError` callback for connection error events. The checkout modal/page will be dismissed/closed, before this callback is triggered.
321
+ | Field | Rule |
322
+ | ----------- | ----------------------------------------------- |
323
+ | `publicKey` | Must start with `live_`, `mock_`, or `test_`. Min 6 characters. |
324
+ | `orderId` | Must start with `order_`. Min 7 characters. |
346
325
 
347
- **Scenarios:**
348
- - Connection failures
349
- - Internet unavailability
350
- - DNS resolution failures
326
+ Validation failures fire `onSdkError` with `type: "validation_error"` and the relevant `field` name. `start()` returns `false`.
351
327
 
352
- **Note:** HTTP `4xx`/`5xx` errors will not be captured as connection errors.
328
+ ## ๐Ÿ”„ Migration from v2
353
329
 
354
- **Example:**
355
- ```tsx
356
- <GlomoLrsCheckout
357
- onConnectionError={(error) => {
358
- // Handle connection/network errors
359
- // The modal will be automatically closed before this callback is triggered
360
- Alert.alert('Connection Error', 'Unable to connect to the GlomoPay servers. Please check your internet connection.');
361
- }}
362
- // ... other props
363
- />
364
- ```
330
+ v3 replaces the LRS-only `GlomoLrsCheckout` with a unified `GlomoCheckout`.
365
331
 
366
- **Note:** `onConnectionError` is for network/connection errors only. Payment-specific failures should be handled by `onPaymentFailure`.
332
+ ### Renamed Exports
367
333
 
368
- ### Device Security Compliance ๐Ÿ›ก๏ธ
334
+ | v2 | v3 |
335
+ | -------------------------- | ------------------------- |
336
+ | `GlomoLrsCheckout` | `GlomoCheckout` |
337
+ | `GlomoLrsCheckoutRef` | `GlomoCheckoutRef` |
338
+ | `GlomoLrsCheckoutProps` | `GlomoCheckoutProps` |
339
+ | `GlomoLrsCheckoutPayload` | `GlomoCheckoutPayload` |
340
+ | `GlomoLrsServer` | `GlomoServer` |
369
341
 
370
- **โš ๏ธ Important:** The SDK provides automatic device security compliance checking via the `jail-monkey` library. For enhanced security compliance and to meet regulatory requirements, we **strongly recommend** installing the optional peer dependency `jail-monkey`.
342
+ ### Breaking Changes
371
343
 
372
- #### Installation
344
+ - **`start()` is now async**: Returns `Promise<boolean>` instead of `boolean`. Update call sites to `await ref.current?.start()`.
345
+ - **New statuses**: `bank_transfer_submitted` and `pay_via_bank_completed` are new additions to `CheckoutStatus`.
346
+ - **New callbacks**: `onBankTransferSubmitted`, `onPayViaBankCompleted`, and `onUserRefusedCameraPermissions` are available.
373
347
 
374
- ```bash
375
- npm install jail-monkey
376
- ```
348
+ For the full list of changes, see [CHANGELOG.md](./CHANGELOG.md).
377
349
 
378
- #### How It Works
350
+ ## ๐Ÿšจ Troubleshooting
379
351
 
380
- - **With `jail-monkey` installed:** The SDK automatically performs device security compliance checks before allowing an LRS checkout to start. Rooted (Android) or jailbroken (iOS) devices are prevented from starting checkouts.
381
- - **Without `jail-monkey`:** The SDK skips automatic compliance checks, and allows checkout to proceed normally. Regulatory compliance would have to be enforced manually.
352
+ ### `start()` returns `false`
382
353
 
383
- #### Features
354
+ Check `onSdkError` for details. Common causes:
355
+ - Invalid `publicKey` format (must start with `live_`, `mock_`, or `test_`)
356
+ - Invalid `orderId` format (must start with `order_`)
357
+ - Device is rooted/jailbroken (when `jail-monkey` is installed)
384
358
 
385
- An automatic device security compliance check:
386
- - Runs synchronously as the **first validation step** in the `start()` method
387
- - Blocks checkout on non-compliant devices to meet regulatory requirements
388
- - Works on both iOS and Android platforms
389
- - Triggers the `onSdkError` callback with a `device_forbidden` error if a non-compliant device is detected
359
+ ### Checkout opens but shows a blank screen
390
360
 
391
- **Example:**
392
- ```tsx
393
- <GlomoLrsCheckout
394
- onSdkError={(errors) => {
395
- errors.forEach((error) => {
396
- if (error.type === 'device_forbidden') {
397
- Alert.alert(
398
- 'Device Unsafe',
399
- 'LRS checkout is not permitted on rooted or jailbroken devices per regulatory compliance requirements.'
400
- );
401
- }
402
- });
403
- }}
404
- // ... other props
405
- />
406
- ```
361
+ - Verify network connectivity
362
+ - Check that the `publicKey` and `orderId` are valid
407
363
 
364
+ ### Camera permission denied
408
365
 
409
- ### Input Validation ๐Ÿ”
366
+ - Ensure `AndroidManifest.xml` and `Info.plist` include camera permission declarations
367
+ - The `onUserRefusedCameraPermissions` callback will fire when the user denies
410
368
 
411
- The SDK automatically validates all inputs:
369
+ ### `onPayViaBankCompleted` not firing
412
370
 
413
- - **`publicKey`**: Must start with `live_` and have a minimum length of 6 characters
414
- - **`orderId`**: Must start with `order_` and have a minimum length of 7 characters
371
+ - Ensure you are passing `onPayViaBankCompleted` as a prop to `GlomoCheckout`
415
372
 
416
- Validation errors are reported through the `onSdkError` callback. The SDK validates inputs when `start()` is called:
417
- - Device security compliance check (first, before any other validation)
418
- - Input validation (publicKey, orderId, and server environment)
419
- - Checkout URL validation (before building the final URL)
373
+ ## ๐Ÿ” Exports
420
374
 
421
- **Example:**
422
- ```tsx
423
- <GlomoLrsCheckout
424
- onSdkError={(errors) => {
425
- if (errors.length > 0) {
426
- // Handle validation errors
427
- Alert.alert(
428
- 'Configuration Error',
429
- errors.map(e => e.message).join('\n')
430
- );
431
- }
432
- }}
433
- // ... other props
434
- />
375
+ ```ts
376
+ // Component
377
+ export { GlomoCheckout } from "@glomopay/react-native-sdk";
378
+
379
+ // Types
380
+ export type {
381
+ GlomoCheckoutRef,
382
+ GlomoCheckoutProps,
383
+ GlomoCheckoutPayload,
384
+ CheckoutStatus,
385
+ GlomoBankTransferPayload,
386
+ GlomoPayViaBankConnectionPayload,
387
+ SdkError,
388
+ } from "@glomopay/react-native-sdk";
389
+
390
+ // Hook (advanced usage)
391
+ export { useGlomoCheckout } from "@glomopay/react-native-sdk";
435
392
  ```
436
393
 
437
394
  ## ๐Ÿ’ฌ Support
438
395
 
439
- ### Documentation
440
- - ๐Ÿ“– API Documentation: https://docs.glomopay.com
441
- - ๐ŸŽ›๏ธ Dashboard: https://dashboard.glomopay.com
442
-
443
- ### Contact Us
444
- - โœ‰๏ธ Email: developer@glomopay.com
445
- - ๐ŸŽŸ๏ธ GitHub Issues: https://github.com/glomopay/glomopay-rn-sdk/issues
446
- - ๐ŸŒ Website: https://glomopay.com
396
+ - GitHub Issues: https://github.com/glomopay/glomopay-rn-sdk/issues
397
+ - Email: developer@glomopay.com
447
398
 
448
- ## License ๐Ÿ“„
399
+ ## ๐Ÿ“„ License
449
400
 
450
- This project is licensed under the Apache License 2.0. See the [LICENSE](LICENSE) file for details.
401
+ Apache-2.0. See [LICENSE](LICENSE) for details.