@gnosispay/pse-react-native 1.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.
package/README.md ADDED
@@ -0,0 +1,262 @@
1
+ # PSE React Native
2
+
3
+ A React Native library that provides a secure WebView component for integrating Gnosis Pay card functionality into your mobile applications.
4
+
5
+ ## Features
6
+
7
+ - 🔒 **Secure WebView Integration** - Safely embed Gnosis Pay card interfaces
8
+ - 📱 **Cross-Platform** - Works on both iOS and Android
9
+ - ⚡ **Easy Integration** - Simple component with minimal setup
10
+ - 🎛️ **Configurable** - Flexible configuration options for different environments
11
+ - 📨 **Message Handling** - Built-in communication between WebView and React Native
12
+ - 🔄 **WebView Controls** - Programmatic navigation and reload capabilities
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install pse-react-native
18
+ ```
19
+
20
+ ### Peer Dependencies
21
+
22
+ Make sure you have the required peer dependencies installed:
23
+
24
+ ```bash
25
+ npm install react-native-webview
26
+ ```
27
+
28
+ For Expo projects:
29
+
30
+ ```bash
31
+ npx expo install react-native-webview
32
+ ```
33
+
34
+ ## Basic Usage
35
+
36
+ ```tsx
37
+ import React, { useRef } from "react";
38
+ import { View, Button, Alert } from "react-native";
39
+ import { PSEWebView, PSEWebViewRef } from "pse-react-native";
40
+
41
+ export default function PaymentScreen() {
42
+ const webViewRef = useRef<PSEWebViewRef>(null);
43
+
44
+ const config = {
45
+ appId: "your-app-id",
46
+ authToken: "your-auth-token",
47
+ cardToken: "your-card-token",
48
+ baseUrl: "https://pse-backend.v2.gnosispay.com", // Optional
49
+ };
50
+
51
+ const handleError = (error: string) => {
52
+ Alert.alert("Payment Error", error);
53
+ };
54
+
55
+ const handleMessage = (message: any) => {
56
+ console.log("Received message from WebView:", message);
57
+ // Handle different message types from the WebView
58
+ };
59
+
60
+ const handleLoad = () => {
61
+ console.log("WebView loaded successfully");
62
+ };
63
+
64
+ return (
65
+ <View style={{ flex: 1 }}>
66
+ <PSEWebView
67
+ ref={webViewRef}
68
+ config={config}
69
+ onError={handleError}
70
+ onMessage={handleMessage}
71
+ onLoad={handleLoad}
72
+ style={{ flex: 1 }}
73
+ testID="pse-webview"
74
+ />
75
+
76
+ <View style={{ padding: 16 }}>
77
+ <Button title="Reload" onPress={() => webViewRef.current?.reload()} />
78
+ <Button title="Go Back" onPress={() => webViewRef.current?.goBack()} />
79
+ </View>
80
+ </View>
81
+ );
82
+ }
83
+ ```
84
+
85
+ ## API Reference
86
+
87
+ ### PSEWebView Props
88
+
89
+ | Prop | Type | Required | Description |
90
+ | ----------- | ------------------------- | -------- | ------------------------------------------------ |
91
+ | `config` | `PSEConfig` | ✅ | Configuration object with authentication details |
92
+ | `onError` | `(error: string) => void` | ❌ | Callback fired when an error occurs |
93
+ | `onMessage` | `(message: any) => void` | ❌ | Callback fired when WebView sends a message |
94
+ | `onLoad` | `() => void` | ❌ | Callback fired when WebView finishes loading |
95
+ | `style` | `ViewStyle` | ❌ | Style object for the WebView container |
96
+ | `testID` | `string` | ❌ | Test identifier for testing frameworks |
97
+
98
+ ### PSEConfig
99
+
100
+ ```tsx
101
+ interface PSEConfig {
102
+ appId: string; // Your application identifier
103
+ authToken: string; // Authentication token
104
+ cardToken: string; // Card-specific token
105
+ baseUrl?: string; // Optional: Custom backend URL
106
+ }
107
+ ```
108
+
109
+ ### PSEWebViewRef Methods
110
+
111
+ The component exposes these methods via ref:
112
+
113
+ ```tsx
114
+ interface PSEWebViewRef {
115
+ goBack: () => void; // Navigate back in WebView history
116
+ reload: () => void; // Reload the current page
117
+ postMessage: (message: string) => void; // Send message to WebView
118
+ }
119
+ ```
120
+
121
+ ## Message Handling
122
+
123
+ The WebView can send various message types. Handle them in your `onMessage` callback:
124
+
125
+ ```tsx
126
+ const handleMessage = (message: any) => {
127
+ switch (message.type) {
128
+ case "error":
129
+ console.error("WebView error:", message.message);
130
+ break;
131
+ case "success":
132
+ console.log("Operation successful:", message.data);
133
+ break;
134
+ case "navigation":
135
+ console.log("Navigation event:", message.url);
136
+ break;
137
+ default:
138
+ console.log("Unknown message type:", message);
139
+ }
140
+ };
141
+ ```
142
+
143
+ ## Error Handling
144
+
145
+ The component provides comprehensive error handling:
146
+
147
+ ```tsx
148
+ const handleError = (error: string) => {
149
+ // Common error scenarios:
150
+ // - Network connectivity issues
151
+ // - Invalid authentication tokens
152
+ // - WebView loading failures
153
+ // - Backend service unavailable
154
+
155
+ console.error("PSE WebView Error:", error);
156
+
157
+ // Show user-friendly error message
158
+ Alert.alert(
159
+ "Payment Error",
160
+ "Unable to load payment interface. Please try again.",
161
+ [{ text: "OK", onPress: () => webViewRef.current?.reload() }]
162
+ );
163
+ };
164
+ ```
165
+
166
+ ## Configuration Environments
167
+
168
+ ### Production
169
+
170
+ ```tsx
171
+ const config = {
172
+ appId: "your-prod-app-id",
173
+ authToken: "your-prod-auth-token",
174
+ cardToken: "your-prod-card-token",
175
+ baseUrl: "https://pse-backend.v2.gnosispay.com",
176
+ };
177
+ ```
178
+
179
+ ### Staging/Testing
180
+
181
+ ```tsx
182
+ const config = {
183
+ appId: "your-staging-app-id",
184
+ authToken: "your-staging-auth-token",
185
+ cardToken: "your-staging-card-token",
186
+ baseUrl: "https://pse-backend-staging.v2.gnosispay.com",
187
+ };
188
+ ```
189
+
190
+ ## Requirements
191
+
192
+ - React Native >= 0.70.0
193
+ - React >= 18.0.0
194
+ - react-native-webview >= 13.0.0
195
+
196
+ ## Development
197
+
198
+ This repository includes an example app to test the library:
199
+
200
+ ### Running the Example App
201
+
202
+ 1. Clone the repository:
203
+
204
+ ```bash
205
+ git clone <repository-url>
206
+ cd pse-react-native
207
+ ```
208
+
209
+ 2. Install dependencies:
210
+
211
+ ```bash
212
+ npm install
213
+ ```
214
+
215
+ 3. Start the example app:
216
+
217
+ ```bash
218
+ npx expo start
219
+ ```
220
+
221
+ 4. Open the app in your preferred development environment:
222
+ - iOS Simulator
223
+ - Android Emulator
224
+ - Physical device with Expo Go
225
+
226
+ ### Building the Library
227
+
228
+ ```bash
229
+ npm run build
230
+ ```
231
+
232
+ This compiles the TypeScript source files and generates the distribution files in the `lib/` directory.
233
+
234
+ ## Troubleshooting
235
+
236
+ ### Common Issues
237
+
238
+ **WebView not loading:**
239
+
240
+ - Verify your authentication tokens are valid
241
+ - Check network connectivity
242
+ - Ensure the baseUrl is accessible
243
+
244
+ **Authentication errors:**
245
+
246
+ - Double-check your appId, authToken, and cardToken
247
+ - Verify tokens haven't expired
248
+ - Contact your PSE provider for token validation
249
+
250
+ **Build errors:**
251
+
252
+ - Ensure react-native-webview is properly installed
253
+ - Check that peer dependencies match the required versions
254
+ - Clear your Metro cache: `npx expo start --clear`
255
+
256
+ ## License
257
+
258
+ [Add your license information here]
259
+
260
+ ## Support
261
+
262
+ For technical support or questions about integration, please contact your PSE provider or create an issue in this repository.
@@ -0,0 +1,4 @@
1
+ import React from "react";
2
+ import type { PSEWebViewProps, PSEWebViewRef } from "./types";
3
+ declare const PSEWebView: React.ForwardRefExoticComponent<PSEWebViewProps & React.RefAttributes<PSEWebViewRef>>;
4
+ export default PSEWebView;
@@ -0,0 +1,64 @@
1
+ import React, { forwardRef, useImperativeHandle, useRef } from "react";
2
+ import { Alert, StyleSheet } from "react-native";
3
+ import { WebView } from "react-native-webview";
4
+ const PSEWebView = forwardRef(({ config, onError, onMessage, onLoad, style, testID }, ref) => {
5
+ const webViewRef = useRef(null);
6
+ useImperativeHandle(ref, () => ({
7
+ goBack: () => {
8
+ webViewRef.current?.goBack();
9
+ },
10
+ reload: () => {
11
+ webViewRef.current?.reload();
12
+ },
13
+ postMessage: (message) => {
14
+ webViewRef.current?.postMessage(message);
15
+ },
16
+ }));
17
+ const handleWebViewLoad = () => {
18
+ // Send parameters to webview after it loads
19
+ const params = {
20
+ appId: config.appId.trim(),
21
+ authToken: config.authToken.trim(),
22
+ cardToken: config.cardToken.trim(),
23
+ };
24
+ const message = JSON.stringify(params);
25
+ webViewRef.current?.postMessage(message);
26
+ console.log("PSE: Message sent to WebView:", message);
27
+ onLoad?.();
28
+ };
29
+ const handleWebViewMessage = (event) => {
30
+ try {
31
+ const data = JSON.parse(event.nativeEvent.data);
32
+ console.log("PSE: Message from WebView:", data);
33
+ // Handle error messages from the webview
34
+ if (data.type === "error") {
35
+ const errorMessage = data.message || "Unknown WebView error";
36
+ onError?.(errorMessage);
37
+ Alert.alert("PSE WebView Error", errorMessage);
38
+ }
39
+ // Pass all messages to the parent component
40
+ onMessage?.(data);
41
+ }
42
+ catch (error) {
43
+ console.log("PSE: Failed to parse WebView message:", error);
44
+ onError?.("Failed to parse WebView message");
45
+ }
46
+ };
47
+ const handleWebViewError = (syntheticEvent) => {
48
+ const { nativeEvent } = syntheticEvent;
49
+ const errorMessage = `Failed to load PSE WebView: ${nativeEvent.description}`;
50
+ console.error("PSE: WebView Error:", errorMessage);
51
+ onError?.(errorMessage);
52
+ Alert.alert("PSE WebView Error", errorMessage);
53
+ };
54
+ const baseUrl = config.baseUrl || "https://pse-backend.v2.gnosispay.com";
55
+ const webViewUrl = `${baseUrl}/native-webview`;
56
+ return (<WebView ref={webViewRef} source={{ uri: webViewUrl }} style={[styles.webview, style]} startInLoadingState={true} scalesPageToFit={true} onLoad={handleWebViewLoad} onMessage={handleWebViewMessage} onError={handleWebViewError} javaScriptEnabled={true} testID={testID}/>);
57
+ });
58
+ PSEWebView.displayName = "PSEWebView";
59
+ const styles = StyleSheet.create({
60
+ webview: {
61
+ flex: 1,
62
+ },
63
+ });
64
+ export default PSEWebView;
@@ -0,0 +1,93 @@
1
+ import React, { forwardRef, useImperativeHandle, useRef } from "react";
2
+ import { Alert, StyleSheet } from "react-native";
3
+ import { WebView } from "react-native-webview";
4
+ import type { PSEWebViewProps, PSEWebViewRef } from "./types";
5
+
6
+ const PSEWebView = forwardRef<PSEWebViewRef, PSEWebViewProps>(
7
+ ({ config, onError, onMessage, onLoad, style, testID }, ref) => {
8
+ const webViewRef = useRef<WebView>(null);
9
+
10
+ useImperativeHandle(ref, () => ({
11
+ goBack: () => {
12
+ webViewRef.current?.goBack();
13
+ },
14
+ reload: () => {
15
+ webViewRef.current?.reload();
16
+ },
17
+ postMessage: (message: string) => {
18
+ webViewRef.current?.postMessage(message);
19
+ },
20
+ }));
21
+
22
+ const handleWebViewLoad = () => {
23
+ // Send parameters to webview after it loads
24
+ const params = {
25
+ appId: config.appId.trim(),
26
+ authToken: config.authToken.trim(),
27
+ cardToken: config.cardToken.trim(),
28
+ };
29
+
30
+ const message = JSON.stringify(params);
31
+ webViewRef.current?.postMessage(message);
32
+
33
+ console.log("PSE: Message sent to WebView:", message);
34
+ onLoad?.();
35
+ };
36
+
37
+ const handleWebViewMessage = (event: any) => {
38
+ try {
39
+ const data = JSON.parse(event.nativeEvent.data);
40
+ console.log("PSE: Message from WebView:", data);
41
+
42
+ // Handle error messages from the webview
43
+ if (data.type === "error") {
44
+ const errorMessage = data.message || "Unknown WebView error";
45
+ onError?.(errorMessage);
46
+ Alert.alert("PSE WebView Error", errorMessage);
47
+ }
48
+
49
+ // Pass all messages to the parent component
50
+ onMessage?.(data);
51
+ } catch (error) {
52
+ console.log("PSE: Failed to parse WebView message:", error);
53
+ onError?.("Failed to parse WebView message");
54
+ }
55
+ };
56
+
57
+ const handleWebViewError = (syntheticEvent: any) => {
58
+ const { nativeEvent } = syntheticEvent;
59
+ const errorMessage = `Failed to load PSE WebView: ${nativeEvent.description}`;
60
+ console.error("PSE: WebView Error:", errorMessage);
61
+ onError?.(errorMessage);
62
+ Alert.alert("PSE WebView Error", errorMessage);
63
+ };
64
+
65
+ const baseUrl = config.baseUrl || "https://pse-backend.v2.gnosispay.com";
66
+ const webViewUrl = `${baseUrl}/native-webview`;
67
+
68
+ return (
69
+ <WebView
70
+ ref={webViewRef}
71
+ source={{ uri: webViewUrl }}
72
+ style={[styles.webview, style]}
73
+ startInLoadingState={true}
74
+ scalesPageToFit={true}
75
+ onLoad={handleWebViewLoad}
76
+ onMessage={handleWebViewMessage}
77
+ onError={handleWebViewError}
78
+ javaScriptEnabled={true}
79
+ testID={testID}
80
+ />
81
+ );
82
+ }
83
+ );
84
+
85
+ PSEWebView.displayName = "PSEWebView";
86
+
87
+ const styles = StyleSheet.create({
88
+ webview: {
89
+ flex: 1,
90
+ },
91
+ });
92
+
93
+ export default PSEWebView;
package/lib/index.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export { default as PSEWebView } from "./PSEWebView";
2
+ export type { PSEConfig, PSEWebViewProps, PSEWebViewRef } from "./types";
package/lib/index.js ADDED
@@ -0,0 +1 @@
1
+ export { default as PSEWebView } from "./PSEWebView";
package/lib/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export { default as PSEWebView } from "./PSEWebView";
2
+ export type { PSEConfig, PSEWebViewProps, PSEWebViewRef } from "./types";
package/lib/types.d.ts ADDED
@@ -0,0 +1,19 @@
1
+ export interface PSEConfig {
2
+ appId: string;
3
+ authToken: string;
4
+ cardToken: string;
5
+ baseUrl?: string;
6
+ }
7
+ export interface PSEWebViewProps {
8
+ config: PSEConfig;
9
+ onError?: (error: string) => void;
10
+ onMessage?: (message: any) => void;
11
+ onLoad?: () => void;
12
+ style?: any;
13
+ testID?: string;
14
+ }
15
+ export interface PSEWebViewRef {
16
+ goBack: () => void;
17
+ reload: () => void;
18
+ postMessage: (message: string) => void;
19
+ }
package/lib/types.js ADDED
File without changes
package/lib/types.ts ADDED
@@ -0,0 +1,21 @@
1
+ export interface PSEConfig {
2
+ appId: string;
3
+ authToken: string;
4
+ cardToken: string;
5
+ baseUrl?: string;
6
+ }
7
+
8
+ export interface PSEWebViewProps {
9
+ config: PSEConfig;
10
+ onError?: (error: string) => void;
11
+ onMessage?: (message: any) => void;
12
+ onLoad?: () => void;
13
+ style?: any;
14
+ testID?: string;
15
+ }
16
+
17
+ export interface PSEWebViewRef {
18
+ goBack: () => void;
19
+ reload: () => void;
20
+ postMessage: (message: string) => void;
21
+ }
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "@gnosispay/pse-react-native",
3
+ "main": "lib/index.js",
4
+ "version": "1.0.1",
5
+ "types": "lib/index.d.ts",
6
+ "files": [
7
+ "lib/",
8
+ "README.md"
9
+ ],
10
+ "scripts": {
11
+ "start": "expo start",
12
+ "android": "expo start --android",
13
+ "ios": "expo start --ios",
14
+ "web": "expo start --web",
15
+ "lint": "expo lint",
16
+ "build": "tsc --project tsconfig.lib.json",
17
+ "prepublishOnly": "npm run build"
18
+ },
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "https://github.com/gnosispay/pse-react-native"
22
+ },
23
+ "keywords": [
24
+ "react-native",
25
+ "pse",
26
+ "gnosis-pay",
27
+ "webview",
28
+ "payment",
29
+ "card",
30
+ "iframe"
31
+ ],
32
+ "peerDependencies": {
33
+ "react": ">=18.0.0",
34
+ "react-native": ">=0.70.0",
35
+ "react-native-webview": ">=13.0.0"
36
+ },
37
+ "dependencies": {
38
+ "@expo/vector-icons": "^14.1.0",
39
+ "@react-navigation/bottom-tabs": "^7.3.10",
40
+ "@react-navigation/elements": "^2.3.8",
41
+ "@react-navigation/native": "^7.1.6",
42
+ "expo": "~53.0.20",
43
+ "expo-blur": "~14.1.5",
44
+ "expo-constants": "~17.1.7",
45
+ "expo-font": "~13.3.2",
46
+ "expo-haptics": "~14.1.4",
47
+ "expo-image": "~2.4.0",
48
+ "expo-linking": "~7.1.7",
49
+ "expo-router": "~5.1.4",
50
+ "expo-splash-screen": "~0.30.10",
51
+ "expo-status-bar": "~2.2.3",
52
+ "expo-symbols": "~0.4.5",
53
+ "expo-system-ui": "~5.0.10",
54
+ "expo-web-browser": "~14.2.0",
55
+ "react": "19.0.0",
56
+ "react-dom": "19.0.0",
57
+ "react-native": "0.79.5",
58
+ "react-native-gesture-handler": "~2.24.0",
59
+ "react-native-reanimated": "~3.17.4",
60
+ "react-native-safe-area-context": "5.4.0",
61
+ "react-native-screens": "~4.11.1",
62
+ "react-native-web": "~0.20.0",
63
+ "react-native-webview": "13.13.5"
64
+ },
65
+ "devDependencies": {
66
+ "@babel/core": "^7.25.2",
67
+ "@types/react": "~19.0.10",
68
+ "typescript": "~5.8.3",
69
+ "eslint": "^9.25.0",
70
+ "eslint-config-expo": "~9.2.0"
71
+ }
72
+ }