Skip to main content

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>

Next Steps