Connect FlutterFlow to Stripe using the built-in native Payment action: go to Settings → Integrations → Payments, toggle Stripe, paste your publishable and secret keys, then drop a 'Stripe Payment' action on any button. FlutterFlow auto-deploys a Firebase Cloud Function so your secret key never ships in the client. Firebase Blaze plan required.
| Fact | Value |
|---|---|
| Tool | Stripe |
| Category | Payments |
| Method | FlutterFlow Native Integration |
| Difficulty | Intermediate |
| Time required | 45 minutes |
| Last updated | July 2026 |
The Only Two Native Payment Gateways in FlutterFlow
FlutterFlow natively supports just two payment processors out of the box: Stripe and Braintree. That native status is a big deal. Instead of hand-building API Call groups, writing Cloud Function proxies from scratch, and manually parsing JSON responses, you configure Stripe in two minutes through a settings screen and get a polished payment sheet — the same card UI that users see in major consumer apps — with zero extra code.
The magic works because FlutterFlow handles the hard security problem for you. When you enter your Stripe secret key (the sk_ key that must never reach a client device) into the FlutterFlow Payments settings, the platform stores it server-side and auto-deploys a Firebase Cloud Function named createStripePaymentIntent. This function creates a PaymentIntent on Stripe's servers and returns a client secret to the app, which then presents the native payment sheet. Your sk_ key never touches the compiled Flutter code — it lives only in Firebase's environment variables.
There is one important constraint: the native Stripe integration requires Firebase as your project backend, and specifically the Firebase Blaze (pay-as-you-go) plan. Cloud Functions don't run on the free Spark plan. If your project uses Supabase as its primary backend, you'll need to either add Firebase alongside it or hand-roll a Supabase Edge Function proxy and call Stripe's REST API manually. This tutorial focuses on the far more common Firebase-native path. Stripe charges 2.9% + 30¢ per transaction with no monthly fee, and a free test mode is available instantly after signup.
Integration method
FlutterFlow includes built-in Stripe support under Settings → Integrations → Payments. When you toggle Stripe on and enter your keys, FlutterFlow automatically deploys a Firebase Cloud Function called createStripePaymentIntent that handles the server-side charge — your secret key stays safely in the Cloud Function and never compiles into the app bundle. You then wire a 'Stripe Payment' action to any button in the Action Flow Editor.
Prerequisites
- A FlutterFlow project with Firebase connected (Settings → Firebase → connect your Firebase project)
- A Firebase project on the Blaze (pay-as-you-go) plan — Cloud Functions won't deploy on the free Spark plan
- A Stripe account — sign up at stripe.com; test mode is available immediately
- Stripe test publishable key (pk_test_...) and test secret key (sk_test_...) from the Stripe Dashboard → Developers → API keys
Step-by-step guide
Verify Firebase is connected and on Blaze plan
Before touching Stripe settings, make sure your Firebase foundation is solid. Open FlutterFlow and go to Settings & Integrations (the gear icon in the left nav) → Firebase. You should see a green 'Connected' badge showing your Firebase project name and project ID. If it shows disconnected, click 'Connect Firebase Project' and follow the OAuth flow to link your Google account and select the correct project. Next, confirm the Blaze plan is active. The native Stripe payment sheet auto-deploys a Firebase Cloud Function (createStripePaymentIntent) the first time you publish a payment-enabled build. Cloud Functions are disabled on the free Spark plan, so your payment will fail silently at runtime — no error in FlutterFlow's test mode, just a blank screen on device. To check or upgrade: open the Firebase Console at console.firebase.google.com, select your project, click the Spark/Blaze badge at the bottom-left of the sidebar, and choose 'Upgrade'. Set a spending limit of $5–10/month to avoid surprise bills — Cloud Functions at this scale cost pennies. Also confirm that Cloud Functions are enabled in the Firebase Console under Build → Functions. If you've never deployed a function to this project before, Firebase may prompt you to enable billing once more. Once you see 'Functions is ready', return to FlutterFlow.
Pro tip: If you're on a team and someone else owns the Firebase project, make sure you have Editor or Owner permissions — FlutterFlow needs these to auto-deploy the Cloud Function.
Expected result: FlutterFlow Settings → Firebase shows a green 'Connected' badge. Firebase Console shows Blaze plan active and Functions enabled.
Enable Stripe in FlutterFlow Payments settings
Now for the core configuration. In FlutterFlow, go to Settings & Integrations (gear icon) → In-App Purchases & Subscriptions → Payments. You'll see a list of payment providers; find Stripe and click the toggle to enable it. A configuration panel expands. You'll see two tabs: Test and Live. Start with Test. Enter your Stripe test publishable key (pk_test_...) in the 'Publishable Key' field and your test secret key (sk_test_...) in the 'Secret Key' field. Both keys come from the Stripe Dashboard → Developers → API keys. The publishable key is safe to enter anywhere; the secret key is stored server-side by FlutterFlow and will be injected into the Cloud Function environment — it never appears in your compiled Dart code. Below the keys, enter a Merchant Display Name — this is the text that appears in the payment sheet header (e.g., 'Acme Store'). Users see this when they're about to enter card details, so make it your brand name. Leave the Live tab empty for now; you'll fill it in before publishing to the App Store or Play Store. Click Save. FlutterFlow validates that both keys are non-empty and match the pk_/sk_ format — a red validation error appears if something is wrong. Once saved successfully, you're ready to add the payment action.
Pro tip: The secret key field in FlutterFlow's UI is masked (shows dots). If you're unsure what you pasted, delete and re-paste — you can't reveal it after saving. Stripe let you create multiple restricted keys; use a key restricted to PaymentIntents write if you want tighter security.
Expected result: Settings → Payments shows Stripe as enabled with a green toggle. No validation errors appear. The test key fields show masked values.
Add a Stripe Payment action to your checkout button
Now wire the payment to your UI. Navigate to the screen in your app where checkout happens — typically a cart screen or a product detail page. Select the 'Buy Now' or 'Pay' button. In the right panel, click the Actions tab (lightning bolt icon), then click '+ Add Action'. In the action search field, type 'Stripe' or scroll to the Monetization section. Select 'Stripe Payment'. The action configuration panel opens on the right. Configure three mandatory fields: **Amount**: This must be in the smallest currency unit (cents for USD, pence for GBP). If your product costs $19.99, enter 1999. Do NOT enter 19.99 — Stripe will charge the customer $19.99 interpreted as 1999 cents, which is $19.99, but if you enter the dollar value directly it charges 20 cents. The most reliable approach: multiply your dollar amount by 100 using a Custom Function or store prices in cents in Firestore from the start. You can bind this to a page variable or state, such as `int priceInCents` passed from the product document. **Currency**: Enter the ISO code (usd, gbp, eur, etc.). Case-insensitive. **Payment Description**: Short text shown in the payment confirmation email Stripe sends automatically (e.g., 'Purchase – Acme Store'). After saving the action, the Action Flow Editor shows a 'Stripe Payment' node. Drag a TRUE branch (success) and FALSE branch (failure) off the node. On success, add a 'Navigate to' action pointing to your order confirmation screen, and optionally a Firestore document create/update to record the order. On failure, add a 'Show Snack Bar' action with a helpful message like 'Payment failed — please try again or use a different card'.
Pro tip: Store prices in cents (integer) in Firestore from the beginning. It prevents rounding issues and makes the Stripe amount binding trivial — just pass the Firestore field directly.
Expected result: The button's Action Flow shows a Stripe Payment node with TRUE (success) and FALSE (failure) branches connected to navigation or Snack Bar actions.
Handle payment success: write to Firestore and navigate
A payment action without a Firestore write is incomplete — if the app crashes or the user closes it right after paying, you have no record of the transaction. The standard pattern is: Stripe Payment succeeds → create an 'orders' Firestore document → navigate to confirmation screen. In the Action Flow Editor, click the TRUE branch node after the Stripe Payment action. Click '+ Add Action' → Firestore → Create Document. Set the collection to 'orders' (create this collection in Firestore first if it doesn't exist). Map the document fields: - `userId`: bind to the logged-in user's UID (from Authenticated User → UID) - `amount`: same amount variable used in the Stripe action - `currency`: the currency string - `status`: set as a string literal 'paid' - `createdAt`: set to Current DateTime - `stripePaymentId`: the Stripe action returns a `paymentId` output — bind this to capture the Stripe charge ID for reconciliation After the Firestore write, add a Navigate action to your Order Confirmation screen and pass the document reference or a success boolean as a parameter. For the FALSE branch: user-initiated cancellations (tapping X on the payment sheet) and card declines both trigger this path. Show a friendly Snack Bar — avoid exposing raw Stripe error codes to users. If you need to surface the decline reason for debugging, you can log the error output of the Stripe action to an 'errors' Firestore collection, but don't show it in-app. Finally, note that the Stripe action also returns a status boolean (`isPaid`) — you can use this in a conditional in the Action Flow as an alternative to branching on the action's own TRUE/FALSE output, if you want to log even 'failed' attempts.
Pro tip: Always create the Firestore 'orders' collection with RLS-equivalent Firestore Security Rules before testing: allow reads to `request.auth.uid == resource.data.userId` and writes to authenticated users only.
Expected result: After a successful test payment, a new document appears in the Firestore 'orders' collection with status 'paid' and the Stripe paymentId populated.
Test with Stripe test cards, then switch to Live keys
FlutterFlow's web preview (Run mode) cannot render the native Stripe payment sheet — the sheet requires a compiled Flutter environment. You must test on an actual device or iOS/Android emulator by using FlutterFlow's 'Preview on Device' feature or by downloading and building the Flutter project. To test on device: click the Preview button (top-right) → 'Test on Device' → scan the QR code with the FlutterFlow Companion app on your phone. Navigate to your checkout screen and tap 'Buy'. The native Stripe payment sheet appears. Use Stripe's test card number: **4242 4242 4242 4242**, expiry any future date (e.g., 12/34), CVC any 3 digits, postal code any 5 digits. This card always succeeds. To test a declined card, use 4000 0000 0000 0002. To test 3D Secure authentication, use 4000 0025 0000 3155. After a successful test payment, verify: 1. The Stripe Dashboard → Test mode → Payments shows the transaction with 'Succeeded' status. 2. Your Firestore 'orders' collection has the new document. 3. Your app navigated to the confirmation screen. When everything works in test mode, return to Settings → Payments → Stripe → Live tab. Enter your live publishable key (pk_live_...) and live secret key (sk_live_...) from the Stripe Dashboard. Switch Stripe Dashboard to Live mode to get the live keys. Click Save. Your next published build will use live keys — test mode remains active for unpublished runs. Do NOT flip to live keys until you've verified the full flow. Real money moves on live keys — a failed order confirmation screen after a successful charge is a support nightmare.
Pro tip: Set up a Stripe webhook in the Stripe Dashboard → Webhooks pointing to a Firebase Cloud Function to receive payment_intent.succeeded and payment_intent.payment_failed events. This gives you server-side confirmation independent of the app UI, which is essential for order management.
Expected result: Test payment of any amount appears in Stripe Dashboard as 'Succeeded'. Firestore order document is created. App shows the confirmation screen.
Common use cases
E-commerce app selling physical or digital products
Build a product catalogue in FlutterFlow backed by Firestore, add to cart logic, and a checkout screen that triggers a Stripe Payment action. On success, write the order to Firestore and navigate to a confirmation page. The native payment sheet handles card entry, Apple Pay, and Google Pay automatically.
A shopping app where users browse products, add them to a cart, and pay with a card or Apple Pay — amounts sent in cents, order saved to Firestore on success.
Copy this prompt to try it in FlutterFlow
Subscription or membership app with recurring billing
For one-time purchases the native action is enough; for subscriptions you create a Stripe Customer and Subscription via a Cloud Function triggered by the FlutterFlow API Call, then surface the plan status from Firestore in the app UI.
A fitness app where users buy a monthly membership — the app calls a Cloud Function to create a Stripe Subscription and then shows an 'Active Member' badge stored in their Firestore profile.
Copy this prompt to try it in FlutterFlow
On-demand service booking with payment capture
A home-services or freelance marketplace where a customer books a service and pays upfront. The Stripe Payment action captures the charge immediately; a Firestore write notifies the provider. Cancellation and refund flows can be added via additional Cloud Function calls.
A cleaning booking app where users pick a date, enter card details, and pay $80 for a 2-hour slot — payment confirmed before the booking is visible to the cleaner.
Copy this prompt to try it in FlutterFlow
Troubleshooting
Payment sheet never appears — the button taps but nothing happens
Cause: Firebase Cloud Functions are not deployed because the Firebase project is on the Spark (free) plan, or Cloud Functions weren't enabled in the Firebase Console.
Solution: Upgrade the Firebase project to Blaze plan in the Firebase Console (bottom-left badge → Upgrade). Then open FlutterFlow → Settings → Firebase → Deploy and redeploy. The createStripePaymentIntent function should appear under Firebase Console → Build → Functions after the next build.
Amount charged is 100× higher than expected (e.g., $19.99 charge becomes $1,999)
Cause: The amount field in the Stripe Payment action was set to a dollar value (e.g., 19.99) instead of cents (1999). Stripe always interprets amounts in the smallest currency unit.
Solution: Change the amount to cents: multiply dollars × 100. In FlutterFlow, create a Custom Function: `int toCents(double dollars) => (dollars * 100).round();` and bind its output to the Stripe action's amount field. Or store prices as integers (in cents) in Firestore from the start.
1int toCents(double dollars) => (dollars * 100).round();Payment succeeds on Stripe but the Firestore order document is not created
Cause: The Firestore Security Rules block authenticated users from writing to the 'orders' collection, or the TRUE branch Action Flow is missing the Firestore create action.
Solution: Open Firebase Console → Firestore → Rules and add a write rule: `allow create: if request.auth != null && request.auth.uid == request.resource.data.userId;`. Also verify in FlutterFlow's Action Flow Editor that the TRUE branch after the Stripe Payment node has a 'Create Firestore Document' action connected.
1allow create: if request.auth != null && request.auth.uid == request.resource.data.userId;Apple Pay or Google Pay button appears on device but fails at authorization
Cause: Apple Pay requires a merchant ID registered in the Apple Developer Portal and an associated domain verified with Stripe. Google Pay needs the app to be published on Play Store (or use a test environment declaration).
Solution: For Apple Pay: register a Merchant ID in the Apple Developer Portal under Identifiers → Merchant IDs, add the Stripe domain verification file at /.well-known/apple-developer-merchantid-domain-association, and configure the merchant ID in your Xcode project. For Google Pay: in the Google Pay API console, add your app's package name and SHA-1 certificate fingerprint. Both are native platform setup steps outside FlutterFlow.
Best practices
- Store all prices in cents (integer) in Firestore from the start — it prevents rounding errors and makes Stripe amount binding trivial.
- Never enter your live secret key (sk_live_...) until you have fully tested the complete checkout-to-confirmation flow in test mode.
- Set up a Stripe webhook handler (Firebase Cloud Function) for payment_intent.succeeded to confirm orders server-side, independent of app UI state.
- Add Firestore Security Rules to the 'orders' collection so only the authenticated user who created the order can read it — never leave collections unrestricted.
- Display a loading state (CircularProgressIndicator) while the Stripe sheet is opening — the payment intent creation takes 1–2 seconds on first call.
- Use the paymentId returned by the Stripe action to store the Stripe charge ID in Firestore, enabling easy reconciliation and refund processing from the Stripe Dashboard.
- Test all decline scenarios with Stripe's test card 4000 0000 0000 0002 and ensure your FALSE branch shows a user-friendly message — never expose raw Stripe error codes to customers.
- Before App Store / Play Store submission, switch to live keys, remove all test-mode Firestore data, and run one real $0.50 test charge to confirm end-to-end.
Alternatives
Braintree is the other natively supported payment processor in FlutterFlow — choose it if you need PayPal as a payment method alongside cards, or if your business already has a Braintree/PayPal merchant account.
Square is better for in-person POS and retail use cases but requires a fully custom API Call + Cloud Function setup in FlutterFlow — much more work than Stripe's native toggle.
Adyen is an enterprise-grade multi-currency processor with no native FlutterFlow support — choose it for high-volume international commerce where negotiated rates matter, but expect significant custom code.
Frequently asked questions
Can I use the native Stripe integration with a Supabase backend instead of Firebase?
Not directly. The native Stripe Payment action in FlutterFlow requires Firebase and auto-deploys a Firebase Cloud Function. If your project uses Supabase, you need to either add Firebase alongside it (just for Cloud Functions) or manually build an API Call group that calls a Supabase Edge Function proxy, which then creates the PaymentIntent on Stripe. The Supabase path requires more setup but is fully possible.
Is the Stripe secret key safe when entered into FlutterFlow's Payments settings?
Yes — FlutterFlow stores the secret key server-side and injects it into the Firebase Cloud Function environment, not into your compiled Flutter code. The Dart app never sees the sk_ key; it only receives the client secret from the Cloud Function. Do NOT separately hardcode the secret key in any API Call header or Custom Action Dart code, as that would compile into the app bundle.
Why can't I test the payment sheet in FlutterFlow's Run mode (web preview)?
The native Stripe payment sheet is a platform-native UI component that requires a compiled Flutter environment on iOS or Android. FlutterFlow's web preview runs a different rendering path that can't instantiate the native sheet. Use the FlutterFlow Companion app on your device or download and build the Flutter project to an emulator for full payment testing.
Can I add subscriptions or recurring billing through the native Stripe integration?
The native Stripe Payment action handles one-time charges only. For subscriptions, you need to create Stripe Customers and Subscriptions via a Firebase Cloud Function, then call that function from an FlutterFlow API Call. The native action handles the payment sheet UI, but subscription lifecycle (create, cancel, upgrade, webhook events) requires custom Cloud Function code. If you'd rather skip the custom code, RapidDev's team builds FlutterFlow integrations like this every week — free scoping call at rapidevelopers.com/contact.
How do I handle refunds from within the FlutterFlow app?
Refund creation must happen server-side (never client-side, since it requires the secret key). Create a Firebase Cloud Function that calls POST https://api.stripe.com/v1/refunds with the charge or payment_intent ID. In FlutterFlow, add an API Call that hits this Cloud Function's URL, passing the payment ID from Firestore. Restrict refund access to admin users using Firestore Security Rules and a role field in the user document.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation