import React, { useState } from 'react'; import { SafeAreaView, ScrollView, StatusBar, StyleSheet, Text, View, TouchableOpacity, Alert, ActivityIndicator, Platform, } from 'react-native'; import BraintreeDropIn, { type PaymentResult, type DropInOptions, } from 'react-native-braintree-dropin-turbo'; // IMPORTANT: Replace with your actual Braintree client token from your server const BRAINTREE_CLIENT_TOKEN = 'sandbox_g42y39zw_348pk9cgf3bgyw2b'; const App = () => { const [paymentResult, setPaymentResult] = useState(null); const [loading, setLoading] = useState(false); const [deviceData, setDeviceData] = useState(''); const showAlert = (title: string, message: string) => { Alert.alert(title, message); }; // Test 1: Basic Drop-In UI with all payment methods const handleBasicDropIn = async () => { setLoading(true); try { const options: DropInOptions = { clientToken: BRAINTREE_CLIENT_TOKEN, orderTotal: 29.99, currencyCode: 'USD', venmo: true, payPal: true, }; const result = await BraintreeDropIn.show(options); setPaymentResult(result); showAlert('Success!', `Payment nonce received: ${result.nonce.substring(0, 20)}...`); console.log('Payment Result:', result); } catch (error: any) { if (error.message === 'USER_CANCELLATION') { console.log('User cancelled payment'); } else { showAlert('Error', error.message); console.error('Payment Error:', error); } } finally { setLoading(false); } }; // Test 2: Apple Pay (iOS only) const handleApplePay = async () => { if (Platform.OS !== 'ios') { showAlert('iOS Only', 'Apple Pay is only available on iOS devices'); return; } setLoading(true); try { const options: DropInOptions = { clientToken: BRAINTREE_CLIENT_TOKEN, orderTotal: 49.99, currencyCode: 'USD', countryCode: 'US', applePay: true, merchantIdentifier: 'merchant.com.yourcompany.app', // Replace with your merchant ID merchantName: 'Your Store Name', venmo: true, payPal: true, }; const result = await BraintreeDropIn.show(options); setPaymentResult(result); showAlert('Success!', `Apple Pay payment received!`); console.log('Apple Pay Result:', result); } catch (error: any) { if (error.message === 'USER_CANCELLATION') { console.log('User cancelled Apple Pay'); } else { showAlert('Error', error.message); console.error('Apple Pay Error:', error); } } finally { setLoading(false); } }; // Test 3: Google Pay (Android only) const handleGooglePay = async () => { if (Platform.OS !== 'android') { showAlert('Android Only', 'Google Pay is only available on Android devices'); return; } setLoading(true); try { const options: DropInOptions = { clientToken: BRAINTREE_CLIENT_TOKEN, orderTotal: 39.99, currencyCode: 'USD', googlePay: true, googlePayMerchantId: 'BCR2DN4T6Z3WWIJJ', // Replace with your Google merchant ID venmo: true, payPal: true, }; const result = await BraintreeDropIn.show(options); setPaymentResult(result); showAlert('Success!', `Google Pay payment received!`); console.log('Google Pay Result:', result); } catch (error: any) { if (error.message === 'USER_CANCELLATION') { console.log('User cancelled Google Pay'); } else { showAlert('Error', error.message); console.error('Google Pay Error:', error); } } finally { setLoading(false); } }; // Test 4: 3D Secure const handle3DSecure = async () => { setLoading(true); try { const options: DropInOptions = { clientToken: BRAINTREE_CLIENT_TOKEN, orderTotal: 100.00, currencyCode: 'USD', threeDSecure: { amount: 100.00, }, venmo: true, payPal: true, }; const result = await BraintreeDropIn.show(options); setPaymentResult(result); showAlert('Success!', '3D Secure verification completed!'); console.log('3D Secure Result:', result); } catch (error: any) { if (error.message === 'USER_CANCELLATION') { console.log('User cancelled 3D Secure'); } else if (error.message.includes('3DSECURE')) { showAlert('3D Secure Failed', error.message); } else { showAlert('Error', error.message); } console.error('3D Secure Error:', error); } finally { setLoading(false); } }; // Test 5: Tokenize Card Directly const handleTokenizeCard = async () => { setLoading(true); try { // Test card number - DO NOT use in production const result = await BraintreeDropIn.tokenizeCard( BRAINTREE_CLIENT_TOKEN, { number: '4111111111111111', expirationMonth: '12', expirationYear: '2025', cvv: '123', postalCode: '12345', } ); setPaymentResult(result); showAlert('Success!', 'Card tokenized successfully!'); console.log('Tokenized Card Result:', result); } catch (error: any) { showAlert('Error', error.message); console.error('Tokenization Error:', error); } finally { setLoading(false); } }; // Test 6: Collect Device Data const handleCollectDeviceData = async () => { setLoading(true); try { const data = await BraintreeDropIn.collectDeviceData(BRAINTREE_CLIENT_TOKEN); setDeviceData(data); showAlert('Device Data Collected', `Length: ${data.length} characters`); console.log('Device Data:', data.substring(0, 100) + '...'); } catch (error: any) { showAlert('Error', error.message); console.error('Device Data Error:', error); } finally { setLoading(false); } }; // Test 7: Fetch Most Recent Payment Method const handleFetchLastPayment = async () => { setLoading(true); try { const result = await BraintreeDropIn.fetchMostRecentPaymentMethod( BRAINTREE_CLIENT_TOKEN ); if (result) { setPaymentResult(result); showAlert('Last Payment Method', result.description); console.log('Last Payment:', result); } else { showAlert('No Payment Found', 'No previous payment method available'); } } catch (error: any) { showAlert('Error', error.message); console.error('Fetch Payment Error:', error); } finally { setLoading(false); } }; // Test 8: Vault Manager const handleVaultManager = async () => { setLoading(true); try { const options: DropInOptions = { clientToken: BRAINTREE_CLIENT_TOKEN, vaultManager: true, orderTotal: 25.00, currencyCode: 'USD', }; const result = await BraintreeDropIn.show(options); setPaymentResult(result); showAlert('Success!', 'Payment method saved to vault!'); console.log('Vault Manager Result:', result); } catch (error: any) { if (error.message === 'USER_CANCELLATION') { console.log('User cancelled vault manager'); } else { showAlert('Error', error.message); } } finally { setLoading(false); } }; // Test 9: Dark Theme (iOS) const handleDarkTheme = async () => { if (Platform.OS !== 'ios') { showAlert('iOS Only', 'Dark theme is only available on iOS'); return; } setLoading(true); try { const options: DropInOptions = { clientToken: BRAINTREE_CLIENT_TOKEN, darkTheme: true, orderTotal: 19.99, currencyCode: 'USD', }; const result = await BraintreeDropIn.show(options); setPaymentResult(result); showAlert('Success!', 'Payment processed with dark theme!'); console.log('Dark Theme Result:', result); } catch (error: any) { if (error.message === 'USER_CANCELLATION') { console.log('User cancelled dark theme'); } else { showAlert('Error', error.message); } } finally { setLoading(false); } }; const TestButton = ({ title, onPress, color = '#007AFF' }: any) => ( {title} ); return ( Braintree Drop-In React Native Turbo Module Example {loading && ( Processing... )} Basic Tests Platform-Specific Advanced Features {paymentResult && ( Last Payment Result: Type: {paymentResult.type} Description: {paymentResult.description} Nonce: {paymentResult.nonce.substring(0, 30)}... Is Default: {paymentResult.isDefault ? 'Yes' : 'No'} Device Data: {paymentResult.deviceData.substring(0, 30)}... )} {deviceData && ( Device Data: {deviceData} )} Platform: {Platform.OS === 'ios' ? 'iOS' : 'Android'} ⚠️ Remember to replace BRAINTREE_CLIENT_TOKEN with your actual token ); }; const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#F2F2F7', }, scrollContent: { padding: 16, }, header: { alignItems: 'center', marginVertical: 20, }, title: { fontSize: 28, fontWeight: 'bold', color: '#000', marginBottom: 8, }, subtitle: { fontSize: 16, color: '#666', }, loadingContainer: { padding: 20, alignItems: 'center', backgroundColor: '#FFF', borderRadius: 12, marginVertical: 10, }, loadingText: { marginTop: 10, fontSize: 16, color: '#666', }, section: { marginVertical: 10, }, sectionTitle: { fontSize: 20, fontWeight: '600', color: '#000', marginBottom: 12, marginLeft: 4, }, button: { backgroundColor: '#007AFF', paddingVertical: 16, paddingHorizontal: 20, borderRadius: 12, marginVertical: 6, alignItems: 'center', shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.1, shadowRadius: 4, elevation: 3, }, buttonText: { color: '#FFF', fontSize: 16, fontWeight: '600', }, resultContainer: { backgroundColor: '#FFF', padding: 16, borderRadius: 12, marginTop: 20, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.1, shadowRadius: 4, elevation: 2, }, resultTitle: { fontSize: 18, fontWeight: 'bold', color: '#000', marginBottom: 12, }, resultRow: { flexDirection: 'row', paddingVertical: 8, borderBottomWidth: 1, borderBottomColor: '#F2F2F7', }, resultLabel: { fontSize: 14, fontWeight: '600', color: '#666', width: 110, }, resultValue: { fontSize: 14, color: '#000', flex: 1, }, deviceDataContainer: { backgroundColor: '#FFF', padding: 16, borderRadius: 12, marginTop: 10, }, deviceDataText: { fontSize: 12, color: '#666', fontFamily: Platform.OS === 'ios' ? 'Menlo' : 'monospace', }, footer: { marginTop: 30, marginBottom: 20, alignItems: 'center', }, footerText: { fontSize: 12, color: '#999', textAlign: 'center', marginVertical: 4, }, }); export default App;