@glomopay/react-native-sdk 2.0.2 → 3.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.
- package/CHANGELOG.md +79 -0
- package/MIGRATION.md +50 -0
- package/README.md +348 -316
- package/lib/config/base.d.ts +17 -11
- package/lib/config/base.d.ts.map +1 -1
- package/lib/config/base.js +19 -7
- package/lib/config/segment.js +3 -3
- package/lib/glomo-checkout.d.ts +8 -0
- package/lib/glomo-checkout.d.ts.map +1 -0
- package/lib/glomo-checkout.js +106 -0
- package/lib/glomo-lrs-checkout.js +9 -9
- package/lib/glomo-standard-checkout.d.ts +25 -0
- package/lib/glomo-standard-checkout.d.ts.map +1 -0
- package/lib/glomo-standard-checkout.js +229 -0
- package/lib/glomo-subscriptions-checkout.d.ts +8 -0
- package/lib/glomo-subscriptions-checkout.d.ts.map +1 -0
- package/lib/glomo-subscriptions-checkout.js +85 -0
- package/lib/index.d.ts +5 -4
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +7 -5
- package/lib/injections/index.d.ts +1 -0
- package/lib/injections/index.d.ts.map +1 -1
- package/lib/injections/index.js +2 -0
- package/lib/injections/webview-flow.injection.d.ts.map +1 -1
- package/lib/injections/webview-flow.injection.js +106 -69
- package/lib/injections/webview-main.injection.d.ts.map +1 -1
- package/lib/injections/webview-main.injection.js +112 -77
- package/lib/injections/webview-standard.injection.d.ts +3 -0
- package/lib/injections/webview-standard.injection.d.ts.map +1 -0
- package/lib/injections/webview-standard.injection.js +214 -0
- package/lib/services/order-type-fetcher.d.ts +28 -0
- package/lib/services/order-type-fetcher.d.ts.map +1 -0
- package/lib/services/order-type-fetcher.js +99 -0
- package/lib/types/checkout.d.ts +65 -0
- package/lib/types/checkout.d.ts.map +1 -0
- package/lib/types/checkout.js +3 -0
- package/lib/types/standard-checkout.d.ts +40 -0
- package/lib/types/standard-checkout.d.ts.map +1 -0
- package/lib/types/standard-checkout.js +3 -0
- package/lib/types/subscriptions-checkout.d.ts +29 -0
- package/lib/types/subscriptions-checkout.d.ts.map +1 -0
- package/lib/types/subscriptions-checkout.js +3 -0
- package/lib/use-glomo-checkout.d.ts +54 -0
- package/lib/use-glomo-checkout.d.ts.map +1 -0
- package/lib/use-glomo-checkout.js +261 -0
- package/lib/use-lrs-checkout.d.ts +9 -4
- package/lib/use-lrs-checkout.d.ts.map +1 -1
- package/lib/use-lrs-checkout.js +76 -93
- package/lib/use-standard-checkout.d.ts +74 -0
- package/lib/use-standard-checkout.d.ts.map +1 -0
- package/lib/use-standard-checkout.js +849 -0
- package/lib/utils/analytics.d.ts +188 -2
- package/lib/utils/analytics.d.ts.map +1 -1
- package/lib/utils/analytics.js +636 -22
- package/lib/utils/device-compliance.d.ts.map +1 -1
- package/lib/utils/device-compliance.js +3 -4
- package/lib/utils/validation.d.ts.map +1 -1
- package/lib/utils/validation.js +7 -6
- package/package.json +17 -5
- package/src/config/base.ts +36 -17
- package/src/config/segment.ts +3 -3
- package/src/glomo-checkout.tsx +147 -0
- package/src/glomo-lrs-checkout.tsx +9 -9
- package/src/glomo-standard-checkout.tsx +353 -0
- package/src/glomo-subscriptions-checkout.tsx +83 -0
- package/src/index.ts +13 -7
- package/src/injections/index.ts +2 -0
- package/src/injections/webview-flow.injection.ts +106 -69
- package/src/injections/webview-main.injection.ts +112 -77
- package/src/injections/webview-standard.injection.ts +211 -0
- package/src/services/order-type-fetcher.ts +86 -0
- package/src/types/checkout.ts +72 -0
- package/src/types/standard-checkout.ts +49 -0
- package/src/types/subscriptions-checkout.ts +31 -0
- package/src/use-glomo-checkout.tsx +369 -0
- package/src/use-lrs-checkout.tsx +91 -111
- package/src/use-standard-checkout.tsx +1203 -0
- package/src/utils/analytics.ts +908 -34
- package/src/utils/device-compliance.ts +3 -4
- package/src/utils/validation.ts +7 -8
package/README.md
CHANGED
|
@@ -1,135 +1,107 @@
|
|
|
1
|
-
# GlomoPay React Native SDK
|
|
1
|
+
# GlomoPay React Native SDK
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@glomopay/react-native-sdk)
|
|
4
4
|
[](LICENSE)
|
|
5
5
|
|
|
6
6
|
Official React Native SDK for integrating GlomoPay payment checkout flows into your mobile applications.
|
|
7
7
|
|
|
8
|
-
##
|
|
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
|
|
16
|
-
|
|
17
|
-
## 📋 Prerequisites
|
|
18
|
-
|
|
19
|
-
Before using this SDK, you need:
|
|
8
|
+
## Prerequisites
|
|
20
9
|
|
|
21
10
|
- API credentials (Public Key) from your GlomoPay dashboard
|
|
11
|
+
- An order ID created via the GlomoPay API
|
|
22
12
|
|
|
23
|
-
##
|
|
24
|
-
|
|
25
|
-
- React Native >= 0.68.0
|
|
26
|
-
- React >= 17.0.0
|
|
27
|
-
- Node.js >= 16.0.0
|
|
28
|
-
- npm >= 8.0.0
|
|
13
|
+
## System Requirements
|
|
29
14
|
|
|
30
|
-
|
|
15
|
+
| Requirement | Version |
|
|
16
|
+
| ---------------------- | ------------ |
|
|
17
|
+
| Node.js | >= 16.0.0 |
|
|
18
|
+
| npm | >= 8.0.0 |
|
|
19
|
+
| React | >= 17.0.0 |
|
|
20
|
+
| React Native | >= 0.68.0 |
|
|
21
|
+
| react-native-webview | ^13.0.0 |
|
|
22
|
+
| jail-monkey (optional) | ^2.6.0 |
|
|
31
23
|
|
|
32
|
-
|
|
24
|
+
## Installation
|
|
33
25
|
|
|
34
|
-
|
|
26
|
+
### React Native CLI
|
|
35
27
|
|
|
36
28
|
```bash
|
|
37
|
-
npm install react-native-webview
|
|
29
|
+
npm install @glomopay/react-native-sdk react-native-webview
|
|
30
|
+
cd ios && pod install
|
|
38
31
|
```
|
|
39
32
|
|
|
40
|
-
|
|
33
|
+
### Expo
|
|
41
34
|
|
|
42
35
|
```bash
|
|
43
|
-
|
|
36
|
+
npx expo install @glomopay/react-native-sdk react-native-webview
|
|
44
37
|
```
|
|
45
38
|
|
|
46
|
-
|
|
39
|
+
### Recommended: Device Security Compliance
|
|
47
40
|
|
|
48
|
-
For
|
|
41
|
+
For rooted/jailbroken device detection (strongly recommended for regulated flows):
|
|
49
42
|
|
|
50
43
|
```bash
|
|
51
44
|
npm install jail-monkey
|
|
52
45
|
```
|
|
53
46
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
### 🔧 2. Expo Projects
|
|
57
|
-
|
|
58
|
-
This SDK is compatible with Expo projects. Install with:
|
|
59
|
-
|
|
60
|
-
```bash
|
|
61
|
-
npx expo install react-native-webview
|
|
62
|
-
npx expo install @glomopay/react-native-sdk
|
|
63
|
-
```
|
|
64
|
-
|
|
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/).
|
|
68
|
-
|
|
69
|
-
## 🚀 Quick Start
|
|
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_`).
|
|
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.
|
|
72
48
|
|
|
73
|
-
|
|
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
|
|
49
|
+
## Quick Start
|
|
78
50
|
|
|
79
51
|
```tsx
|
|
52
|
+
import React, { useRef } from "react";
|
|
53
|
+
import { View, Button } from "react-native";
|
|
80
54
|
import {
|
|
81
|
-
|
|
82
|
-
type
|
|
55
|
+
GlomoCheckout,
|
|
56
|
+
type GlomoCheckoutRef,
|
|
57
|
+
type GlomoCheckoutPayload,
|
|
83
58
|
type SdkError,
|
|
84
|
-
} from
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
### 2. Add the Component to Your App
|
|
88
|
-
|
|
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';
|
|
59
|
+
} from "@glomopay/react-native-sdk";
|
|
96
60
|
|
|
97
|
-
function
|
|
98
|
-
|
|
99
|
-
const [orderId, setOrderId] = useState('YOUR_ORDER_ID');
|
|
100
|
-
const checkoutRef = useRef<GlomoLrsCheckoutRef>(null);
|
|
61
|
+
export default function PaymentScreen() {
|
|
62
|
+
const checkoutRef = useRef<GlomoCheckoutRef>(null);
|
|
101
63
|
|
|
102
|
-
const
|
|
103
|
-
const started = checkoutRef.current?.start();
|
|
64
|
+
const handlePay = async () => {
|
|
65
|
+
const started = await checkoutRef.current?.start();
|
|
104
66
|
if (!started) {
|
|
105
|
-
|
|
106
|
-
console.log('Checkout could not be started. Current status:', status);
|
|
67
|
+
console.log("Checkout could not start - check onSdkError for details");
|
|
107
68
|
}
|
|
108
69
|
};
|
|
109
70
|
|
|
110
71
|
return (
|
|
111
|
-
<View>
|
|
112
|
-
<
|
|
72
|
+
<View style={{ flex: 1 }}>
|
|
73
|
+
<Button title="Pay Now" onPress={handlePay} />
|
|
74
|
+
|
|
75
|
+
<GlomoCheckout
|
|
113
76
|
ref={checkoutRef}
|
|
114
|
-
publicKey=
|
|
115
|
-
orderId=
|
|
116
|
-
onPaymentSuccess={(payload) => {
|
|
117
|
-
console.log(
|
|
118
|
-
|
|
77
|
+
publicKey="live_pk_abc123"
|
|
78
|
+
orderId="order_xyz789"
|
|
79
|
+
onPaymentSuccess={(payload: GlomoCheckoutPayload) => {
|
|
80
|
+
console.log("Payment success:", payload.paymentId);
|
|
81
|
+
}}
|
|
82
|
+
onPaymentFailure={(payload: GlomoCheckoutPayload) => {
|
|
83
|
+
console.log("Payment failed:", payload.paymentId);
|
|
119
84
|
}}
|
|
120
|
-
|
|
121
|
-
console.log(
|
|
122
|
-
// Handle failed payment
|
|
85
|
+
onPaymentTerminate={() => {
|
|
86
|
+
console.log("User dismissed checkout");
|
|
123
87
|
}}
|
|
124
88
|
onConnectionError={(error) => {
|
|
125
|
-
console.log(
|
|
126
|
-
|
|
89
|
+
console.log("Connection error:", error);
|
|
90
|
+
}}
|
|
91
|
+
onBankTransferSubmitted={(payload) => {
|
|
92
|
+
console.log("Bank transfer submitted:", payload?.transactionReference);
|
|
93
|
+
}}
|
|
94
|
+
onPayViaBankCompleted={(payload) => {
|
|
95
|
+
console.log("Pay via bank completed:", payload.status);
|
|
96
|
+
}}
|
|
97
|
+
onPayViaBankBankConnectionSuccessful={(payload) => {
|
|
98
|
+
console.log("Bank connected:", payload?.bankName);
|
|
127
99
|
}}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
100
|
+
onUserRefusedCameraPermissions={() => {
|
|
101
|
+
console.log("User refused camera - cannot proceed with bank authentication");
|
|
102
|
+
}}
|
|
103
|
+
onSdkError={(errors: SdkError[]) => {
|
|
104
|
+
errors.forEach((e) => console.error(e.type, e.message, e.field));
|
|
133
105
|
}}
|
|
134
106
|
/>
|
|
135
107
|
</View>
|
|
@@ -137,314 +109,374 @@ function CheckoutScreen()
|
|
|
137
109
|
}
|
|
138
110
|
```
|
|
139
111
|
|
|
140
|
-
##
|
|
112
|
+
## Breaking Changes (v3)
|
|
141
113
|
|
|
142
|
-
|
|
114
|
+
- `GlomoLrsCheckout` has been replaced by `GlomoCheckout` - the new component now works for all checkout orders (including LRS)
|
|
115
|
+
- `start()` is now async - returns `Promise<boolean>` instead of `boolean`
|
|
116
|
+
- All LRS-specific exports have been renamed (e.g. `GlomoLrsCheckoutRef` -> `GlomoCheckoutRef`)
|
|
143
117
|
|
|
144
|
-
|
|
118
|
+
For migration details, see the [Migration from v2](#migration-from-v2) section below or MIGRATION.md included in this package.
|
|
145
119
|
|
|
146
|
-
|
|
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. |
|
|
120
|
+
## Subscriptions Checkout
|
|
157
121
|
|
|
158
|
-
|
|
122
|
+
To process subscription payments, pass a `subscriptionId` instead of an `orderId`:
|
|
159
123
|
|
|
160
124
|
```tsx
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
125
|
+
<GlomoCheckout
|
|
126
|
+
ref={checkoutRef}
|
|
127
|
+
publicKey="live_pk_abc123"
|
|
128
|
+
subscriptionId="sub_xyz789"
|
|
129
|
+
onPaymentSuccess={(payload) => {
|
|
130
|
+
console.log("Subscription payment success:", payload.paymentId);
|
|
131
|
+
}}
|
|
132
|
+
onPaymentFailure={(payload) => {
|
|
133
|
+
console.log("Subscription payment failed:", payload.paymentId);
|
|
134
|
+
}}
|
|
135
|
+
onSdkError={(errors) => {
|
|
136
|
+
errors.forEach((e) => console.error(e.type, e.message));
|
|
137
|
+
}}
|
|
138
|
+
/>
|
|
165
139
|
```
|
|
166
140
|
|
|
167
|
-
|
|
141
|
+
When `subscriptionId` is provided:
|
|
142
|
+
- The SDK skips order type detection (no API call)
|
|
143
|
+
- The `subscriptionId` must start with `sub_`
|
|
144
|
+
- Bank transfer callbacks (`onBankTransferSubmitted`, `onPayViaBankCompleted`) are not applicable - subscriptions are card-only
|
|
145
|
+
- Do not pass both `orderId` and `subscriptionId` - the SDK will fire `onSdkError`
|
|
146
|
+
- The `detecting_order_type` status is not emitted for subscription flows
|
|
147
|
+
|
|
148
|
+
## Features
|
|
149
|
+
|
|
150
|
+
- **Cross-platform** - works on both iOS and Android
|
|
151
|
+
- **TypeScript** - full type definitions for all exports
|
|
152
|
+
- **Unified checkout** - renders the correct checkout flow automatically based on your order
|
|
153
|
+
- **Bank transfer support** - callback for bank transfer submission events
|
|
154
|
+
- **Pay via bank** - bank payment flow completion and connection callbacks
|
|
155
|
+
- **Camera permissions** - built-in handling for bank authentication
|
|
156
|
+
- **Device security** - optional **(but strongly recommended)** `jail-monkey` integration for rooted/jailbroken device detection
|
|
157
|
+
- **Input validation** - publicKey and orderId format enforcement before checkout starts
|
|
158
|
+
- **Mock mode** - test with `test_` / `mock_` prefixed keys without hitting production
|
|
159
|
+
|
|
160
|
+
## useGlomoCheckout Hook (Deprecated)
|
|
161
|
+
|
|
162
|
+
> **Deprecated** - Legacy hook, will be removed in a future major version.
|
|
163
|
+
|
|
164
|
+
`useGlomoCheckout` is a legacy placeholder from the v1.x hook-based API. In v1.x, the equivalent
|
|
165
|
+
hook (`useLrsCheckout`) provided reactive WebView state and rendering primitives that merchants used
|
|
166
|
+
to build custom checkout UIs. In v3, the inner checkout components are no longer exported, making
|
|
167
|
+
this hook ineffective for custom rendering.
|
|
168
|
+
|
|
169
|
+
The hook's public return type (`UseGlomoCheckoutReturn`) exposes:
|
|
170
|
+
- `start()` - identical to `GlomoCheckoutRef.start()`. Returns `Promise<boolean>`.
|
|
171
|
+
- `getStatus()` - returns a point-in-time `CheckoutStatus` snapshot. **Not reactive** - does not
|
|
172
|
+
trigger re-renders when status changes.
|
|
173
|
+
|
|
174
|
+
**Use the `GlomoCheckout` component with a ref instead:**
|
|
175
|
+
|
|
168
176
|
```tsx
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
177
|
+
import React, { useRef } from "react";
|
|
178
|
+
import { GlomoCheckout, type GlomoCheckoutRef } from "@glomopay/react-native-sdk";
|
|
179
|
+
|
|
180
|
+
const checkoutRef = useRef<GlomoCheckoutRef>(null);
|
|
181
|
+
|
|
182
|
+
// Start checkout
|
|
183
|
+
const started = await checkoutRef.current?.start();
|
|
184
|
+
|
|
185
|
+
// Check status (point-in-time, same as hook)
|
|
186
|
+
const status = checkoutRef.current?.getStatus();
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
The component-based API provides the same functionality with proper lifecycle management.
|
|
190
|
+
|
|
191
|
+
## API Reference
|
|
178
192
|
|
|
179
|
-
|
|
180
|
-
|
|
193
|
+
### GlomoCheckout Component
|
|
194
|
+
|
|
195
|
+
The unified checkout component. Place it in your render tree and control it via a ref.
|
|
196
|
+
|
|
197
|
+
```tsx
|
|
198
|
+
<GlomoCheckout ref={checkoutRef} {...props} />
|
|
181
199
|
```
|
|
182
200
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
201
|
+
#### Props (`GlomoCheckoutProps`)
|
|
202
|
+
|
|
203
|
+
| Prop | Type | Required | Description |
|
|
204
|
+
| -------------------------------- | ----------------------------------------------- | -------- | ------------------------------------------------------------------- |
|
|
205
|
+
| `publicKey` | `string` | Yes | Your GlomoPay public key (must start with `live_`, `mock_`, or `test_`) |
|
|
206
|
+
| `orderId` | `string` | No* | Order ID from the GlomoPay API (must start with `order_`) |
|
|
207
|
+
| `subscriptionId` | `string` | No* | Subscription ID (must start with `sub_`). Bypasses order type detection. |
|
|
208
|
+
| `onPaymentSuccess` | `(payload: GlomoCheckoutPayload) => void` | Yes | Called when payment succeeds |
|
|
209
|
+
| `onPaymentFailure` | `(payload: GlomoCheckoutPayload) => void` | Yes | Called when payment fails |
|
|
210
|
+
| `onConnectionError` | `(error: unknown) => void` | No | Called on network/connection errors |
|
|
211
|
+
| `onPaymentTerminate` | `() => void` | No | Called when user dismisses checkout (back button or swipe) |
|
|
212
|
+
| `onSdkError` | `(errors: SdkError[]) => void` | No | Called on validation errors or device compliance failures |
|
|
213
|
+
| `onBankTransferSubmitted` | `(payload: GlomoBankTransferPayload \| null \| undefined) => void` | No | Called when user submits bank transfer details |
|
|
214
|
+
| `onPayViaBankCompleted` | `(payload: { status: string }) => void` | No | Called when pay via bank flow completes |
|
|
215
|
+
| `onPayViaBankBankConnectionSuccessful` | `(payload: GlomoPayViaBankConnectionPayload \| null \| undefined) => void` | No | Called when bank connection is established during pay via bank flow |
|
|
216
|
+
| `onUserRefusedCameraPermissions` | `() => void` | No | Called when user denies camera access needed for bank authentication |
|
|
217
|
+
|
|
218
|
+
*Exactly one of `orderId` or `subscriptionId` must be provided. If both or neither are set, `onSdkError` fires and `start()` returns `false`.
|
|
219
|
+
|
|
220
|
+
#### Ref Methods (`GlomoCheckoutRef`)
|
|
221
|
+
|
|
222
|
+
| Method | Signature | Description |
|
|
223
|
+
| ------------ | ------------------------ | --------------------------------------------------------------------------------------------------------- |
|
|
224
|
+
| `start()` | `() => Promise<boolean>` | Validates inputs, and opens the checkout modal. Resolves `true` if successful, `false` otherwise. |
|
|
225
|
+
| `getStatus()`| `() => CheckoutStatus` | Returns the current checkout status. |
|
|
226
|
+
|
|
227
|
+
#### CheckoutStatus
|
|
228
|
+
|
|
229
|
+
| Status | Description |
|
|
230
|
+
| -------------------------- | -------------------------------------------------------------- |
|
|
231
|
+
| `ready` | Initial state - checkout can be started |
|
|
232
|
+
| `detecting_order_type` | Order type detection in progress (after `start()`, before checkout opens) |
|
|
233
|
+
| `payment_in_progress` | Checkout modal is open, user is interacting |
|
|
234
|
+
| `payment_successful` | Payment completed successfully. Cannot restart with same order |
|
|
235
|
+
| `payment_failed` | Payment failed. Can retry with same order |
|
|
236
|
+
| `payment_cancelled` | User dismissed checkout mid-flow. Can retry |
|
|
237
|
+
| `bank_transfer_submitted` | User submitted bank transfer details |
|
|
238
|
+
| `pay_via_bank_completed` | Pay via bank flow completed |
|
|
239
|
+
|
|
240
|
+
### Type Definitions
|
|
241
|
+
|
|
242
|
+
#### GlomoCheckoutPayload
|
|
243
|
+
|
|
244
|
+
```ts
|
|
245
|
+
interface GlomoCheckoutPayload {
|
|
246
|
+
orderId: string;
|
|
247
|
+
paymentId: string;
|
|
248
|
+
signature: string;
|
|
202
249
|
}
|
|
203
250
|
```
|
|
204
251
|
|
|
205
|
-
|
|
252
|
+
#### GlomoBankTransferPayload
|
|
206
253
|
|
|
207
|
-
|
|
254
|
+
```ts
|
|
255
|
+
interface GlomoBankTransferPayload {
|
|
256
|
+
orderId: string;
|
|
257
|
+
senderAccountNumber: string;
|
|
258
|
+
transactionReference: string;
|
|
259
|
+
}
|
|
260
|
+
```
|
|
208
261
|
|
|
209
|
-
|
|
262
|
+
#### GlomoPayViaBankConnectionPayload
|
|
210
263
|
|
|
211
|
-
```
|
|
264
|
+
```ts
|
|
265
|
+
interface GlomoPayViaBankConnectionPayload {
|
|
266
|
+
bankIdentifier: string;
|
|
267
|
+
cooldownPeriodInMinutes: number;
|
|
268
|
+
bankName: string;
|
|
269
|
+
bankImageSrc: string;
|
|
270
|
+
bankImageAlt: string;
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
#### SdkError
|
|
275
|
+
|
|
276
|
+
```ts
|
|
212
277
|
interface SdkError {
|
|
213
278
|
type: "validation_error" | "device_forbidden";
|
|
214
279
|
message: string;
|
|
215
|
-
field?: "publicKey" | "orderId" | "baseCheckoutUrl";
|
|
280
|
+
field?: "publicKey" | "orderId" | "subscriptionId" | "baseCheckoutUrl" | "generatedCheckoutUrl";
|
|
216
281
|
}
|
|
217
282
|
```
|
|
218
283
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
284
|
+
## Bank Transfer Support
|
|
285
|
+
|
|
286
|
+
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
287
|
|
|
223
|
-
**Example:**
|
|
224
288
|
```tsx
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
if (error.field) {
|
|
230
|
-
console.error(`Field: ${error.field}`);
|
|
231
|
-
}
|
|
232
|
-
});
|
|
233
|
-
// Handle validation errors appropriately
|
|
234
|
-
}}
|
|
235
|
-
// ... other props
|
|
236
|
-
/>
|
|
289
|
+
onBankTransferSubmitted={(payload) => {
|
|
290
|
+
// payload may be null/undefined if the checkout page omits it
|
|
291
|
+
console.log("Transfer ref:", payload?.transactionReference);
|
|
292
|
+
}}
|
|
237
293
|
```
|
|
238
294
|
|
|
239
|
-
|
|
295
|
+
The checkout status transitions to `bank_transfer_submitted`.
|
|
240
296
|
|
|
241
|
-
|
|
297
|
+
## Pay via Bank Support
|
|
242
298
|
|
|
243
|
-
The SDK
|
|
299
|
+
The SDK fires `onPayViaBankCompleted` when the pay-via-bank journey completes:
|
|
244
300
|
|
|
245
301
|
```tsx
|
|
246
|
-
|
|
247
|
-
|
|
302
|
+
onPayViaBankCompleted={(payload) => {
|
|
303
|
+
// payload.status - e.g. "success", "failed", "unknown"
|
|
304
|
+
console.log("Pay via bank status:", payload.status);
|
|
305
|
+
}}
|
|
248
306
|
```
|
|
249
307
|
|
|
250
|
-
|
|
308
|
+
The checkout status transitions to `pay_via_bank_completed`. The SDK deduplicates this event internally - the callback fires only once per checkout session.
|
|
251
309
|
|
|
252
|
-
|
|
310
|
+
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:
|
|
311
|
+
|
|
312
|
+
```tsx
|
|
313
|
+
onPayViaBankBankConnectionSuccessful={(payload) => {
|
|
314
|
+
// payload may be null/undefined if the checkout page omits it
|
|
315
|
+
console.log("Connected to:", payload?.bankName);
|
|
316
|
+
console.log("Cooldown:", payload?.cooldownPeriodInMinutes, "minutes");
|
|
317
|
+
}}
|
|
318
|
+
```
|
|
253
319
|
|
|
254
|
-
|
|
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`) |
|
|
320
|
+
## Camera Permissions
|
|
261
321
|
|
|
262
|
-
|
|
322
|
+
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
323
|
|
|
324
|
+
### Android
|
|
325
|
+
|
|
326
|
+
Add to `android/app/src/main/AndroidManifest.xml`:
|
|
327
|
+
|
|
328
|
+
```xml
|
|
329
|
+
<uses-permission android:name="android.permission.CAMERA" />
|
|
264
330
|
```
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
331
|
+
|
|
332
|
+
### iOS
|
|
333
|
+
|
|
334
|
+
Add to `ios/<YourApp>/Info.plist`:
|
|
335
|
+
|
|
336
|
+
```xml
|
|
337
|
+
<key>NSCameraUsageDescription</key>
|
|
338
|
+
<string>Camera access is required for identity verification during checkout</string>
|
|
270
339
|
```
|
|
271
340
|
|
|
272
|
-
|
|
341
|
+
### Behavior
|
|
273
342
|
|
|
274
|
-
|
|
275
|
-
-
|
|
276
|
-
- Users can dismiss `GlomoLrsCheckout` component by swiping down
|
|
277
|
-
- `onPaymentTerminate` is called when modal is dismissed
|
|
343
|
+
- **Android**: SDK prompts the user via a native permission dialog. If denied, checkout closes and `onUserRefusedCameraPermissions` fires.
|
|
344
|
+
- **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
345
|
|
|
279
|
-
|
|
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
|
|
346
|
+
## Platform Behavior
|
|
283
347
|
|
|
284
|
-
|
|
348
|
+
- **iOS**: Checkout opens as a `pageSheet` modal (swipe-down to dismiss). Dismissing fires `onPaymentTerminate`.
|
|
349
|
+
- **Android**: Checkout opens fullscreen. The hardware back button dismisses it and fires `onPaymentTerminate`.
|
|
285
350
|
|
|
286
|
-
|
|
351
|
+
## Device Security Compliance
|
|
287
352
|
|
|
288
|
-
|
|
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
|
|
353
|
+
The SDK optionally integrates with `jail-monkey` to detect rooted (Android) or jailbroken (iOS) devices.
|
|
299
354
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
-
|
|
303
|
-
- Use custom dev client: `npx expo prebuild`
|
|
304
|
-
- Or use EAS Build for testing
|
|
355
|
+
- If `jail-monkey` is installed and the device is compromised: `start()` returns `false` and `onSdkError` fires with `type: "device_forbidden"`.
|
|
356
|
+
- If `jail-monkey` is installed and the device is clean: checkout proceeds normally.
|
|
357
|
+
- 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
358
|
|
|
359
|
+
## Mock Mode
|
|
306
360
|
|
|
307
|
-
|
|
361
|
+
The SDK infers mock mode from the `publicKey` prefix:
|
|
308
362
|
|
|
309
|
-
|
|
363
|
+
| Prefix | Mode | Environment |
|
|
364
|
+
| -------- | ----- | -------------------- |
|
|
365
|
+
| `live_` | Live | Production |
|
|
366
|
+
| `test_` | Mock | Test/sandbox |
|
|
367
|
+
| `mock_` | Mock | Test/sandbox |
|
|
310
368
|
|
|
311
|
-
|
|
312
|
-
<GlomoLrsCheckout
|
|
313
|
-
devMode={true}
|
|
314
|
-
// ... other props
|
|
315
|
-
/>
|
|
316
|
-
```
|
|
317
|
-
Remember to disable this in production.
|
|
369
|
+
Mock mode keys route to the sandbox backend. No real transactions are created.
|
|
318
370
|
|
|
319
|
-
|
|
371
|
+
## Connection Handling
|
|
320
372
|
|
|
321
|
-
|
|
373
|
+
The SDK detects connection errors from the WebView and fires `onConnectionError`:
|
|
322
374
|
|
|
323
|
-
-
|
|
324
|
-
-
|
|
375
|
+
- **iOS**: NSURLErrorDomain codes (-1001 timeout, -1003 host not found, -1004 connection refused, -1009 offline)
|
|
376
|
+
- **Android**: ERR_EMPTY_RESPONSE, ERR_CONNECTION_REFUSED, ERR_NAME_NOT_RESOLVED, ERR_INTERNET_DISCONNECTED, ERR_CONNECTION_TIMED_OUT, ERR_NETWORK_CHANGED
|
|
325
377
|
|
|
326
|
-
|
|
327
|
-
```tsx
|
|
328
|
-
// Mock mode (publicKey starts with "test_")
|
|
329
|
-
<GlomoLrsCheckout
|
|
330
|
-
publicKey="test_abc123..."
|
|
331
|
-
// ... other props
|
|
332
|
-
/>
|
|
378
|
+
The checkout modal is automatically dismissed on connection errors.
|
|
333
379
|
|
|
334
|
-
|
|
335
|
-
<GlomoLrsCheckout
|
|
336
|
-
publicKey="live_xyz789..."
|
|
337
|
-
// ... other props
|
|
338
|
-
/>
|
|
339
|
-
```
|
|
380
|
+
## Input Validation
|
|
340
381
|
|
|
341
|
-
|
|
382
|
+
The SDK validates inputs before starting the checkout:
|
|
342
383
|
|
|
343
|
-
|
|
384
|
+
| Field | Rule |
|
|
385
|
+
| ---------------- | ----------------------------------------------- |
|
|
386
|
+
| `publicKey` | Must start with `live_`, `mock_`, or `test_`. Min 6 characters. |
|
|
387
|
+
| `orderId` | Must start with `order_`. Min 7 characters. Required when `subscriptionId` is absent. |
|
|
388
|
+
| `subscriptionId` | Must start with `sub_`. Trimmed and checked for emptiness. Required when `orderId` is absent. |
|
|
344
389
|
|
|
345
|
-
|
|
390
|
+
Validation failures fire `onSdkError` with `type: "validation_error"` and the relevant `field` name. `start()` returns `false`.
|
|
346
391
|
|
|
347
|
-
|
|
348
|
-
- Connection failures
|
|
349
|
-
- Internet unavailability
|
|
350
|
-
- DNS resolution failures
|
|
392
|
+
Providing both `orderId` and `subscriptionId` (or neither) also fires `onSdkError`.
|
|
351
393
|
|
|
352
|
-
|
|
394
|
+
## Migration from v2
|
|
353
395
|
|
|
354
|
-
|
|
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
|
-
```
|
|
396
|
+
v3 replaces the LRS-only `GlomoLrsCheckout` with a unified `GlomoCheckout`.
|
|
365
397
|
|
|
366
|
-
|
|
398
|
+
### Renamed Exports
|
|
367
399
|
|
|
368
|
-
|
|
400
|
+
| v2 | v3 |
|
|
401
|
+
| -------------------------- | ------------------------- |
|
|
402
|
+
| `GlomoLrsCheckout` | `GlomoCheckout` |
|
|
403
|
+
| `GlomoLrsCheckoutRef` | `GlomoCheckoutRef` |
|
|
404
|
+
| `GlomoLrsCheckoutProps` | `GlomoCheckoutProps` |
|
|
405
|
+
| `GlomoLrsCheckoutPayload` | `GlomoCheckoutPayload` |
|
|
406
|
+
| `GlomoLrsServer` | `GlomoServer` |
|
|
369
407
|
|
|
370
|
-
|
|
408
|
+
### Breaking Changes
|
|
371
409
|
|
|
372
|
-
|
|
410
|
+
- **`start()` is now async**: Returns `Promise<boolean>` instead of `boolean`. Update call sites to `await ref.current?.start()`.
|
|
411
|
+
- **New statuses**: `bank_transfer_submitted` and `pay_via_bank_completed` are new additions to `CheckoutStatus`.
|
|
412
|
+
- **New callbacks**: `onBankTransferSubmitted`, `onPayViaBankCompleted`, and `onUserRefusedCameraPermissions` are available.
|
|
373
413
|
|
|
374
|
-
|
|
375
|
-
npm install jail-monkey
|
|
376
|
-
```
|
|
414
|
+
See MIGRATION.md included in this package for a standalone migration guide with before/after code examples.
|
|
377
415
|
|
|
378
|
-
|
|
416
|
+
## Troubleshooting
|
|
379
417
|
|
|
380
|
-
|
|
381
|
-
- **Without `jail-monkey`:** The SDK skips automatic compliance checks, and allows checkout to proceed normally. Regulatory compliance would have to be enforced manually.
|
|
418
|
+
### `start()` returns `false`
|
|
382
419
|
|
|
383
|
-
|
|
420
|
+
Check `onSdkError` for details. Common causes:
|
|
421
|
+
- Invalid `publicKey` format (must start with `live_`, `mock_`, or `test_`)
|
|
422
|
+
- Invalid `orderId` format (must start with `order_`)
|
|
423
|
+
- Invalid `subscriptionId` format (must start with `sub_`, non-empty after trimming)
|
|
424
|
+
- Both `orderId` and `subscriptionId` provided (or neither)
|
|
425
|
+
- Device is rooted/jailbroken (when `jail-monkey` is installed)
|
|
384
426
|
|
|
385
|
-
|
|
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
|
|
427
|
+
### Checkout opens but shows a blank screen
|
|
390
428
|
|
|
391
|
-
|
|
392
|
-
|
|
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
|
-
```
|
|
429
|
+
- Verify network connectivity
|
|
430
|
+
- Check that the `publicKey` and `orderId` are valid
|
|
407
431
|
|
|
432
|
+
### Camera permission denied
|
|
408
433
|
|
|
409
|
-
|
|
434
|
+
- Ensure `AndroidManifest.xml` and `Info.plist` include camera permission declarations
|
|
435
|
+
- The `onUserRefusedCameraPermissions` callback will fire when the user denies
|
|
410
436
|
|
|
411
|
-
|
|
437
|
+
### `onPayViaBankCompleted` not firing
|
|
412
438
|
|
|
413
|
-
-
|
|
414
|
-
- **`orderId`**: Must start with `order_` and have a minimum length of 7 characters
|
|
439
|
+
- Ensure you are passing `onPayViaBankCompleted` as a prop to `GlomoCheckout`
|
|
415
440
|
|
|
416
|
-
|
|
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)
|
|
441
|
+
## Exports
|
|
420
442
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
443
|
+
```ts
|
|
444
|
+
// Components
|
|
445
|
+
export { GlomoCheckout } from "@glomopay/react-native-sdk";
|
|
446
|
+
|
|
447
|
+
// Hooks (deprecated - use GlomoCheckout component with ref instead)
|
|
448
|
+
export { useGlomoCheckout } from "@glomopay/react-native-sdk";
|
|
449
|
+
|
|
450
|
+
// Types
|
|
451
|
+
export type {
|
|
452
|
+
GlomoCheckoutRef,
|
|
453
|
+
GlomoCheckoutProps,
|
|
454
|
+
GlomoCheckoutPayload,
|
|
455
|
+
CheckoutStatus,
|
|
456
|
+
GlomoBankTransferPayload,
|
|
457
|
+
GlomoPayViaBankConnectionPayload,
|
|
458
|
+
UseGlomoCheckoutReturn, // deprecated
|
|
459
|
+
SdkError,
|
|
460
|
+
} from "@glomopay/react-native-sdk";
|
|
435
461
|
```
|
|
436
462
|
|
|
437
|
-
##
|
|
463
|
+
## Security
|
|
464
|
+
|
|
465
|
+
The SDK loads checkout pages in an isolated WebView. No PAN, CVV, or sensitive payment data passes through the React Native bridge - all sensitive input is handled within the WebView's sandboxed context.
|
|
466
|
+
|
|
467
|
+
Device integrity checking is available via optional `jail-monkey` integration (see [Device Security Compliance](#device-security-compliance)).
|
|
468
|
+
|
|
469
|
+
To report a security vulnerability, email security@glomopay.com. Do not open a public GitHub issue for security reports.
|
|
470
|
+
|
|
471
|
+
## Contributing
|
|
472
|
+
|
|
473
|
+
This SDK is maintained by GlomoPay. We do not accept external contributions at this time.
|
|
438
474
|
|
|
439
|
-
|
|
440
|
-
- 📖 API Documentation: https://docs.glomopay.com
|
|
441
|
-
- 🎛️ Dashboard: https://dashboard.glomopay.com
|
|
475
|
+
## Support
|
|
442
476
|
|
|
443
|
-
|
|
444
|
-
-
|
|
445
|
-
- 🎟️ GitHub Issues: https://github.com/glomopay/glomopay-rn-sdk/issues
|
|
446
|
-
- 🌐 Website: https://glomopay.com
|
|
477
|
+
- GitHub Issues: https://github.com/glomopay/glomopay-rn-sdk/issues
|
|
478
|
+
- Email: developer@glomopay.com
|
|
447
479
|
|
|
448
|
-
## License
|
|
480
|
+
## License
|
|
449
481
|
|
|
450
|
-
|
|
482
|
+
Apache-2.0. See [LICENSE](LICENSE) for details.
|