React NativeExamples · Props · Code

Stripe in React Native

The cleanest way to take payments in React Native is Stripe’s Payment Sheet from @stripe/stripe-react-native. It needs one small backend endpoint (to create the PaymentIntent) — you can never do that safely on the device. Here’s both halves.

How it works

Payments are two-sided: your server creates a PaymentIntent with the secret key and returns a clientSecret; your app uses the publishable key to present the native sheet with that secret. Never put the secret key in the app.

1. Backend — create the PaymentIntent

// Your server (Node) — never create PaymentIntents on the device.
import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);

// POST /payment-sheet
export async function createPaymentSheet(amount) {
  const paymentIntent = await stripe.paymentIntents.create({
    amount,             // in the smallest unit, e.g. 1999 = $19.99
    currency: 'usd',
  });
  return { clientSecret: paymentIntent.client_secret };
}

2. App — present the Payment Sheet

Wrap the app in StripeProvider once, then init and present the sheet from the checkout button:

// npx expo install @stripe/stripe-react-native
import { StripeProvider, useStripe } from '@stripe/stripe-react-native';
import { Button, Alert } from 'react-native';

function CheckoutButton() {
  const { initPaymentSheet, presentPaymentSheet } = useStripe();

  async function pay() {
    // 1. get a clientSecret from YOUR backend
    const res = await fetch('https://your-api.com/payment-sheet', { method: 'POST' });
    const { clientSecret } = await res.json();

    // 2. init + present the native sheet
    await initPaymentSheet({ merchantDisplayName: 'My App', paymentIntentClientSecret: clientSecret });
    const { error } = await presentPaymentSheet();

    Alert.alert(error ? 'Payment failed' : 'Success', error?.message ?? 'Thanks!');
  }

  return <Button title="Pay $19.99" onPress={pay} />;
}

// Wrap your app once, near the root:
export function Root({ children }) {
  return <StripeProvider publishableKey="pk_test_...">{children}</StripeProvider>;
}

Key APIs

PropTypeDefaultDescription
StripeProvidercomponentWrap the app; takes your publishable key.
initPaymentSheetfnConfigure the sheet with the clientSecret.
presentPaymentSheetfnShow the native sheet; resolves with { error } or success.
merchantDisplayNamestringShown to the user in the sheet.
amountnumberSet on the SERVER, in the smallest currency unit (cents).

Gotchas

  • Never create PaymentIntents or use the secret key on the device. That endpoint must live on your server.
  • amount is in the smallest unit — 1999 means $19.99, not $1,999.
  • Payment Sheet doesn’t run in the web preview or Expo Go for real charges — test on a device with a dev build. Use Stripe test cards (4242 4242 4242 4242).
  • Apple Pay / Google Pay need extra config (merchant ID, entitlements). Card payments work with just the keys.

FAQ

How do I add Stripe to a React Native app? Install @stripe/stripe-react-native, wrap the app in StripeProvider, and present the Payment Sheet with a clientSecret from your backend.

Do I need a backend for Stripe? Yes — a small endpoint to create the PaymentIntent. The secret key can never live in the app.

Related components

Skip the boilerplate

Describe your screen in ShipNative and it wires up the component for you — in a real, exportable React Native app.

Generate it with AI →