Payment Gateways in Flutter: Razorpay, PayU, CCAvenue and Stripe compared
How mobile payment integration actually works, how the main gateways differ for Indian and global apps, and the security and edge-case handling that separates a demo from a production checkout.
Adding payments to a mobile app looks like a two-day task and rarely is. The SDK call is small; the work sits in verification, failure handling and the states a payment can end up in. This guide covers how mobile payments actually flow, how the main gateways differ, and what separates a demo checkout from one that can take real money.
The one rule that matters
Never trust the client to say a payment succeeded. Always verify on your server.
Every gateway returns a success callback to the app. That callback is a hint, not proof. A modified client can fake it. The order should only be marked paid after your backend has either verified the signature on the response or confirmed the payment by calling the gateway directly.
How the flow actually works
Almost every gateway follows the same five steps.
- Your server creates an order with the gateway, sending the amount and currency, and receives an order or intent id. The amount is decided server-side — never sent up from the app, or a user can change the price.
- The app opens the gatewaywith that id and a public key. The user enters card details, UPI or wallet credentials inside the gateway's own UI.
- The gateway returns a result to the app: a payment id and a signature, or an error.
- Your server verifies the signature, or fetches the payment status from the gateway API, and only then updates the order.
- A webhook confirms independently. The gateway calls your server directly with the final status. This is the source of truth.
Step 5 is the one teams skip, and it is the one that saves you. If the user's phone dies between paying and returning to the app, the webhook is the only way you learn the money arrived.
Comparing the common gateways
| Gateway | Best suited to | Notes |
|---|---|---|
| Razorpay | Indian apps | Broad UPI, netbanking, card and wallet coverage. Clean Flutter SDK, good docs, quick onboarding for Indian businesses. |
| PayU | Indian apps, established merchants | Similar coverage; often chosen for existing commercial terms rather than developer experience. |
| CCAvenue | Enterprise and legacy integrations | Very wide payment-method support and long-standing enterprise presence. Integration is more dated than the newer options. |
| Stripe | Global and subscription products | Excellent API design, strong subscription tooling, wide international coverage. Availability and settlement rules vary by country. |
For an India-first product, the practical shortlist is usually Razorpay or PayU because UPI matters more than anything else. For a global or subscription product, Stripe is usually the stronger fit. Many apps end up supporting more than one.
Choosing: the questions that decide it
- Where are your customers? This narrows the list faster than any feature comparison.
- Which methods must you support? In India, UPI is not optional.
- One-off or recurring? Subscriptions, mandates and auto-debit differ substantially between providers and are worth testing before committing.
- What are the settlement terms? How long until money reaches the bank account, and what are the per-transaction fees?
- Refunds and disputes. Can your operations team handle them from a dashboard, or does every refund need an engineer?
Apple and Google take their cut of digital goods
This catches teams late and can block a release. If you sell digital content or services consumed inside the app — subscriptions, premium features, in-app currency — the store rules generally require their in-app purchase systems, with the associated commission.
Third-party gateways are for physical goods and real-world services: retail, delivery, bookings, tickets. A jewellery store or a food-delivery app uses Razorpay. A meditation app selling a subscription generally cannot. Check the current rules for both stores before building, because they change and there are regional exceptions.
The states a checkout can be in
Treating payment as a boolean is the most common design error. A real checkout has at least:
- Idle — nothing started
- Creating order — waiting on your own backend
- Awaiting gateway — the user is in the payment UI
- Verifying — returned to the app, server confirming
- Succeeded — verified, order confirmed
- Failed — declined or errored, safe to retry
- Pending — some methods, including certain UPI flows, settle asynchronously
That pending state is essential and frequently missed. If you only have success and failure, an asynchronous payment shows the user an error while the money leaves their account.
Edge cases worth testing deliberately
- User backs out of the gateway screen halfway.
- App is killed while the payment app is in the foreground.
- Network drops immediately after payment, before verification.
- User taps pay twice — idempotency keys prevent a double charge.
- Payment succeeds but your own server errors while saving the order.
- Refund issued from the dashboard — does the app reflect it?
- Card declined, insufficient funds, expired card, wrong OTP.
Every gateway provides test credentials for these. Work through the list before launch, not after the first support ticket.
Security basics
- Keep secret keys on the server. Only the public key belongs in the app. Anything shipped in an APK can be extracted.
- Never store card details yourself.Let the gateway's UI handle them so card data never touches your systems.
- Verify webhook signatures. An unauthenticated webhook endpoint is a way to fake payments.
- Log payment ids, never payment data. Check what your analytics and crash reporting actually capture.
- Use idempotency keys so a retried request cannot charge twice.
A realistic estimate
A single-gateway, one-off card and UPI checkout, done properly with server verification, webhooks and the failure states above, is typically a week of work rather than a day. Subscriptions and mandates take longer. Budget accordingly: this is the part of the app where bugs cost money directly.
Read next
Flutter State Management: setState, Provider, BLoC and Riverpod compared
A practical guide to choosing state management in Flutter. What each option is good at, where each breaks down…
Flutter Performance: how to find and fix jank, slow lists and memory problems
Why Flutter apps stutter and what to do about it — rebuild scope, list building, image sizing, expensive widge…