React Native
Seamless OZZOBiT integration for React Native applications
Integrate OZZOBiT into your React Native application using WebView. This guide covers both Expo and bare React Native projects.
Installation
Install WebView Dependency
bashbash
npx expo install react-native-webviewbashbash
npm install react-native-webview
# For React Native < 0.60:
cd ios && pod install && cd ..Implementation
Create OZZOBiT Component
OZZOBiTWidget.tsxtsx
// components/OZZOBiTWidget.tsx
import React, { useRef, useCallback } from 'react'
import {
View,
StyleSheet,
Platform,
BackHandler,
NativeEventEmitter,
NativeModules,
DeviceEventEmitter,
} from 'react-native'
import { WebView, WebViewNavigation } from 'react-native-webview'
interface OZZOBiTConfig {
apiKey: string
environment?: 'STAGING' | 'PRODUCTION'
productsAvailed?: string
network?: string
defaultCryptoCurrency?: string
defaultFiatCurrency?: string
walletAddress?: string
fiatAmount?: number
cryptoAmount?: number
email?: string
themeColor?: string
redirectURL?: string
}
interface OZZOBiTProps {
config: OZZOBiTConfig
onSuccess?: (data: any) => void
onFailure?: (data: any) => void
onClose?: () => void
}
const OZZOBiTWidget: React.FC<OZZOBiTProps> = ({
config,
onSuccess,
onFailure,
onClose,
}) => {
const webViewRef = useRef<WebView>(null)
const buildUrl = useCallback(() => {
const params = new URLSearchParams({
apiKey: config.apiKey,
environment: config.environment || 'PRODUCTION',
productsAvailed: config.productsAvailed || 'BUY',
network: config.network || 'ethereum',
defaultCryptoCurrency: config.defaultCryptoCurrency || 'ETH',
defaultFiatCurrency: config.defaultFiatCurrency || 'USD',
themeColor: config.themeColor || '#1461db',
})
if (config.walletAddress) params.set('walletAddress', config.walletAddress)
if (config.fiatAmount) params.set('fiatAmount', String(config.fiatAmount))
if (config.cryptoAmount) params.set('cryptoAmount', String(config.cryptoAmount))
if (config.email) params.set('email', config.email)
if (config.redirectURL) params.set('redirectURL', config.redirectURL)
return `https://OZZOBiT.com/global?${params.toString()}`
}, [config])
const handleNavigationStateChange = useCallback(
(navState: WebViewNavigation) => {
const url = navState.url
// Handle callback URLs
if (url?.includes('callback') || url?.includes('status=')) {
try {
const urlObj = new URL(url)
const status = urlObj.searchParams.get('status')
const orderId = urlObj.searchParams.get('orderId')
switch (status) {
case 'SUCCESS':
onSuccess?.({ orderId, status })
break
case 'FAILURE':
onFailure?.({ orderId, status })
break
}
} catch (e) {
console.error('Error parsing callback URL:', e)
}
}
},
[onSuccess, onFailure]
)
// Handle Android back button to navigate within WebView
useEffect(() => {
const backHandler = BackHandler.addEventListener(
'hardwareBackPress',
() => {
if (webViewRef.current?.canGoBack()) {
webViewRef.current.goBack()
return true
}
onClose?.()
return false
}
)
return () => backHandler.remove()
}, [onClose])
// Inject JavaScript for event handling
const injectedJavaScript = `
window.ReactNativeWebView = window.ReactNativeWebView || {};
// Listen for postMessage events from OZZOBiT
window.addEventListener('message', function(event) {
if (event.data && event.data.eventName) {
window.ReactNativeWebView.postMessage(JSON.stringify(event.data));
}
});
// Override postMessage for compatibility
const originalPostMessage = window.postMessage;
window.postMessage = function(data) {
if (data && data.eventName) {
window.ReactNativeWebView.postMessage(JSON.stringify(data));
}
originalPostMessage.apply(this, arguments);
};
true; // Required for injected JS
`
const handleMessage = useCallback((event: any) => {
try {
const data = JSON.parse(event.nativeEvent.data)
switch (data.eventName) {
case 'ORDER_SUCCESSFUL':
onSuccess?.(data)
break
case 'ORDER_FAILED':
onFailure?.(data)
break
case 'CLOSE_WIDGET':
onClose?.()
break
default:
console.log('[OZZOBiT Event]', data.eventName, data)
}
} catch (e) {
console.error('Error parsing message:', e)
}
}, [onSuccess, onFailure, onClose])
return (
<View style={styles.container}>
<WebView
ref={webViewRef}
source={{ uri: buildUrl() }}
style={styles.webview}
originWhelist={['*']}
onNavigationStateChange={handleNavigationStateChange}
onMessage={handleMessage}
injectedJavaScriptBeforeContentLoaded={injectedJavaScript}
javaScriptEnabled={true}
domStorageEnabled={true}
allowsInlineMediaPlayback={true}
startInLoadingState={true}
renderLoading={() => (
<View style={styles.loadingContainer}>
{/* Add your loading indicator here */}
</View>
)}
{...(Platform.OS === 'android' ? {
mixedContentMode: 'always_allow',
} : {})}
/>
</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
webview: {
flex: 1,
},
loadingContainer: {
...StyleSheet.absoluteFillObject,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#fff',
},
})
export default OZZOBiTWidgetUse in Your App
BuyCryptoScreen.tsxtsx
// screens/BuyCryptoScreen.tsx
import React, { useState } from 'react'
import { View, Button, Alert, Modal } from 'react-native'
import OZZOBiTWidget from '../components/OZZOBiTWidget'
export default function BuyCryptoScreen() {
const [showWidget, setShowWidget] = useState(false)
return (
<View style={{ flex: 1, justifyContent: 'center', padding: 20 }}>
<Button
title="Buy Crypto with OZZOBiT"
onPress={() => setShowWidget(true)}
/>
<Modal visible={showWidget} animationType="slide">
<OZZOBiTWidget
config={{
apiKey: process.env.EXPO_PUBLIC_OZZOBiT_API_KEY!,
environment: __DEV__ ? 'STAGING' : 'PRODUCTION',
productsAvailed: 'BUY',
network: 'ethereum',
defaultCryptoCurrency: 'ETH',
walletAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f8bD21',
}}
onSuccess={(data) => {
Alert.alert('Success!', `Order ID: ${data.orderId}`)
setShowWidget(false)
}}
onFailure={(data) => {
Alert.alert('Failed', `Order failed. ID: ${data.orderId}`)
setShowWidget(false)
}}
onClose={() => setShowWidget(false)}
/>
</Modal>
</View>
)
}Platform-Specific Notes
- iOS: Ensure you've added
NSAppTransportSecurityexceptions in Info.plist for OZZOBiT domains - Android: Set
usesCleartextTrafficonly if needed during development; use HTTPS in production - Expo: Use
npx expo install react-native-webviewinstead of npm for better compatibility - The
originWhitelist=*is needed for postMessage communication