Introduction
Digital payments have become the backbone of modern applications. Whether you’re building an e-commerce store, a subscription-based SaaS platform, or a booking app, the ability to accept payments securely and seamlessly is critical. With Flutter becoming one of the most popular cross-platform frameworks, developers frequently face the challenge of integrating payment gateways into their apps.
We'll look at how to include three of the most popular payment methods into Flutter apps in this blog:
- Razorpay – widely used in India.
- Stripe – global payment leader.
- PayPal – one of the oldest and most trusted digital wallets.
We’ll discuss the setup, integration process, coding examples, and best practices for each. By the end, you’ll have a clear roadmap to implement secure payments in your Flutter apps.
Why Payment Gateway Integration Matters
Before diving into code, let’s first understand why integrating a reliable payment gateway is important:
- Security: Payment gateways provide PCI-DSS compliance by handling private card and wallet information.
- Global Reach – They support multiple currencies, allowing businesses to sell internationally.
- Convenience – Customers can pay with their preferred method: cards, wallets, UPI, net banking, etc.
- Automation – They provide APIs for refunds, subscriptions, invoicing, and transaction history.
- Trust – Known gateways like PayPal, Stripe, and Razorpay add credibility to your app.
Pre-requisites for Payment Gateway Integration in Flutter
Before you begin coding, make sure you have:
- Flutter SDK installed and set up.
- Backend server (Node.js, Django, Firebase, etc.) – optional, but recommended for handling sensitive API keys.
- Payment gateway account (Razorpay, Stripe, PayPal).
- API Keys – test and live keys from the payment provider’s dashboard.
Pro Tip: Always start integration in sandbox/test mode before switching to live payments.
Part 1: Integrating Razorpay in Flutter
Razorpay is one of the most popular payment gateways in India, offering a wide range of options like UPI, cards, wallets, and net banking.
Step 1: Add Razorpay Flutter Plugin
Add the following dependency to your pubspec.yaml:
dependencies:
razorpay_flutter: ^1.3.5
Run:
flutter pub get
Step 2: Initialize Razorpay
Create a new instance in your Dart file:
import 'package:flutter/material.dart';
import 'package:razorpay_flutter/razorpay_flutter.dart';
class RazorpayPaymentPage extends StatefulWidget {
@override
_RazorpayPaymentPageState createState() => _RazorpayPaymentPageState();
}
class _RazorpayPaymentPageState extends State<RazorpayPaymentPage> {
late Razorpay _razorpay;
@override
void initState() {
super.initState();
_razorpay = Razorpay();
_razorpay.on(Razorpay.EVENT_PAYMENT_SUCCESS, _handlePaymentSuccess);
_razorpay.on(Razorpay.EVENT_PAYMENT_ERROR, _handlePaymentError);
_razorpay.on(Razorpay.EVENT_EXTERNAL_WALLET, _handleExternalWallet);
}
@override
void dispose() {
_razorpay.clear();
super.dispose();
}
void openCheckout() {
var options = {
'key': 'rzp_test_1234567890abcdef', // Replace with your test key
'amount': 50000, // Amount in paise (50000 = ₹500)
'name': 'My App',
'description': 'Payment for services',
'prefill': {'contact': '9876543210', 'email': 'test@example.com'},
'external': {'wallets': ['paytm']}
};
try {
_razorpay.open(options);
} catch (e) {
debugPrint('Error: $e');
}
}
void _handlePaymentSuccess(PaymentSuccessResponse response) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Payment Successful: ${response.paymentId}")),
);
}
void _handlePaymentError(PaymentFailureResponse response) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Payment Failed: ${response.message}")),
);
}
void _handleExternalWallet(ExternalWalletResponse response) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("External Wallet: ${response.walletName}")),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Razorpay Integration")),
body: Center(
child: ElevatedButton(
onPressed: openCheckout,
child: Text("Pay with Razorpay"),
),
),
);
}
}
Step 3: Testing Razorpay
- Use Razorpay’s test key (rzp_test_...).
- To test, use fake cards and the UPI IDs from Razorpay Docs.
Part 2: Integrating Stripe in Flutter
Stripe is a global leader in payments, known for its powerful APIs and support for cards, wallets (Apple Pay, Google Pay), and subscriptions.
Step 1: Add Stripe Plugin
Add the official Flutter Stripe SDK:
dependencies:
flutter_stripe: ^11.0.0
Run:
flutter pub get
Step 2: Initialize Stripe
In your main.dart:
import 'package:flutter/material.dart';
import 'package:flutter_stripe/flutter_stripe.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
Stripe.publishableKey = "pk_test_1234567890abcdef"; // Replace with your key
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: StripePaymentPage(),
);
}
}
Step 3: Payment Flow
Stripe usually requires a backend server to create PaymentIntents for security reasons.
Backend (Node.js example):
const express = require("express");
const Stripe = require("stripe");
const stripe = Stripe("sk_test_1234567890abcdef"); // Secret key
const app = express();
app.post("/create-payment-intent", async (req, res) => {
const paymentIntent = await stripe.paymentIntents.create({
amount: 5000, // $50.00
currency: "usd",
payment_method_types: ["card"],
});
res.send({
clientSecret: paymentIntent.client_secret,
});
});
app.listen(3000, () => console.log("Server running on port 3000"));
Flutter (Frontend):
import 'package:flutter/material.dart';
import 'package:flutter_stripe/flutter_stripe.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
class StripePaymentPage extends StatefulWidget {
@override
_StripePaymentPageState createState() => _StripePaymentPageState();
}
class _StripePaymentPageState extends State<StripePaymentPage> {
Map<String, dynamic>? paymentIntentData;
Future<void> makePayment() async {
try {
final response = await http.post(
Uri.parse("http://localhost:3000/create-payment-intent"),
);
paymentIntentData = jsonDecode(response.body);
await Stripe.instance.initPaymentSheet(
paymentSheetParameters: SetupPaymentSheetParameters(
paymentIntentClientSecret: paymentIntentData!['clientSecret'],
merchantDisplayName: 'My App',
),
);
await Stripe.instance.presentPaymentSheet();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Payment Successful!")),
);
} catch (e) {
print(e);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Payment Failed")),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Stripe Integration")),
body: Center(
child: ElevatedButton(
onPressed: makePayment,
child: Text("Pay with Stripe"),
),
),
);
}
}
Step 4: Testing Stripe
- Use Stripe Test Cards.
- For instance, 4111 1111 1111 1111(any CVC, any future expiry).
Part 3: Integrating PayPal in Flutter
PayPal is a trusted payment provider, especially popular in the US and Europe. It allows users to pay with their PayPal balance or linked cards.
Step 1: Use Flutter PayPal Plugin
One option is flutter_paypal_checkout:
dependencies:
flutter_paypal_checkout: ^1.0.2
Run:
flutter pub get
Step 2: Implement PayPal Checkout
import 'package:flutter/material.dart';
import 'package:flutter_paypal_checkout/flutter_paypal_checkout.dart';
class PayPalPaymentPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("PayPal Integration")),
body: Center(
child: ElevatedButton(
child: Text("Pay with PayPal"),
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) => PaypalCheckout(
sandboxMode: true,
clientId: "YOUR_PAYPAL_CLIENT_ID",
secretKey: "YOUR_PAYPAL_SECRET_KEY",
returnURL: "success.example.com",
cancelURL: "cancel.example.com",
transactions: [
{
"amount": {
"total": '10.00',
"currency": "USD",
"details": {
"subtotal": '10.00',
"shipping": '0',
"shipping_discount": 0
}
},
"description": "Payment for order",
}
],
note: "Contact us for any issues",
onSuccess: (Map params) async {
print("OnSuccess: $params");
},
onError: (error) {
print("OnError: $error");
},
onCancel: () {
print("Cancelled");
},
),
));
},
),
),
);
}
}
Step 3: Testing PayPal
- Use sandbox mode with test credentials from PayPal Developer Dashboard.
Best Practices for Payment Integration
- Use Test Mode First – Always verify flows with sandbox keys.
- Backend Security – Never store or expose secret keys in Flutter apps.
- Error Handling – Show proper messages for failed payments.
- Receipts – Generate receipts after successful payments.
- Refunds and Disputes – Implement refund handling via backend APIs.
- Compliance – Ensure PCI-DSS compliance and country-specific regulations.
- User Experience – Keep the payment process smooth with fewer clicks.
Choosing the Right Payment Gateway
- Razorpay – Best for India (UPI, cards, net banking, Paytm, etc.).
- Stripe – Best for global apps (subscriptions, wallets, Apple Pay, Google Pay).
- PayPal – Trusted brand, great for international buyers.
Many apps integrate multiple gateways to give users flexibility.
Conclusion
Integrating payment gateways in Flutter might seem complex, but with the right approach, it becomes straightforward. Razorpay, Stripe, and PayPal all provide solid SDKs and APIs that work smoothly with Flutter.
To recap:
- Razorpay – quick integration for India.
- Stripe – robust global solution for cards and subscriptions.
- PayPal – trusted digital wallet worldwide.
By following the steps above, you can enable seamless payments in your app and provide a secure, trustworthy experience to your users.