@glomopay/react-native-sdk 3.0.1 โ†’ 4.0.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 (52) hide show
  1. package/CHANGELOG.md +38 -2
  2. package/MIGRATION.md +129 -0
  3. package/README.md +176 -126
  4. package/lib/glomo-checkout.d.ts +2 -1
  5. package/lib/glomo-checkout.d.ts.map +1 -1
  6. package/lib/glomo-checkout.js +25 -3
  7. package/lib/glomo-lrs-checkout.d.ts +1 -1
  8. package/lib/glomo-lrs-checkout.d.ts.map +1 -1
  9. package/lib/glomo-standard-checkout.d.ts +20 -0
  10. package/lib/glomo-standard-checkout.d.ts.map +1 -1
  11. package/lib/glomo-standard-checkout.js +15 -6
  12. package/lib/glomo-subscriptions-checkout.d.ts +8 -0
  13. package/lib/glomo-subscriptions-checkout.d.ts.map +1 -0
  14. package/lib/glomo-subscriptions-checkout.js +85 -0
  15. package/lib/index.d.ts +3 -3
  16. package/lib/index.d.ts.map +1 -1
  17. package/lib/index.js +5 -3
  18. package/lib/types/checkout.d.ts +33 -22
  19. package/lib/types/checkout.d.ts.map +1 -1
  20. package/lib/types/checkout.js +12 -1
  21. package/lib/types/standard-checkout.d.ts +3 -7
  22. package/lib/types/standard-checkout.d.ts.map +1 -1
  23. package/lib/types/subscriptions-checkout.d.ts +29 -0
  24. package/lib/types/subscriptions-checkout.d.ts.map +1 -0
  25. package/lib/types/subscriptions-checkout.js +3 -0
  26. package/lib/use-glomo-checkout.d.ts +34 -4
  27. package/lib/use-glomo-checkout.d.ts.map +1 -1
  28. package/lib/use-glomo-checkout.js +92 -13
  29. package/lib/use-lrs-checkout.d.ts +1 -1
  30. package/lib/use-lrs-checkout.d.ts.map +1 -1
  31. package/lib/use-standard-checkout.d.ts +14 -9
  32. package/lib/use-standard-checkout.d.ts.map +1 -1
  33. package/lib/use-standard-checkout.js +74 -85
  34. package/lib/utils/analytics.d.ts +86 -3
  35. package/lib/utils/analytics.d.ts.map +1 -1
  36. package/lib/utils/analytics.js +344 -22
  37. package/lib/utils/device-compliance.d.ts.map +1 -1
  38. package/lib/utils/device-compliance.js +0 -1
  39. package/package.json +15 -4
  40. package/src/glomo-checkout.tsx +65 -9
  41. package/src/glomo-lrs-checkout.tsx +1 -1
  42. package/src/glomo-standard-checkout.tsx +35 -10
  43. package/src/glomo-subscriptions-checkout.tsx +83 -0
  44. package/src/index.ts +5 -5
  45. package/src/types/checkout.ts +28 -20
  46. package/src/types/standard-checkout.ts +3 -5
  47. package/src/types/subscriptions-checkout.ts +31 -0
  48. package/src/use-glomo-checkout.tsx +158 -17
  49. package/src/use-lrs-checkout.tsx +1 -1
  50. package/src/use-standard-checkout.tsx +94 -153
  51. package/src/utils/analytics.ts +469 -31
  52. package/src/utils/device-compliance.ts +0 -1
package/CHANGELOG.md CHANGED
@@ -5,6 +5,40 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [4.0.0] - 2026-06-11
9
+
10
+ ### Breaking Changes
11
+
12
+ - **Consolidated async payment callbacks**: `onBankTransferSubmitted` and `onPayViaBankCompleted` have been replaced by a single `onUserJourneyCompleted` callback. The new callback receives a `GlomoUserJourneyCompletedPayload` with a `journeyType` field from the `ASYNC_PAYMENT_EVENTS` enum.
13
+ - **Removed `onPayViaBankBankConnectionSuccessful`**: This informational callback has been removed. It may be reintroduced in a future version if merchant demand warrants it.
14
+ - **Removed types**: `GlomoBankTransferPayload` and `GlomoPayViaBankConnectionPayload` are no longer exported.
15
+ - **`onSdkError` is now required**: Previously optional, `onSdkError` must now be provided. This ensures validation errors, device compliance failures, and configuration issues are handled properly.
16
+
17
+ ### Added
18
+
19
+ - **`ASYNC_PAYMENT_EVENTS` enum**: Enumeration of asynchronous payment event types (`BANK_TRANSFER_SUBMITTED`, `PAY_VIA_BANK_COMPLETED`).
20
+ - **`GlomoUserJourneyCompletedPayload` type**: Flat payload interface with `journeyType`, `orderId?`, `status?`, `senderAccountNumber?`, `transactionReference?`.
21
+ - **`onUserJourneyCompleted` callback**: Single callback for all asynchronous payment flow completions.
22
+
23
+ ### Unchanged
24
+
25
+ - `CheckoutStatus` values `bank_transfer_submitted` and `pay_via_bank_completed` remain for granular `getStatus()` state checks.
26
+
27
+ ## [3.1.0] - 2026-06-08
28
+
29
+ ### Added
30
+
31
+ - **Subscriptions checkout support** - new `subscriptionId` prop on `GlomoCheckout`. When provided, the SDK bypasses order type detection and renders the subscriptions checkout flow directly. No API call is made - the inner checkout component mounts immediately. The `detecting_order_type` status is not emitted for subscription flows.
32
+ - **Mutual exclusion validation** - `GlomoCheckout` validates that exactly one of `orderId` or `subscriptionId` is provided. If both or neither are set, `onSdkError` fires with a clear message and `start()` returns `false`.
33
+
34
+ ### Changed
35
+
36
+ - **`orderId` is now optional** on `GlomoCheckoutProps` - required only when `subscriptionId` is absent.
37
+
38
+ ### Deprecated
39
+
40
+ - **`useGlomoCheckout` hook** - use the `GlomoCheckout` component with a ref instead. The hook does not provide reactive state - `getStatus()` returns a point-in-time snapshot. Will be removed in a future major version.
41
+
8
42
  ## [3.0.1] - 2026-06-02
9
43
 
10
44
  ### Added
@@ -59,6 +93,8 @@ Checkout flows with camera-based bank authentication require native permissions:
59
93
 
60
94
  These are only required for flows that use camera-based bank authentication.
61
95
 
62
- ## [2.0.2]
96
+ ## [2.0.2] - 2025-11-26
97
+
98
+ Private v2 release candidate with experimental features. Not available for general use.
63
99
 
64
- Last v2 release.
100
+ Backwards compatible with `v1.x`
package/MIGRATION.md ADDED
@@ -0,0 +1,129 @@
1
+ # Migration Guide
2
+
3
+ ## v3 to v4
4
+
5
+ v4 consolidates the asynchronous payment flow callbacks into a single generic callback.
6
+
7
+ ### Removed Callbacks
8
+
9
+ | v3 | v4 |
10
+ |---|---|
11
+ | `onBankTransferSubmitted` | Use `onUserJourneyCompleted` with `journeyType: ASYNC_PAYMENT_EVENTS.BANK_TRANSFER_SUBMITTED` |
12
+ | `onPayViaBankCompleted` | Use `onUserJourneyCompleted` with `journeyType: ASYNC_PAYMENT_EVENTS.PAY_VIA_BANK_COMPLETED` |
13
+ | `onPayViaBankBankConnectionSuccessful` | Removed (no replacement) |
14
+
15
+ ### Removed Types
16
+
17
+ | v3 | v4 |
18
+ |---|---|
19
+ | `GlomoBankTransferPayload` | Use `GlomoUserJourneyCompletedPayload` |
20
+ | `GlomoPayViaBankConnectionPayload` | Removed |
21
+
22
+ ### New Types
23
+
24
+ | Type | Purpose |
25
+ |---|---|
26
+ | `ASYNC_PAYMENT_EVENTS` | Enum of asynchronous payment event types |
27
+ | `GlomoUserJourneyCompletedPayload` | Payload for `onUserJourneyCompleted` callback |
28
+
29
+ ### `onSdkError` is now required
30
+
31
+ `onSdkError` was optional in v3. In v4 it is required. If you were not passing it, add it:
32
+
33
+ ```tsx
34
+ onSdkError={(errors) => {
35
+ errors.forEach((e) => console.error(e.type, e.message, e.field));
36
+ }}
37
+ ```
38
+
39
+ ### Unchanged
40
+
41
+ - `CheckoutStatus` values `bank_transfer_submitted` and `pay_via_bank_completed` remain unchanged. `getStatus()` continues to return granular status values.
42
+
43
+ ### Before / After
44
+
45
+ **v3:**
46
+ ```tsx
47
+ <GlomoCheckout
48
+ onBankTransferSubmitted={(payload) => {
49
+ console.log("Transfer ref:", payload?.transactionReference);
50
+ }}
51
+ onPayViaBankCompleted={(payload) => {
52
+ console.log("Pay via bank:", payload.status);
53
+ }}
54
+ onPayViaBankBankConnectionSuccessful={(payload) => {
55
+ console.log("Bank connected:", payload?.bankName);
56
+ }}
57
+ // ...other props
58
+ />
59
+ ```
60
+
61
+ **v4:**
62
+ ```tsx
63
+ import { ASYNC_PAYMENT_EVENTS } from "@glomopay/react-native-sdk";
64
+
65
+ <GlomoCheckout
66
+ onUserJourneyCompleted={(payload) => {
67
+ switch (payload.journeyType) {
68
+ case ASYNC_PAYMENT_EVENTS.BANK_TRANSFER_SUBMITTED:
69
+ console.log("Transfer ref:", payload.transactionReference);
70
+ break;
71
+ case ASYNC_PAYMENT_EVENTS.PAY_VIA_BANK_COMPLETED:
72
+ console.log("Pay via bank:", payload.status);
73
+ break;
74
+ }
75
+ }}
76
+ // ...other props
77
+ />
78
+ ```
79
+
80
+ ---
81
+
82
+ ## v2 to v3
83
+
84
+ v3 replaces the LRS-only `GlomoLrsCheckout` with a unified `GlomoCheckout` that auto-detects order type.
85
+
86
+ ### Renamed Exports
87
+
88
+ | v2 | v3 |
89
+ | -------------------------- | ------------------------- |
90
+ | `GlomoLrsCheckout` | `GlomoCheckout` |
91
+ | `GlomoLrsCheckoutRef` | `GlomoCheckoutRef` |
92
+ | `GlomoLrsCheckoutProps` | `GlomoCheckoutProps` |
93
+ | `GlomoLrsCheckoutPayload` | `GlomoCheckoutPayload` |
94
+ | `GlomoLrsServer` | `GlomoServer` |
95
+
96
+ ### Breaking Changes
97
+
98
+ - **`start()` is now async**: Returns `Promise<boolean>` instead of `boolean`. Update call sites to `await ref.current?.start()`.
99
+ - **New statuses**: `bank_transfer_submitted` and `pay_via_bank_completed` are new additions to `CheckoutStatus`.
100
+ - **New callbacks**: `onBankTransferSubmitted`, `onPayViaBankCompleted`, and `onUserRefusedCameraPermissions` are available.
101
+
102
+ ### Before / After
103
+
104
+ **v2:**
105
+ ```tsx
106
+ import { GlomoLrsCheckout, type GlomoLrsCheckoutRef } from "@glomopay/react-native-sdk";
107
+
108
+ const ref = useRef<GlomoLrsCheckoutRef>(null);
109
+ const started = ref.current?.start(); // boolean
110
+ ```
111
+
112
+ **v3:**
113
+ ```tsx
114
+ import { GlomoCheckout, type GlomoCheckoutRef } from "@glomopay/react-native-sdk";
115
+
116
+ const ref = useRef<GlomoCheckoutRef>(null);
117
+ const started = await ref.current?.start(); // Promise<boolean>
118
+ ```
119
+
120
+ ### Platform Configuration (New in v3)
121
+
122
+ Checkout flows with camera-based bank authentication require native permissions:
123
+
124
+ - **Android** (`AndroidManifest.xml`): `<uses-permission android:name="android.permission.CAMERA" />`
125
+ - **iOS** (`Info.plist`): `NSCameraUsageDescription` key
126
+
127
+ These are only required for flows that use camera-based bank authentication.
128
+
129
+ For the full changelog, see CHANGELOG.md included in this package.
package/README.md CHANGED
@@ -1,28 +1,16 @@
1
- # GlomoPay React Native SDK ๐Ÿ’ณ
1
+ # GlomoPay React Native SDK
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/@glomopay/react-native-sdk.svg)](https://www.npmjs.com/package/@glomopay/react-native-sdk)
4
4
  [![License](https://img.shields.io/npm/l/@glomopay/react-native-sdk.svg)](LICENSE)
5
5
 
6
6
  Official React Native SDK for integrating GlomoPay payment checkout flows into your mobile applications.
7
7
 
8
- ## โœจ Features
9
-
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
19
-
20
- ## ๐Ÿ“‹ Prerequisites
8
+ ## Prerequisites
21
9
 
22
10
  - API credentials (Public Key) from your GlomoPay dashboard
23
11
  - An order ID created via the GlomoPay API
24
12
 
25
- ## ๐Ÿ› ๏ธ System Requirements
13
+ ## System Requirements
26
14
 
27
15
  | Requirement | Version |
28
16
  | ---------------------- | ------------ |
@@ -33,15 +21,7 @@ Official React Native SDK for integrating GlomoPay payment checkout flows into y
33
21
  | react-native-webview | ^13.0.0 |
34
22
  | jail-monkey (optional) | ^2.6.0 |
35
23
 
36
- ## โš ๏ธ Breaking Changes (v3)
37
-
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`)
41
-
42
- For the full list of changes and migration details, see [CHANGELOG.md](./CHANGELOG.md) and [Migration from v2](#-migration-from-v2).
43
-
44
- ## ๐Ÿ“ฆ Installation
24
+ ## Installation
45
25
 
46
26
  ### React Native CLI
47
27
 
@@ -66,13 +46,14 @@ npm install jail-monkey
66
46
 
67
47
  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
48
 
69
- ## ๐Ÿš€ Quick Start
49
+ ## Quick Start
70
50
 
71
51
  ```tsx
72
52
  import React, { useRef } from "react";
73
53
  import { View, Button } from "react-native";
74
54
  import {
75
55
  GlomoCheckout,
56
+ ASYNC_PAYMENT_EVENTS,
76
57
  type GlomoCheckoutRef,
77
58
  type GlomoCheckoutPayload,
78
59
  type SdkError,
@@ -108,14 +89,15 @@ export default function PaymentScreen() {
108
89
  onConnectionError={(error) => {
109
90
  console.log("Connection error:", error);
110
91
  }}
111
- onBankTransferSubmitted={(payload) => {
112
- console.log("Bank transfer submitted:", payload?.transactionReference);
113
- }}
114
- onPayViaBankCompleted={(payload) => {
115
- console.log("Pay via bank completed:", payload.status);
116
- }}
117
- onPayViaBankBankConnectionSuccessful={(payload) => {
118
- console.log("Bank connected:", payload?.bankName);
92
+ onUserJourneyCompleted={(payload) => {
93
+ switch (payload.journeyType) {
94
+ case ASYNC_PAYMENT_EVENTS.BANK_TRANSFER_SUBMITTED:
95
+ console.log("Bank transfer submitted:", payload.transactionReference);
96
+ break;
97
+ case ASYNC_PAYMENT_EVENTS.PAY_VIA_BANK_COMPLETED:
98
+ console.log("Pay via bank completed:", payload.status);
99
+ break;
100
+ }
119
101
  }}
120
102
  onUserRefusedCameraPermissions={() => {
121
103
  console.log("User refused camera - cannot proceed with bank authentication");
@@ -129,7 +111,90 @@ export default function PaymentScreen() {
129
111
  }
130
112
  ```
131
113
 
132
- ## ๐Ÿ“š API Reference
114
+ ## Breaking Changes (v4)
115
+
116
+ - `GlomoLrsCheckout` has been replaced by `GlomoCheckout` - the new component now works for all checkout orders (including LRS)
117
+ - `start()` is now async - returns `Promise<boolean>` instead of `boolean`
118
+ - All LRS-specific exports have been renamed (e.g. `GlomoLrsCheckoutRef` -> `GlomoCheckoutRef`)
119
+ - `onBankTransferSubmitted` and `onPayViaBankCompleted` replaced by a single `onUserJourneyCompleted` callback
120
+ - `onPayViaBankBankConnectionSuccessful` removed entirely
121
+ - `GlomoBankTransferPayload` and `GlomoPayViaBankConnectionPayload` types removed
122
+ - `onSdkError` is now **required** - previously optional, now must be provided to ensure validation and device compliance errors are always surfaced
123
+ - New exports: `ASYNC_PAYMENT_EVENTS` enum and `GlomoUserJourneyCompletedPayload` type
124
+ - `CheckoutStatus` values `bank_transfer_submitted` and `pay_via_bank_completed` are unchanged
125
+
126
+ For migration details, see MIGRATION.md included in this package.
127
+
128
+ ## Subscriptions Checkout
129
+
130
+ To process subscription payments, pass a `subscriptionId` instead of an `orderId`:
131
+
132
+ ```tsx
133
+ <GlomoCheckout
134
+ ref={checkoutRef}
135
+ publicKey="live_pk_abc123"
136
+ subscriptionId="sub_xyz789"
137
+ onPaymentSuccess={(payload) => {
138
+ console.log("Subscription payment success:", payload.paymentId);
139
+ }}
140
+ onPaymentFailure={(payload) => {
141
+ console.log("Subscription payment failed:", payload.paymentId);
142
+ }}
143
+ onSdkError={(errors) => {
144
+ errors.forEach((e) => console.error(e.type, e.message));
145
+ }}
146
+ />
147
+ ```
148
+
149
+ When `subscriptionId` is provided:
150
+ - The SDK skips order type detection (no API call)
151
+ - The `subscriptionId` must start with `sub_`
152
+ - Do not pass both `orderId` and `subscriptionId` - the SDK will fire `onSdkError`
153
+ - The `detecting_order_type` status is not emitted for subscription flows
154
+
155
+ ## Features
156
+
157
+ - **Cross-platform** - works on both iOS and Android
158
+ - **TypeScript** - full type definitions for all exports
159
+ - **Unified checkout** - renders the correct checkout flow automatically based on your order
160
+ - **Asynchronous payment flows** - single `onUserJourneyCompleted` callback for bank transfer and pay via bank events
161
+ - **Camera permissions** - built-in handling for bank authentication
162
+ - **Device security** - optional **(but strongly recommended)** `jail-monkey` integration for rooted/jailbroken device detection
163
+ - **Input validation** - publicKey and orderId format enforcement before checkout starts
164
+ - **Mock mode** - test with `test_` / `mock_` prefixed keys without hitting production
165
+
166
+ ## useGlomoCheckout Hook (Deprecated)
167
+
168
+ > **Deprecated** - Legacy hook, will be removed in a future major version.
169
+
170
+ `useGlomoCheckout` is a legacy placeholder from the v1.x hook-based API. In v1.x, the equivalent
171
+ hook (`useLrsCheckout`) provided reactive WebView state and rendering primitives that merchants used
172
+ to build custom checkout UIs. In v3, the inner checkout components are no longer exported, making
173
+ this hook ineffective for custom rendering.
174
+
175
+ The hook's public return type (`UseGlomoCheckoutReturn`) exposes:
176
+ - `start()` - identical to `GlomoCheckoutRef.start()`. Returns `Promise<boolean>`.
177
+ - `getStatus()` - returns a point-in-time `CheckoutStatus` snapshot. **Not reactive** - does not
178
+ trigger re-renders when status changes.
179
+
180
+ **Use the `GlomoCheckout` component with a ref instead:**
181
+
182
+ ```tsx
183
+ import React, { useRef } from "react";
184
+ import { GlomoCheckout, type GlomoCheckoutRef } from "@glomopay/react-native-sdk";
185
+
186
+ const checkoutRef = useRef<GlomoCheckoutRef>(null);
187
+
188
+ // Start checkout
189
+ const started = await checkoutRef.current?.start();
190
+
191
+ // Check status (point-in-time, same as hook)
192
+ const status = checkoutRef.current?.getStatus();
193
+ ```
194
+
195
+ The component-based API provides the same functionality with proper lifecycle management.
196
+
197
+ ## API Reference
133
198
 
134
199
  ### GlomoCheckout Component
135
200
 
@@ -144,17 +209,18 @@ The unified checkout component. Place it in your render tree and control it via
144
209
  | Prop | Type | Required | Description |
145
210
  | -------------------------------- | ----------------------------------------------- | -------- | ------------------------------------------------------------------- |
146
211
  | `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_`) |
212
+ | `orderId` | `string` | No* | Order ID from the GlomoPay API (must start with `order_`) |
213
+ | `subscriptionId` | `string` | No* | Subscription ID (must start with `sub_`). Bypasses order type detection. |
148
214
  | `onPaymentSuccess` | `(payload: GlomoCheckoutPayload) => void` | Yes | Called when payment succeeds |
149
215
  | `onPaymentFailure` | `(payload: GlomoCheckoutPayload) => void` | Yes | Called when payment fails |
150
216
  | `onConnectionError` | `(error: unknown) => void` | No | Called on network/connection errors |
151
217
  | `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 |
218
+ | `onSdkError` | `(errors: SdkError[]) => void` | Yes | Called on validation errors or device compliance failures |
219
+ | `onUserJourneyCompleted` | `(payload: GlomoUserJourneyCompletedPayload) => void` | No | Called when an asynchronous payment flow completes (bank transfer submission, pay via bank completion). Check `payload.journeyType` to determine the flow. |
156
220
  | `onUserRefusedCameraPermissions` | `() => void` | No | Called when user denies camera access needed for bank authentication |
157
221
 
222
+ *Exactly one of `orderId` or `subscriptionId` must be provided. If both or neither are set, `onSdkError` fires and `start()` returns `false`.
223
+
158
224
  #### Ref Methods (`GlomoCheckoutRef`)
159
225
 
160
226
  | Method | Signature | Description |
@@ -167,6 +233,7 @@ The unified checkout component. Place it in your render tree and control it via
167
233
  | Status | Description |
168
234
  | -------------------------- | -------------------------------------------------------------- |
169
235
  | `ready` | Initial state - checkout can be started |
236
+ | `detecting_order_type` | Order type detection in progress (after `start()`, before checkout opens) |
170
237
  | `payment_in_progress` | Checkout modal is open, user is interacting |
171
238
  | `payment_successful` | Payment completed successfully. Cannot restart with same order |
172
239
  | `payment_failed` | Payment failed. Can retry with same order |
@@ -186,25 +253,24 @@ interface GlomoCheckoutPayload {
186
253
  }
187
254
  ```
188
255
 
189
- #### GlomoBankTransferPayload
256
+ #### ASYNC_PAYMENT_EVENTS
190
257
 
191
258
  ```ts
192
- interface GlomoBankTransferPayload {
193
- orderId: string;
194
- senderAccountNumber: string;
195
- transactionReference: string;
259
+ enum ASYNC_PAYMENT_EVENTS {
260
+ BANK_TRANSFER_SUBMITTED = "bank_transfer_submitted",
261
+ PAY_VIA_BANK_COMPLETED = "pay_via_bank_completed",
196
262
  }
197
263
  ```
198
264
 
199
- #### GlomoPayViaBankConnectionPayload
265
+ #### GlomoUserJourneyCompletedPayload
200
266
 
201
267
  ```ts
202
- interface GlomoPayViaBankConnectionPayload {
203
- bankIdentifier: string;
204
- cooldownPeriodInMinutes: number;
205
- bankName: string;
206
- bankImageSrc: string;
207
- bankImageAlt: string;
268
+ interface GlomoUserJourneyCompletedPayload {
269
+ journeyType: ASYNC_PAYMENT_EVENTS;
270
+ orderId?: string;
271
+ status?: string;
272
+ senderAccountNumber?: string;
273
+ transactionReference?: string;
208
274
  }
209
275
  ```
210
276
 
@@ -214,47 +280,40 @@ interface GlomoPayViaBankConnectionPayload {
214
280
  interface SdkError {
215
281
  type: "validation_error" | "device_forbidden";
216
282
  message: string;
217
- field?: string;
283
+ field?: "publicKey" | "orderId" | "subscriptionId" | "baseCheckoutUrl" | "generatedCheckoutUrl";
218
284
  }
219
285
  ```
220
286
 
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`:
224
-
225
- ```tsx
226
- onBankTransferSubmitted={(payload) => {
227
- // payload may be null/undefined if the checkout page omits it
228
- console.log("Transfer ref:", payload?.transactionReference);
229
- }}
230
- ```
231
-
232
- The checkout status transitions to `bank_transfer_submitted`.
287
+ ## Asynchronous Payment Flows
233
288
 
234
- ## ๐Ÿฆ Pay via Bank Support
235
-
236
- The SDK fires `onPayViaBankCompleted` when the pay-via-bank journey completes:
289
+ The SDK fires `onUserJourneyCompleted` when an asynchronous payment flow completes. Use `payload.journeyType` to determine which flow triggered the callback:
237
290
 
238
291
  ```tsx
239
- onPayViaBankCompleted={(payload) => {
240
- // payload.status - e.g. "success", "failed", "unknown"
241
- console.log("Pay via bank status:", payload.status);
292
+ onUserJourneyCompleted={(payload) => {
293
+ switch (payload.journeyType) {
294
+ case ASYNC_PAYMENT_EVENTS.BANK_TRANSFER_SUBMITTED:
295
+ /**
296
+ * User submitted bank transfer details.
297
+ * Relevant fields: orderId, senderAccountNumber, transactionReference
298
+ * Note: fields may be absent if the checkout page omits them.
299
+ */
300
+ console.log("Transfer ref:", payload.transactionReference);
301
+ break;
302
+ case ASYNC_PAYMENT_EVENTS.PAY_VIA_BANK_COMPLETED:
303
+ /**
304
+ * Pay via bank journey completed.
305
+ * Relevant fields: orderId, status
306
+ * The SDK deduplicates this event - fires only once per session.
307
+ */
308
+ console.log("Pay via bank status:", payload.status);
309
+ break;
310
+ }
242
311
  }}
243
312
  ```
244
313
 
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:
248
-
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
- ```
314
+ The checkout status transitions to `bank_transfer_submitted` or `pay_via_bank_completed` respectively. Use `getStatus()` for granular programmatic checks.
256
315
 
257
- ## ๐Ÿ“ท Camera Permissions for bank authentication
316
+ ## Camera Permissions
258
317
 
259
318
  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.
260
319
 
@@ -280,12 +339,12 @@ Add to `ios/<YourApp>/Info.plist`:
280
339
  - **Android**: SDK prompts the user via a native permission dialog. If denied, checkout closes and `onUserRefusedCameraPermissions` fires.
281
340
  - **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.
282
341
 
283
- ## ๐Ÿ“ฑ Platform Behavior
342
+ ## Platform Behavior
284
343
 
285
344
  - **iOS**: Checkout opens as a `pageSheet` modal (swipe-down to dismiss). Dismissing fires `onPaymentTerminate`.
286
345
  - **Android**: Checkout opens fullscreen. The hardware back button dismisses it and fires `onPaymentTerminate`.
287
346
 
288
- ## ๐Ÿ”’ Device Security Compliance
347
+ ## Device Security Compliance
289
348
 
290
349
  The SDK optionally integrates with `jail-monkey` to detect rooted (Android) or jailbroken (iOS) devices.
291
350
 
@@ -293,7 +352,7 @@ The SDK optionally integrates with `jail-monkey` to detect rooted (Android) or j
293
352
  - If `jail-monkey` is installed and the device is clean: checkout proceeds normally.
294
353
  - If `jail-monkey` is not installed: SDK logs a warning and proceeds without checking. This is not recommended for production deployments handling regulated transactions.
295
354
 
296
- ## ๐Ÿงช Mock Mode
355
+ ## Mock Mode
297
356
 
298
357
  The SDK infers mock mode from the `publicKey` prefix:
299
358
 
@@ -305,7 +364,7 @@ The SDK infers mock mode from the `publicKey` prefix:
305
364
 
306
365
  Mock mode keys route to the sandbox backend. No real transactions are created.
307
366
 
308
- ## ๐ŸŒ Connection Handling
367
+ ## Connection Handling
309
368
 
310
369
  The SDK detects connection errors from the WebView and fires `onConnectionError`:
311
370
 
@@ -314,46 +373,33 @@ The SDK detects connection errors from the WebView and fires `onConnectionError`
314
373
 
315
374
  The checkout modal is automatically dismissed on connection errors.
316
375
 
317
- ## ๐Ÿ›ก๏ธ Input Validation
376
+ ## Input Validation
318
377
 
319
378
  The SDK validates inputs before starting the checkout:
320
379
 
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. |
380
+ | Field | Rule |
381
+ | ---------------- | ----------------------------------------------- |
382
+ | `publicKey` | Must start with `live_`, `mock_`, or `test_`. Min 6 characters. |
383
+ | `orderId` | Must start with `order_`. Min 7 characters. Required when `subscriptionId` is absent. |
384
+ | `subscriptionId` | Must start with `sub_`. Trimmed and checked for emptiness. Required when `orderId` is absent. |
325
385
 
326
386
  Validation failures fire `onSdkError` with `type: "validation_error"` and the relevant `field` name. `start()` returns `false`.
327
387
 
328
- ## ๐Ÿ”„ Migration from v2
329
-
330
- v3 replaces the LRS-only `GlomoLrsCheckout` with a unified `GlomoCheckout`.
331
-
332
- ### Renamed Exports
388
+ Providing both `orderId` and `subscriptionId` (or neither) also fires `onSdkError`.
333
389
 
334
- | v2 | v3 |
335
- | -------------------------- | ------------------------- |
336
- | `GlomoLrsCheckout` | `GlomoCheckout` |
337
- | `GlomoLrsCheckoutRef` | `GlomoCheckoutRef` |
338
- | `GlomoLrsCheckoutProps` | `GlomoCheckoutProps` |
339
- | `GlomoLrsCheckoutPayload` | `GlomoCheckoutPayload` |
340
- | `GlomoLrsServer` | `GlomoServer` |
390
+ ## Migration from v1/v3
341
391
 
342
- ### Breaking Changes
392
+ See MIGRATION.md included in this package for migration guides with before/after code examples.
343
393
 
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.
347
-
348
- For the full list of changes, see [CHANGELOG.md](./CHANGELOG.md).
349
-
350
- ## ๐Ÿšจ Troubleshooting
394
+ ## Troubleshooting
351
395
 
352
396
  ### `start()` returns `false`
353
397
 
354
398
  Check `onSdkError` for details. Common causes:
355
399
  - Invalid `publicKey` format (must start with `live_`, `mock_`, or `test_`)
356
400
  - Invalid `orderId` format (must start with `order_`)
401
+ - Invalid `subscriptionId` format (must start with `sub_`, non-empty after trimming)
402
+ - Both `orderId` and `subscriptionId` provided (or neither)
357
403
  - Device is rooted/jailbroken (when `jail-monkey` is installed)
358
404
 
359
405
  ### Checkout opens but shows a blank screen
@@ -364,38 +410,42 @@ Check `onSdkError` for details. Common causes:
364
410
  ### Camera permission denied
365
411
 
366
412
  - Ensure `AndroidManifest.xml` and `Info.plist` include camera permission declarations
367
- - The `onUserRefusedCameraPermissions` callback will fire when the user denies
368
-
369
- ### `onPayViaBankCompleted` not firing
370
-
371
- - Ensure you are passing `onPayViaBankCompleted` as a prop to `GlomoCheckout`
413
+ - The `onUserRefusedCameraPermissions` callback will fire when the user denies camera permissions to your app
372
414
 
373
- ## ๐Ÿ” Exports
415
+ ## Exports
374
416
 
375
417
  ```ts
376
- // Component
418
+ // Components
377
419
  export { GlomoCheckout } from "@glomopay/react-native-sdk";
378
420
 
421
+ // Hooks (deprecated - use GlomoCheckout component with ref instead)
422
+ export { useGlomoCheckout } from "@glomopay/react-native-sdk";
423
+
424
+ // Enums
425
+ export { ASYNC_PAYMENT_EVENTS } from "@glomopay/react-native-sdk";
426
+
379
427
  // Types
380
428
  export type {
381
429
  GlomoCheckoutRef,
382
430
  GlomoCheckoutProps,
383
431
  GlomoCheckoutPayload,
384
432
  CheckoutStatus,
385
- GlomoBankTransferPayload,
386
- GlomoPayViaBankConnectionPayload,
433
+ GlomoUserJourneyCompletedPayload,
434
+ UseGlomoCheckoutReturn, // deprecated
387
435
  SdkError,
388
436
  } from "@glomopay/react-native-sdk";
389
-
390
- // Hook (advanced usage)
391
- export { useGlomoCheckout } from "@glomopay/react-native-sdk";
392
437
  ```
393
438
 
394
- ## ๐Ÿ’ฌ Support
439
+ ## Security
440
+
441
+ Device integrity checking is available via optional `jail-monkey` integration (see [Device Security Compliance](#device-security-compliance)).
442
+
443
+ To report a security vulnerability, email security@glomopay.com.
444
+
445
+ ## Support
395
446
 
396
- - GitHub Issues: https://github.com/glomopay/glomopay-rn-sdk/issues
397
447
  - Email: developer@glomopay.com
398
448
 
399
- ## ๐Ÿ“„ License
449
+ ## License
400
450
 
401
451
  Apache-2.0. See [LICENSE](LICENSE) for details.
@@ -1,6 +1,7 @@
1
1
  /**
2
- * The unified GlomoPay Checkout Component (v3).
2
+ * The unified GlomoPay Checkout Component (v4).
3
3
  * Detects order type (LRS vs Standard) and delegates rendering to the appropriate inner component.
4
+ * Enforces error handling via `onSdkError()` as a mandatory prop.
4
5
  */
5
6
  import React from "react";
6
7
  import { type GlomoCheckoutRef, type GlomoCheckoutProps } from "./types/checkout";
@@ -1 +1 @@
1
- {"version":3,"file":"glomo-checkout.d.ts","sourceRoot":"","sources":["../src/glomo-checkout.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAA0C,MAAM,OAAO,CAAC;AAG/D,OAAO,EAAE,KAAK,gBAAgB,EAAE,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AA8DlF,eAAO,MAAM,aAAa,6FAA2E,CAAC"}
1
+ {"version":3,"file":"glomo-checkout.d.ts","sourceRoot":"","sources":["../src/glomo-checkout.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAsE,MAAM,OAAO,CAAC;AAG3F,OAAO,EAAE,KAAK,gBAAgB,EAAE,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAqHlF,eAAO,MAAM,aAAa,6FAA2E,CAAC"}