Skip to main content
RapidDev - Software Development Agency
flutterflow-tutorials

How to Integrate a Payment Gateway Other Than Stripe in FlutterFlow

All non-Stripe payment gateways in FlutterFlow follow the same three-step pattern: a Cloud Function creates a payment session and returns a checkout URL or client token, your FlutterFlow app launches the hosted checkout page (or loads a Custom Widget with the native SDK UI), and a webhook confirms the payment to another Cloud Function which updates your Firestore order status. Never build a custom card input form — always use the gateway's pre-built UI for PCI compliance.

What you'll learn

  • How PayPal, Razorpay, Square, Braintree, and Flutterwave follow the same Cloud Function architecture
  • How to create a PayPal order and redirect to PayPal's hosted checkout from FlutterFlow
  • How to integrate Razorpay with its native Flutter SDK for in-app payment UI
  • How to verify payment completion via webhooks and update order status in Firestore
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner10 min read60-90 minFlutterFlow Free+ (Cloud Functions required for all payment gateways)March 2026RapidDev Engineering Team
TL;DR

All non-Stripe payment gateways in FlutterFlow follow the same three-step pattern: a Cloud Function creates a payment session and returns a checkout URL or client token, your FlutterFlow app launches the hosted checkout page (or loads a Custom Widget with the native SDK UI), and a webhook confirms the payment to another Cloud Function which updates your Firestore order status. Never build a custom card input form — always use the gateway's pre-built UI for PCI compliance.

Non-Stripe payment gateways all follow the same architecture in FlutterFlow

Whether you choose PayPal (global brand recognition), Razorpay (India), Square (US in-person + online), Braintree (PayPal-owned, supports cards + PayPal + Venmo), or Flutterwave (Africa), the technical pattern in FlutterFlow is identical: a Cloud Function creates a payment session server-side, the app redirects to the gateway's hosted checkout or loads a native SDK widget, and a second Cloud Function receives the completion webhook. The only variation is whether the payment UI is a full browser redirect (PayPal, Square, Flutterwave) or an in-app native overlay (Razorpay, Braintree Drop-in). This tutorial covers both patterns.

Prerequisites

  • A developer account with your chosen payment gateway (PayPal Sandbox, Razorpay test mode, Square Sandbox, or Braintree Sandbox — all free)
  • A Firebase project with Cloud Functions enabled (Blaze billing plan required)
  • Your gateway's test API credentials (client ID/secret, API key, or public/private key pair)
  • A FlutterFlow project with user authentication and a cart or product page to attach payment to

Step-by-step guide

1

Create the payment session Cloud Function (PayPal example)

For PayPal: install the paypal-rest-sdk or use axios to call the PayPal Orders API directly. Cloud Function createPayPalOrder: (1) get an access token by POSTing to https://api-m.sandbox.paypal.com/v1/oauth2/token with your client_id:client_secret as Basic Auth; (2) create an order by POSTing to https://api-m.sandbox.paypal.com/v2/checkout/orders with body {intent: 'CAPTURE', purchase_units: [{amount: {currency_code: 'USD', value: '49.99'}}]}; (3) find the link in the response where rel == 'approve' — this is the PayPal checkout URL; (4) return it to FlutterFlow. Store client_id and client_secret in Cloud Function environment variables — never hardcode. In FlutterFlow, add an API Group pointing to your Cloud Functions URL and add a createPayPalOrder API Call (POST, JSON body with amount, currency, orderId).

Expected result: The createPayPalOrder Cloud Function returns a PayPal checkout URL that, when opened, shows a PayPal payment page.

2

Launch the payment checkout URL from FlutterFlow

In your FlutterFlow checkout button Action Flow: (1) call the createPayPalOrder API Call and store the returned approvalUrl in Page State variable paymentUrl; (2) add a Launch URL action using paymentUrl. On mobile, Launch URL opens the URL in the device's default browser or the PayPal app if installed. After the user completes payment, PayPal redirects to your return_url (set when creating the order). To detect the return: set the return_url to a deep link back to your app (e.g., yourapp://payment-complete?token={token}) and configure deep links in FlutterFlow Settings → Deep Link. In the deep link handler action, extract the PayPal token from the URL and call a capturePayPalOrder Cloud Function to finalize the payment. Alternatively, rely on the webhook (next step) and just navigate the user to an 'order processing' screen after returning from PayPal.

Expected result: Tapping the Checkout button opens the PayPal payment page in the browser, and users can complete payment with their PayPal account or credit card.

3

Integrate Razorpay with native Flutter SDK (in-app payment UI)

Razorpay provides a Flutter SDK that shows a native in-app payment sheet without leaving your app — better UX than browser redirect for Indian markets. In FlutterFlow, go to Custom Code → Pubspec Dependencies, add razorpay_flutter ^1.3.6. Create a Custom Action named openRazorpayCheckout. Import: import 'package:razorpay_flutter/razorpay_flutter.dart';. Initialize: final razorpay = Razorpay(); razorpay.on(Razorpay.EVENT_PAYMENT_SUCCESS, (response) { /* call Cloud Function to verify + update Firestore */ }); razorpay.on(Razorpay.EVENT_PAYMENT_ERROR, (response) { /* show error */ });. Create an order server-side in a Cloud Function (POST to https://api.razorpay.com/v1/orders) and pass the returned orderId to the Custom Action. Open checkout: razorpay.open({'key': 'rzp_test_xxx', 'amount': 4999, 'name': 'YourApp', 'order_id': orderId, 'prefill': {'email': userEmail}}). Amount is in smallest currency unit (paise for INR — 4999 = ₹49.99).

Expected result: Tapping Pay opens a Razorpay native payment sheet within the app. After payment, the success callback fires and updates the order in Firestore.

4

Verify payment via webhook and update order status

Payment webhooks are the authoritative confirmation — never rely solely on the client-side success callback (it can be spoofed). In your Firebase Cloud Functions, create an HTTP function paymentWebhook. For PayPal: verify the event by calling PayPal's webhook verification API. For Razorpay: verify the signature with crypto.createHmac('sha256', webhookSecret).update(rawBody).digest('hex') and compare to the X-Razorpay-Signature header. For Square: verify the X-Square-Hmacsha256-Signature header. After verification, extract the order ID from the event payload, find the matching Firestore order document, and update its status to 'paid' along with the payment transaction ID. Register your Cloud Function URL as the webhook endpoint in your gateway's developer dashboard: PayPal → Webhooks → Add Webhook, Razorpay → Settings → Webhooks → Add New Webhook.

Expected result: The Firestore order document status updates to 'paid' within seconds of payment completion, visible in the FlutterFlow app's order confirmation screen.

Complete working example

create_paypal_order_cloud_function.js
1// Cloud Function: createPayPalOrder
2// Creates a PayPal order and returns the approval URL
3const functions = require('firebase-functions');
4const axios = require('axios');
5
6const PAYPAL_CLIENT_ID = process.env.PAYPAL_CLIENT_ID;
7const PAYPAL_SECRET = process.env.PAYPAL_SECRET;
8const PAYPAL_BASE = 'https://api-m.sandbox.paypal.com'; // change to api-m.paypal.com for production
9
10async function getAccessToken() {
11 const creds = Buffer.from(`${PAYPAL_CLIENT_ID}:${PAYPAL_SECRET}`).toString('base64');
12 const resp = await axios.post(
13 `${PAYPAL_BASE}/v1/oauth2/token`,
14 'grant_type=client_credentials',
15 { headers: { Authorization: `Basic ${creds}`, 'Content-Type': 'application/x-www-form-urlencoded' } }
16 );
17 return resp.data.access_token;
18}
19
20exports.createPayPalOrder = functions.https.onRequest(async (req, res) => {
21 res.set('Access-Control-Allow-Origin', '*');
22 if (req.method === 'OPTIONS') return res.status(204).send('');
23 if (req.method !== 'POST') return res.status(405).send('POST only');
24
25 const { amount, currency = 'USD', internalOrderId } = req.body;
26 if (!amount) return res.status(400).json({ error: 'amount required' });
27
28 try {
29 const token = await getAccessToken();
30 const orderResp = await axios.post(
31 `${PAYPAL_BASE}/v2/checkout/orders`,
32 {
33 intent: 'CAPTURE',
34 purchase_units: [{
35 reference_id: internalOrderId,
36 amount: { currency_code: currency, value: String(amount) },
37 }],
38 application_context: {
39 return_url: 'yourapp://payment-complete',
40 cancel_url: 'yourapp://payment-cancelled',
41 },
42 },
43 { headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' } }
44 );
45
46 const approvalLink = orderResp.data.links.find(l => l.rel === 'approve');
47 return res.json({
48 paypalOrderId: orderResp.data.id,
49 approvalUrl: approvalLink.href,
50 });
51 } catch (err) {
52 return res.status(500).json({ error: err.message });
53 }
54});

Common mistakes

Why it's a problem: Building a custom card input form instead of using the gateway's pre-built UI

How to avoid: Always use the gateway's hosted checkout (PayPal, Square, Flutterwave) or their native SDK UI (Razorpay Flutter SDK, Braintree Drop-in). These components handle all card data on the gateway's servers — your app never sees the raw card number.

Why it's a problem: Using the client-side payment success callback as the sole confirmation

How to avoid: Always confirm payment via webhook before fulfilling orders. The webhook call comes directly from the payment gateway server to your Cloud Function — it cannot be spoofed by the client. Update the Firestore order status only after the verified webhook arrives.

Why it's a problem: Forgetting to switch from sandbox/test credentials to live credentials before launch

How to avoid: Use FlutterFlow Secrets with different values for test and production environments, or use Cloud Function environment variables with separate test and live values. Create a deployment checklist that explicitly verifies live credentials are active before every production release.

Best practices

  • Store the gateway API secret key exclusively in Cloud Function environment variables — never in client code, Firestore, or FlutterFlow Secrets
  • Always generate the payment amount in your Cloud Function based on server-side cart data from Firestore, not from the amount passed by the FlutterFlow client — amounts sent from the client can be tampered with
  • Test the complete payment flow including webhook delivery using the gateway's test webhooks feature before going live — PayPal, Razorpay, and Square all have webhook testing tools in their developer dashboards
  • Implement idempotency in your webhook handler — payment webhooks can be delivered more than once, so check if the order is already marked as paid before processing again
  • Show a processing screen while waiting for webhook confirmation rather than immediately showing a success screen — webhook delivery can take 1-10 seconds
  • Save the gateway's payment/transaction ID to the Firestore order document for refund reference — you will need this ID if you need to process a refund via the gateway dashboard or API
  • Test your payment flow with actual test card numbers provided by each gateway — Razorpay test cards differ from PayPal test accounts differ from Square sandbox cards

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

I am integrating PayPal payments into a FlutterFlow app. Write a Node.js Firebase Cloud Function named createPayPalOrder that: (1) authenticates to the PayPal Sandbox API using client credentials OAuth, (2) creates a PayPal order with the amount and currency from the request body, (3) sets return_url and cancel_url to deep link back to the app, (4) returns the approval URL and PayPal order ID. Store credentials in environment variables and include CORS headers for FlutterFlow API Manager calls.

FlutterFlow Prompt

Add a Razorpay payment button to my FlutterFlow checkout page. The button should call a Backend API to create a Razorpay order server-side, then open the Razorpay native payment sheet using a Custom Action with the razorpay_flutter package. On payment success, call another Backend API to verify the payment and update the Firestore order document status to paid.

Frequently asked questions

Which payment gateway should I choose for my FlutterFlow app?

Choose based on your market and customer preferences: PayPal for global apps where brand recognition reduces checkout abandonment, Razorpay for India (supports UPI, netbanking, wallet payments that Indian users prefer), Square for US businesses with in-person sales (POS + online), Braintree for apps needing PayPal + credit card in one SDK, Flutterwave for African markets. For most new global apps, Stripe remains the easiest to integrate and has the most comprehensive Flutter ecosystem.

Can I accept in-app purchases through the App Store and Google Play instead of a third-party gateway?

Yes, using the in_app_purchase Flutter package added via Custom Code → Pubspec Dependencies. In-app purchases go through Apple/Google's native payment systems, which handle all payment UI and PCI compliance. The trade-off: Apple takes 15-30% and Google takes 15-30% of each purchase. Use IAP for digital goods (premium features, subscriptions, virtual currency). For physical goods, services, or B2B sales, third-party gateways like PayPal and Stripe are allowed and have lower fees.

How do I handle refunds with non-Stripe payment gateways?

Refunds are typically initiated from the gateway's merchant dashboard or via the gateway's refund API. For PayPal: POST to /v2/payments/captures/{captureId}/refund with the amount. Store the PayPal capture ID in your Firestore order document during the webhook processing step. For Razorpay: POST to /v1/payments/{paymentId}/refund. Add a Cloud Function refundPayment triggered by an admin action in your FlutterFlow app, and store refund transaction IDs back in Firestore for tracking.

Can I use multiple payment gateways in the same FlutterFlow app?

Yes — route to different gateways based on the user's region or preference. Add a payment method selector to your checkout page (Radio buttons: PayPal, Card, UPI). Based on the selection, call a different Cloud Function endpoint that handles the corresponding gateway. This is common for apps with global user bases — Stripe or Braintree for Western users, Razorpay for Indian users, Flutterwave for African users.

Does FlutterFlow have built-in support for any payment gateways?

FlutterFlow has a native Stripe integration that handles simple checkout without requiring a Cloud Function for basic use cases. All other payment gateways (PayPal, Razorpay, Square, Braintree, Flutterwave) require the Cloud Function pattern described in this tutorial. The built-in Stripe widget handles payment intents and card forms — for Stripe's advanced features (subscriptions, Connect marketplace, custom UI) you still need the Cloud Function pattern.

What if I need help setting up a payment gateway integration for my FlutterFlow app?

Payment integrations involve security-sensitive server-side code, webhook verification, and fraud prevention patterns. Getting them wrong can result in financial losses or App Store rejection. RapidDev has integrated PayPal, Razorpay, Braintree, and Flutterwave into FlutterFlow apps and can set up a complete payment flow including Cloud Functions, webhook handlers, and Firestore order management for your app.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.