Set Up Stripe Payments

Wire Stripe into a React Native app and backend using PaymentIntents, with prices validated server-side and secrets kept off the device.

This guide covers wiring Stripe into a React Native app with a backend, using the PaymentIntent flow.

Quick Answer

Put your Stripe publishable key in the app and your secret key only on the server; have the server create a PaymentIntent for a server-computed amount; confirm it in the app with @stripe/stripe-react-native's PaymentSheet; and never trust a price sent from the client.

1. Keys: What Goes Where

  • The publishable key (pk_...) is safe in the app; it can only create tokens, not move money on its own.
  • The secret key (sk_...) must live only in server environment variables. If it ends up in the app bundle, anyone can extract it and create arbitrary charges against your account.

2. Compute the Amount Server-Side

The server, not the client, must look up the price of whatever is being purchased and compute the final amount. Never accept a raw price/amount field from the app; a modified client could send any number it wants.

3. Create a PaymentIntent

On the server, create a PaymentIntent for the computed amount and currency, and return its client secret to the app.

const intent = await stripe.paymentIntents.create({
  amount: computedAmountInCents,
  currency: 'usd',
});

Amounts are in the currency's smallest unit; for USD that's cents, so

0.00 is 1000, not 10.

4. Confirm Payment in the App

Initialize @stripe/stripe-react-native's PaymentSheet with the client secret, then present it. Stripe handles card entry, 3D Secure challenges, and Apple/Google Pay if enabled, without you building that UI yourself.

5. Fulfilment Belongs on the Webhook, Not the Client Callback

The PaymentSheet's success callback tells you the payment UI closed successfully, but the user's app could crash or lose connectivity a second later. Treat the client callback as a UX signal only; do the actual order fulfilment from a webhook (see Handle Stripe Webhooks).

Common Issues

Secret key ends up in the app grep your app bundle for sk_; if you find one, rotate the key immediately and move the logic server-side.

Amount off by 100x forgetting the minor-unit conversion;

0 charged as
000 or $0.10.

PaymentSheet fails to present usually the client secret wasn't fetched before presenting, or the publishable key doesn't match the account that created the intent (test vs live key mismatch).

Verification Checklist

  • the secret key exists only in server environment variables;
  • the app only ever holds the publishable key;
  • amounts are computed and validated server-side, never trusted from the client;
  • a real card processes successfully through PaymentSheet in test mode;
  • fulfilment happens from a webhook, not the client success callback.

Next Steps