Payment Types
The Easy React Native SDK supports two types of payment instruments: Payment Cards and Bank Accounts. Each type has specific requirements and use cases.
Payment Cards
Credit and debit cards are the most common payment method.
Type Definition
type PaymentCardParams = {
type: "PAYMENT_CARD";
address?: Address;
// Separate card elements (React Native only supports this approach)
cardNumberElement: RefObject<ICardNumberElement>;
cardExpirationDateElement: RefObject<ICardExpirationDateElement>;
cardVerificationCodeElement: RefObject<ICardVerificationCodeElement>;
name?: string; // Cardholder name
};
Using Separate Card Elements
React Native requires separate elements for each card field:
import {
useEasy,
CardNumberElement,
CardExpirationDateElement,
CardVerificationCodeElement,
} from "@easylabs/react-native";
import { useRef } from "react";
import { View, Text, Button, StyleSheet } from "react-native";
function PaymentForm() {
const { checkout } = useEasy();
const cardNumberRef = useRef(null);
const expiryRef = useRef(null);
const cvcRef = useRef(null);
const handleSubmit = async () => {
await checkout({
customer_creation: true,
customer_details: {
first_name: "John",
last_name: "Doe",
email: "[email protected]",
},
source: {
type: "PAYMENT_CARD",
cardNumberElement: cardNumberRef,
cardExpirationDateElement: expiryRef,
cardVerificationCodeElement: cvcRef,
name: "John Doe",
},
line_items: [{ price_id: "price_123", quantity: 1 }],
});
};
return (
<View style={styles.container}>
<Text style={styles.label}>Card Number</Text>
<CardNumberElement btRef={cardNumberRef} style={styles.input} />
<Text style={styles.label}>Expiration Date</Text>
<CardExpirationDateElement btRef={expiryRef} style={styles.input} />
<Text style={styles.label}>CVC</Text>
<CardVerificationCodeElement btRef={cvcRef} style={styles.input} />
<Button title="Pay Now" onPress={handleSubmit} />
</View>
);
}
const styles = StyleSheet.create({
container: {
padding: 20,
},
label: {
fontSize: 16,
fontWeight: "600",
marginBottom: 8,
marginTop: 16,
},
input: {
borderWidth: 1,
borderColor: "#ccc",
borderRadius: 8,
padding: 12,
fontSize: 16,
},
});
With Billing Address
Include a billing address for additional verification:
const result = await checkout({
customer_creation: true,
customer_details: {
first_name: "John",
last_name: "Doe",
email: "[email protected]",
},
source: {
type: "PAYMENT_CARD",
cardNumberElement: cardNumberRef,
cardExpirationDateElement: expiryRef,
cardVerificationCodeElement: cvcRef,
name: "John Doe",
address: {
line1: "123 Main St",
city: "Anytown",
state: "CA",
postal_code: "12345",
country: "US",
},
},
line_items: [{ price_id: "price_123", quantity: 1 }],
});
Bank Accounts
ACH bank account payments for US customers.
Type Definition
type BankAccountParams = {
type: "BANK_ACCOUNT";
accountType: "CHECKING" | "SAVINGS";
routingElement: RefObject<ITextElement>;
accountElement: RefObject<ITextElement>;
name?: string; // Account holder name
};
Using Bank Account Elements
import { useEasy, TextElement } from "@easylabs/react-native";
import { useRef, useState } from "react";
import { View, Text, Button, StyleSheet } from "react-native";
import { Picker } from "@react-native-picker/picker";
function BankPaymentForm() {
const { checkout } = useEasy();
const routingRef = useRef(null);
const accountRef = useRef(null);
const [accountType, setAccountType] = useState("CHECKING");
const handleSubmit = async () => {
await checkout({
customer_creation: true,
customer_details: {
first_name: "Jane",
last_name: "Smith",
email: "[email protected]",
},
source: {
type: "BANK_ACCOUNT",
accountType: accountType,
routingElement: routingRef,
accountElement: accountRef,
name: "Jane Smith",
},
line_items: [{ price_id: "price_123", quantity: 1 }],
});
};
return (
<View style={styles.container}>
<Text style={styles.label}>Account Type</Text>
<Picker
selectedValue={accountType}
onValueChange={setAccountType}
style={styles.picker}
>
<Picker.Item label="Checking" value="CHECKING" />
<Picker.Item label="Savings" value="SAVINGS" />
</Picker>
<Text style={styles.label}>Routing Number</Text>
<TextElement
btRef={routingRef}
placeholder="123456789"
style={styles.input}
/>
<Text style={styles.label}>Account Number</Text>
<TextElement
btRef={accountRef}
placeholder="0123456789"
style={styles.input}
/>
<Button title="Pay with Bank Account" onPress={handleSubmit} />
</View>
);
}
const styles = StyleSheet.create({
container: {
padding: 20,
},
label: {
fontSize: 16,
fontWeight: "600",
marginBottom: 8,
marginTop: 16,
},
input: {
borderWidth: 1,
borderColor: "#ccc",
borderRadius: 8,
padding: 12,
fontSize: 16,
},
picker: {
borderWidth: 1,
borderColor: "#ccc",
borderRadius: 8,
},
});
Address Type
The address object for billing addresses:
type Address = {
line1: string; // Street address
line2?: string; // Apartment, suite, etc.
city: string;
state: string; // 2-letter state code (e.g., "CA")
postal_code: string;
country: string; // 2-letter country code (e.g., "US")
};
Example:
const billingAddress = {
line1: "123 Main Street",
line2: "Apt 4B",
city: "San Francisco",
state: "CA",
postal_code: "94102",
country: "US",
};
Choosing Payment Method Type
Use Payment Cards When:
- Customer prefers credit/debit cards
- Immediate payment processing needed
- International payments
- Rewards/points programs
- Disputed transactions need to be handled
Use Bank Accounts When:
- Lower processing fees needed
- Large transaction amounts
- Recurring ACH payments
- B2B payments
- US-only transactions
Payment Method Selection UI
Allow users to choose their preferred payment method:
import { useState } from "react";
import { View, Text, TouchableOpacity, StyleSheet } from "react-native";
function PaymentMethodSelector() {
const [method, setMethod] = useState<"CARD" | "BANK">("CARD");
return (
<View style={styles.container}>
<Text style={styles.title}>Select Payment Method</Text>
<View style={styles.options}>
<TouchableOpacity
style={[styles.option, method === "CARD" && styles.optionActive]}
onPress={() => setMethod("CARD")}
>
<Text
style={[
styles.optionText,
method === "CARD" && styles.optionTextActive,
]}
>
💳 Credit/Debit Card
</Text>
</TouchableOpacity>
<TouchableOpacity
style={[styles.option, method === "BANK" && styles.optionActive]}
onPress={() => setMethod("BANK")}
>
<Text
style={[
styles.optionText,
method === "BANK" && styles.optionTextActive,
]}
>
🏦 Bank Account
</Text>
</TouchableOpacity>
</View>
{method === "CARD" ? <CardPaymentForm /> : <BankPaymentForm />}
</View>
);
}
const styles = StyleSheet.create({
container: {
padding: 20,
},
title: {
fontSize: 20,
fontWeight: "bold",
marginBottom: 16,
},
options: {
flexDirection: "row",
gap: 12,
marginBottom: 24,
},
option: {
flex: 1,
padding: 16,
borderWidth: 2,
borderColor: "#e0e0e0",
borderRadius: 8,
alignItems: "center",
},
optionActive: {
borderColor: "#007AFF",
backgroundColor: "#E3F2FD",
},
optionText: {
fontSize: 16,
color: "#666",
},
optionTextActive: {
color: "#007AFF",
fontWeight: "600",
},
});
Validation
Validate payment details before submission:
import { Alert } from "react-native";
const validatePayment = () => {
if (!cardNumberRef.current) {
Alert.alert("Error", "Please enter your card number");
return false;
}
if (!expiryRef.current) {
Alert.alert("Error", "Please enter the expiration date");
return false;
}
if (!cvcRef.current) {
Alert.alert("Error", "Please enter the CVC");
return false;
}
return true;
};
const handleSubmit = async () => {
if (!validatePayment()) {
return;
}
await checkout({...});
};
Security Notes
Security
- Never store sensitive payment data in your app
- Always use secure elements for payment data collection
- Use the publishable API key, never the secret key
- Validate all user input on both client and server
Testing
Use test card numbers in development mode:
// Test card that will succeed
4242 4242 4242 4242
// Test card that will be declined
4000 0000 0000 0002
// Test routing number (bank)
110000000
Enable development mode:
<EasyProvider apiKey={apiKey} __dev={true}>
<App />
</EasyProvider>