@one-payments/react-native
v1.9.3
Published
React Native wrapper for One Payments web component
Downloads
486
Readme
@one-payments/react-native
React Native wrapper for One Payments web component using WebView.
Features
- ✅ Cross-platform - Works on iOS and Android
- ✅ Type-safe - Full TypeScript support
- ✅ Easy integration - Drop-in component with simple props
- ✅ Event-driven - Callbacks for payment success, errors, and state changes
- ✅ Secure - Props validation and XSS protection
- ✅ Customizable - Custom loading and error components
Installation
npm install @one-payments/react-native react-native-webview
# or
yarn add @one-payments/react-native react-native-webview
# or
pnpm add @one-payments/react-native react-native-webviewiOS Setup
After installing, run pod install:
cd ios && pod installUsage
Basic Example
import React from 'react';
import { SafeAreaView } from 'react-native';
import { OnePaymentView } from '@one-payments/react-native';
import { PaymentConfig } from '@one-payments/core';
export default function CheckoutScreen() {
// Create config using PaymentConfig class (recommended for type safety and validation)
const config = new PaymentConfig({
apiKey: 'your-api-key',
secretKey: 'your-secret-key',
environment: 'demo'
});
const handleSuccess = (data) => {
console.log('Payment succeeded!', data.paymentIntentId);
// Navigate to success screen
};
const handleError = (error) => {
console.error('Payment failed:', error.message);
// Show error message
};
return (
<SafeAreaView style={{ flex: 1 }}>
<OnePaymentView
config={config}
amount={5000}
currency="SGD"
orderId={`order-${Date.now()}`}
firstName="John"
lastName="Doe"
email="[email protected]"
onPaymentSuccess={handleSuccess}
onPaymentError={handleError}
/>
</SafeAreaView>
);
}Note: You can also pass a plain config object instead of using
PaymentConfig:config={{ apiKey: 'your-api-key', secretKey: 'your-secret-key', environment: 'demo' }}However,
PaymentConfigis recommended as it provides validation and better TypeScript support.
With Navigation
import React from 'react';
import { SafeAreaView, Alert } from 'react-native';
import { OnePaymentView } from '@one-payments/react-native';
import type { PaymentSuccessData, PaymentErrorData } from '@one-payments/react-native';
function CheckoutScreen({ navigation }) {
const handleSuccess = (data: PaymentSuccessData) => {
navigation.navigate('Success', {
paymentId: data.paymentIntentId,
amount: data.amount,
});
};
const handleError = (error: PaymentErrorData) => {
Alert.alert('Payment Failed', error.message);
};
const handleStateChange = (state) => {
console.log('Payment state:', state.status);
};
return (
<SafeAreaView style={{ flex: 1 }}>
<OnePaymentView
config={{
apiKey: process.env.ONE_PAYMENTS_API_KEY,
secretKey: process.env.ONE_PAYMENTS_SECRET_KEY,
environment: 'prod'
}}
amount={5000}
currency="SGD"
orderId={`order-${Date.now()}`}
firstName="John"
lastName="Doe"
email="[email protected]"
onPaymentSuccess={handleSuccess}
onPaymentError={handleError}
onStateChange={handleStateChange}
/>
</SafeAreaView>
);
}Custom Loading Component
import React from 'react';
import { View, ActivityIndicator, Text, StyleSheet } from 'react-native';
import { OnePaymentView } from '@one-payments/react-native';
function CheckoutScreen() {
const renderLoading = () => (
<View style={styles.loadingContainer}>
<ActivityIndicator size="large" color="#007AFF" />
<Text style={styles.loadingText}>Preparing payment...</Text>
</View>
);
return (
<OnePaymentView
config={/* ... */}
amount={5000}
currency="SGD"
orderId="order-123"
firstName="John"
lastName="Doe"
email="[email protected]"
renderLoading={renderLoading}
onPaymentSuccess={(data) => console.log('Success:', data)}
onPaymentError={(error) => console.error('Error:', error)}
/>
);
}
const styles = StyleSheet.create({
loadingContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#f5f5f5',
},
loadingText: {
marginTop: 16,
fontSize: 16,
color: '#333',
},
});API Reference
OnePaymentView Props
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| config | SDKConfig \| PaymentConfig | Yes | SDK configuration - use new PaymentConfig({...}) (recommended) or plain object |
| amount | number | Yes | Payment amount in smallest currency unit (e.g., cents for USD, SGD) |
| currency | string | Yes | ISO 4217 currency code (e.g., "USD", "EUR", "SGD") |
| orderId | string | Yes | Unique order identifier from your system |
| firstName | string | Yes | Customer's first name (required for all payments) |
| lastName | string | Yes | Customer's last name (required for all payments) |
| email | string | Yes | Customer's email address (required for all payments) |
| onPaymentSuccess | (data: PaymentSuccessData) => void | No | Callback fired when payment succeeds |
| onPaymentError | (error: PaymentErrorData) => void | No | Callback fired when payment fails |
| onStateChange | (state: PaymentStateData) => void | No | Callback fired when payment state changes |
| style | ViewStyle | No | Additional styles for container view |
| showLoadingIndicator | boolean | No | Whether to show loading indicator (default: true) |
| renderLoading | () => ReactElement | No | Custom loading component |
| renderError | (error: Error) => ReactElement | No | Custom error component |
SDKConfig
interface SDKConfig {
apiKey: string;
secretKey: string;
environment: 'dev' | 'staging' | 'prod';
}PaymentSuccessData
interface PaymentSuccessData {
paymentIntentId: string;
amount: number;
currency: string;
status: 'succeeded';
metadata?: Record<string, unknown>;
}PaymentErrorData
interface PaymentErrorData {
code: string;
message: string;
details?: Record<string, unknown>;
timestamp?: number;
}PaymentStateData
interface PaymentStateData {
status: 'idle' | 'initializing' | 'ready' | 'processing' | 'requires_action' | 'succeeded' | 'failed';
[key: string]: unknown;
}Architecture
WebView + Hybrid Adapters
This package uses a WebView to render the One Payments web component inside your React Native app. To ensure compatibility with React Native WebView environments (which don't support the Web Crypto API crypto.subtle), we use a hybrid adapter approach:
WebView Environment:
├── Crypto: @one-payments/adapters-crypto-js (crypto-js library)
├── Storage: @one-payments/adapters-web (localStorage)
├── HTTP: @one-payments/adapters-web (fetch API)
└── Timer: @one-payments/adapters-web (setTimeout/setInterval)Why Crypto-JS?
React Native WebView doesn't provide crypto.subtle, which is required for cryptographic operations like HMAC signing. To solve this, we use:
- @one-payments/adapters-crypto-js - A pure JavaScript implementation using the
crypto-jslibrary - This adapter is loaded via unpkg CDN and bundled with crypto-js (no external dependencies)
- Provides identical cryptographic operations without requiring native crypto APIs
Version History
- v1.3.0 (Current) - Fixed crypto.subtle error with dedicated crypto-js adapter
- v1.2.0 - Attempted fix using @one-payments/adapters-native (failed due to React Native dependencies)
- v1.1.2 - Fixed JSON over-escaping in payment props serialization
- v1.1.1 - Fixed ES module loading from unpkg CDN
- v1.0.x - Initial release
Supported Currencies
- USD - US Dollar
- EUR - Euro
- GBP - British Pound
- SGD - Singapore Dollar
Requirements
- React Native >= 0.70.0
- React >= 18.0.0
- react-native-webview >= 13.0.0
Troubleshooting
WebView not loading
- Ensure
react-native-webviewis installed - On iOS, run
pod installafter installing - Check console for errors
Events not firing
- Verify callback props are provided (e.g.,
onPaymentSuccess) - Check for JavaScript errors in the WebView
- Ensure WebView has JavaScript enabled (enabled by default)
Build errors
- Check Node.js version (>= 18)
- Clear node_modules and reinstall
- Verify all peer dependencies are installed
Type errors
- Ensure TypeScript version >= 5.0
- Restart TypeScript server in your IDE
- Check that
@one-payments/coreis installed
License
MIT
