Accepting online payments is one of the most important features of any eCommerce, subscription, food delivery, booking, or service application. Razorpay is one of India's most popular payment gateways and provides a simple Flutter SDK for integrating secure payments.

In this tutorial, you'll learn how to integrate Razorpay into your Flutter application from scratch.

What is Razorpay?

Razorpay is a secure online payment gateway that allows businesses to accept payments through:

  • UPI
  • Credit Cards
  • Debit Cards
  • Net Banking
  • Wallets
  • EMI
  • Pay Later

It offers an easy-to-use SDK for Flutter and excellent documentation.

Features

  • Secure payments
  • Fast integration
  • UPI support
  • Card payments
  • Wallet payments
  • Net Banking
  • EMI options
  • Payment callbacks
  • Refund support
  • Dashboard analytics

Prerequisites

Before starting, make sure you have:

  • Flutter SDK installed
  • Android Studio or VS Code
  • Razorpay Account
  • Android device or emulator
  • Basic Flutter knowledge

Step 1: Create Razorpay Account

  1. Visit Razorpay Dashboard.
  2. Create a new account.
  3. Verify your mobile number and email.
  4. Complete your business verification.
  5. Generate API Keys.

You'll receive:

Key ID

and

Key Secret

Never expose your Key Secret inside your Flutter application.

Step 2: Create Flutter Project

flutter create razorpay_demo

cd razorpay_demo

Step 3: Add Dependency

Open

pubspec.yaml

Add

dependencies:
  flutter:
    sdk: flutter

  razorpay_flutter: ^1.4.0

Now install

flutter pub get

Step 4: Android Configuration

Open

android/app/src/main/AndroidManifest.xml

Add Internet Permission

<uses-permission android:name="android.permission.INTERNET"/>

Step 5: iOS Configuration

Open

ios/Runner/Info.plist

Add

<key>LSApplicationQueriesSchemes</key>
<array>
<string>upi</string>
<string>phonepe</string>
<string>paytmmp</string>
<string>tez</string>
</array>

Then run

pod install

Step 6: Import Razorpay

import 'package:razorpay_flutter/razorpay_flutter.dart';

Step 7: Create Razorpay Object

late Razorpay _razorpay;

Initialize

@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);
}

Step 8: Create Payment Function

void openCheckout() {

  var options = {
    'key': 'YOUR_KEY_ID',
    'amount': 50000,
    'name': 'Deep Crazy World',
    'description': 'Flutter Course',
    'prefill': {
      'contact': '9876543210',
      'email': 'user@email.com'
    },
    'external': {
      'wallets': ['paytm']
    }
  };

  try {
    _razorpay.open(options);
  } catch (e) {
    print(e);
  }
}

Amount Calculation

Razorpay accepts the amount in paise.

AmountValue₹1100₹101000₹10010000₹50050000

Example:

amount: 99900

Means

₹999

Step 9: Payment Success Callback

void _handlePaymentSuccess(
    PaymentSuccessResponse response) {

  print(response.paymentId);

  ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text("Payment Successful"),
      ));
}

Step 10: Payment Failed

void _handlePaymentError(
    PaymentFailureResponse response) {

  ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text("Payment Failed"),
      ));
}

Step 11: External Wallet

void _handleExternalWallet(
    ExternalWalletResponse response) {

  print(response.walletName);
}

Step 12: Dispose

@override
void dispose() {
  _razorpay.clear();
  super.dispose();
}

Step 13: Payment Button

ElevatedButton(
  onPressed: openCheckout,
  child: Text("Pay Now"),
)

Complete Example

class PaymentPage extends StatefulWidget {
  const PaymentPage({super.key});

  @override
  State<PaymentPage> createState() => _PaymentPageState();
}

class _PaymentPageState extends State<PaymentPage> {

  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);
  }

  void openCheckout() {

    var options = {
      'key': 'YOUR_KEY_ID',
      'amount': 50000,
      'name': 'Flutter Shop',
      'description': 'Premium Product',
      'prefill': {
        'contact': '9876543210',
        'email': 'abc@gmail.com'
      }
    };

    _razorpay.open(options);
  }

  void _handlePaymentSuccess(
      PaymentSuccessResponse response) {

    print(response.paymentId);

    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text("Payment Successful"),
      ),
    );
  }

  void _handlePaymentError(
      PaymentFailureResponse response) {

    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text("Payment Failed"),
      ),
    );
  }

  void _handleExternalWallet(
      ExternalWalletResponse response) {

    print(response.walletName);
  }

  @override
  void dispose() {
    _razorpay.clear();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(
        title: Text("Razorpay Demo"),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: openCheckout,
          child: Text("Pay Now"),
        ),
      ),
    );
  }
}

Test Cards

During testing, Razorpay provides test payment methods in Test Mode. Use the Razorpay Dashboard documentation for the latest test cards, UPI IDs, and wallet credentials. Never use real customer payment details while testing.

Best Practices

  • Never store API Secret inside Flutter.
  • Create Orders from your backend.
  • Verify payment signature on the server.
  • Always use HTTPS APIs.
  • Validate payment before delivering products.
  • Log payment responses securely.
  • Handle payment failures gracefully.
  • Implement retries for network issues.

Common Errors

Payment Failed

  • Invalid API Key
  • Internet connection issue
  • Incorrect amount format
  • Razorpay account not activated

Plugin Not Working

Run

flutter clean

flutter pub get

Android Build Failed

Update Gradle

flutter doctor

Check Android SDK versions.

Payment Window Doesn't Open

Verify:

  • Internet permission added
  • Correct Key ID
  • Razorpay initialized properly
  • Event listeners registered

Production Checklist

  • Enable Live Mode.
  • Replace the Test Key with the Live Key ID.
  • Keep the Key Secret only on your backend.
  • Verify payment signatures server-side.
  • Test UPI, cards, wallets, and refunds.
  • Monitor transactions from the Razorpay Dashboard.

Advantages of Razorpay

  • Easy Flutter integration
  • Fast onboarding
  • Multiple payment methods
  • Secure transactions
  • Excellent dashboard
  • Refund support
  • Subscription payments
  • Payment links
  • Smart analytics

Conclusion

Integrating Razorpay into a Flutter application is straightforward when you follow the proper setup process. For a production-ready integration, always create payment orders on your backend, verify the payment signature after a successful transaction, and never expose your API Secret in the mobile app. Following these practices helps ensure secure and reliable payment processing for your users.