import React, { Fragment, useRef, useState } from 'react'; import { StyleSheet, View, Platform, ActivityIndicator, Text, Linking, } from 'react-native'; import { WebView, type WebViewMessageEvent } from 'react-native-webview'; import { clientSdkBaseUrl, serverSdkBaseUrl } from '../lib/config'; import { getContact } from '../functions'; import { Registration } from './views/Registration'; import { BvnVerification } from './views/BvnVerification'; import { PaylaterAgreement } from './views/PaylaterAgreement'; import { PaymentLinking } from './views/PaymentLinking'; import { FaceVerification } from './views/FaceVerification'; type OmnipayProps = { color: string; env: 'dev' | 'prod'; publicKey: string; phoneNumber: string; view: 'bills' | 'registration'; onEnterFullScreen?: () => void; onExitFullScreen?: () => void; }; type PostMessage = { [key: string]: unknown; }; type Status = 'error' | 'loading' | 'success'; const Omnipay = ({ color, env, publicKey, phoneNumber, view, onEnterFullScreen, onExitFullScreen, }: OmnipayProps): JSX.Element => { const webviewRef = useRef(null); const [webviewStatus, setWebviewStatus] = useState('loading'); const webHost = getWebHost(); const webUrl = getWebUrl(); const onWebviewMount = ` window.nativeOs = ${Platform.OS}; true; `; function getWebHost() { /** * use client rendered app url for bills sdk, * else use server rendered app url */ if (view === 'bills') { return clientSdkBaseUrl[env]; } return serverSdkBaseUrl[env]; } function getWebUrl() { const themeColor = color.includes('#') ? color.split('#')[1] : color; if (view === 'bills') { return `${webHost}?theme=${themeColor}&view=${view}&publicKey=${publicKey}&phoneNumber=${phoneNumber}`; } return `${webHost}auth/register?theme=${themeColor}&publicKey=${publicKey}&phoneNumber=${phoneNumber}`; } function postMessage(data: PostMessage) { if (!webviewRef.current) { return; } try { webviewRef.current.postMessage(JSON.stringify(data)); } catch (error) {} } async function onWebviewMessage(e: WebViewMessageEvent) { try { if (e.nativeEvent && e.nativeEvent.data) { const eventData = JSON.parse(e.nativeEvent.data); const { dataKey, dataValue } = eventData; if (dataKey === 'chooseContact') { const contactDetails = await getContact(); postMessage({ dataKey: 'contactSelected', dataValue: contactDetails, }); } if (dataKey === 'modalOpen') { if (onEnterFullScreen) { onEnterFullScreen(); } } if (dataKey === 'modalClosed') { if (onExitFullScreen) { onExitFullScreen(); } } if (dataKey === 'openLink') { Linking.openURL(dataValue); } } } catch (error) {} } if (view !== 'bills' && view !== 'registration') { return Invalid view; } if (!publicKey.includes('OMNIPUBKEY_')) { return Invalid public key; } if (phoneNumber.length < 10) { return Invalid phone number; } if (color.length < 3) { return Invalid color; } if (!['dev', 'prod'].includes(env)) { return Invalid environment; } return ( setWebviewStatus('success')} /> {webviewStatus === 'loading' && ( )} ); }; const styles = StyleSheet.create({ hide: { display: 'none', }, full: { flex: 1, width: '100%', height: '100%', }, webview: { flex: 1, width: '100%', height: '100%', }, webviewLoader: { zIndex: 3, backgroundColor: 'white', alignItems: 'center', justifyContent: 'center', flex: 1, width: '100%', height: '100%', position: 'absolute', top: 0, left: 0, }, }); Omnipay.Registration = Registration; Omnipay.BvnVerification = BvnVerification; Omnipay.PaylaterAgreement = PaylaterAgreement; Omnipay.PaymentLinking = PaymentLinking; Omnipay.FaceVerification = FaceVerification; export default Omnipay;