How to Wire Stripe Payment Sheet in React Native

Step-by-step: Stripe Payment Sheet in React Native + Expo, with the NestJS PaymentIntent endpoint and the Apple review rules that decide where Stripe is allowed.

Learn/How to Wire Stripe Payment Sheet in React Native
intermediate4 hours

How to Wire Stripe Payment Sheet in React Native

Stripe Payment Sheet in React Native with the NestJS PaymentIntent endpoint, webhook, and the Apple review rules I follow on every shipped app.

Prerequisites

Expo projectStripe accountNestJS backend

What you ship at the end

A React Native checkout that opens the native Stripe Payment Sheet, processes a one-time payment for a physical good or service, writes the order to Supabase, and confirms via webhook. Roughly 4 hours the first time.

Prerequisites

  • Expo project (or bare RN) with a backend you control.
  • Stripe account with test keys.
  • NestJS (or any) backend you can add an endpoint to. Do not call Stripe directly from mobile.

Step 1: Backend PaymentIntent endpoint

Add a POST endpoint that takes amount and currency, creates a PaymentIntent with automatic_payment_methods: { enabled: true }, and returns the client secret.

@Post(''payments/intent'')
async createIntent(@Body() body: { amount: number; currency: string }) {
  const pi = await stripe.paymentIntents.create({
    amount: body.amount,
    currency: body.currency,
    automatic_payment_methods: { enabled: true },
  });
  return { clientSecret: pi.client_secret };
}

Return only the client_secret, never the full PaymentIntent.

Step 2: Install and wrap with StripeProvider

Install @stripe/stripe-react-native. Wrap your app root:

<StripeProvider publishableKey={process.env.EXPO_PUBLIC_STRIPE_PUBLISHABLE_KEY!}>
  <App />
</StripeProvider>

Step 3: Checkout button

On tap: fetch the client secret from your backend, call initPaymentSheet, then presentPaymentSheet.

const { initPaymentSheet, presentPaymentSheet } = useStripe();

async function onCheckout() {
  const res = await fetch(`${API_URL}/payments/intent`, {
    method: ''POST'',
    body: JSON.stringify({ amount: 4900, currency: ''usd'' }),
  });
  const { clientSecret } = await res.json();

  await initPaymentSheet({
    paymentIntentClientSecret: clientSecret,
    merchantDisplayName: ''AI App Factory'',
  });
  const { error } = await presentPaymentSheet();
  if (error) return alert(error.message);
}

Step 4: Webhook + order write

Your backend webhook handler listens for payment_intent.succeeded and writes the order row to Supabase. Do not trust the mobile client to confirm payment.

Apple review rule I always cite to myself

Stripe for physical goods and real-world services is fine. Stripe for digital unlocks is a rejection. When in doubt, ask: would this goods still exist if my backend was turned off? If no, it is digital, and Apple wants IAP.

What the boilerplate gives you

AI App Factory ships the NestJS payments endpoint, the webhook handler, the Supabase order schema, and the React Native checkout screen — all wired, all tested, all ready to customize.

See pricing

Or let AI App Factory handle this for you.

Everything in this guide is already pre-configured in AI App Factory. 11 AI agents automate the rest.

AI App FactoryLearnHow to Wire Stripe Payment Sheet in React Native