Razorpay Flutter Banking Wrapper SDK

Flutter plugin for Razorpay Banking Payment SDK.

Getting Started

This Flutter plugin is a wrapper for the Razorpay Banking Payment flow. It supports iOS only; on Android the plugin reports that the platform is not supported via the onPaymentError callback, and you should use the native Android Payment SDK for Android.

To know more about Razorpay payment flow and documentation, refer to: https://razorpay.com/docs/

Prerequisites

Installation

Add this to dependencies in your app's pubspec.yaml:

From pub.dev (recommended):

dependencies:
  razorpay_flutter_banking_wrapper_sdk: ^1.0.0

Or from git:

dependencies:
  razorpay_flutter_banking_wrapper_sdk:
    git:
      url: https://github.com/razorpay/razorpay-flutter-banking-wrapper-sdk.git

Note for iOS: Set minimum deployment target to 15.0 or higher in your app's ios/Podfile: platform :ios, '15.0'. The native banking SDK is pulled automatically via CocoaPods when you run pod install (see iOS Setup below).

Note for Android: This plugin does not implement the banking payment flow on Android. Use the native Android Payment SDK for Android; the plugin will call onError with RzpPaymentError.platformUnsupported when running on Android.

Run flutter pub get in the root directory of your app.

iOS Setup

The native Banking Payment SDK is pulled automatically via CocoaPods when you install the plugin:

  1. Set platform :ios, '15.0' in your app's ios/Podfile.
  2. Run flutter pub get and cd ios && pod install.

No Xcode SPM or manual framework steps are required. The plugin depends on razorpay-banking-wrapper-sdk (and Checkout SDK), which CocoaPods installs for you.

Minimum iOS deployment target: 15.0

Usage

Sample code to integrate can be found in example/lib/main.dart.

Import package

import 'package:razorpay_flutter_banking_wrapper_sdk/razorpay_flutter_banking_wrapper_sdk.dart';

Create instance and initialize

final payment = RazorpayBankingPayment();

payment.initialize(
  showLoader: () {
    // Show loading indicator
  },
  hideLoader: () {
    // Hide loading indicator
  },
  onPaymentSuccess: (response) {
    // Payment succeeded — response contains post-payment data
  },
  onPaymentError: (error, response) {
    // Payment failed
    // Use error.code and error.description
    // On Android, error.code == RzpPaymentError.platformUnsupported
  },
);

Start payment

payment.open({
  'config_type': 'NTRP_PAYMENT',
  'ep': 'prod',
  'data': {
    'merchIdVal': '...',
    'encrequestparameter': '...',
    'reqdigitalsignature': '...',
    'bank': '...',
    'authKey': '...',
  },
});

Dispose

payment.dispose();  // Call from your widget's dispose()

API

RazorpayBankingPayment

initialize(...)

Registers callbacks. Must be called before open. All callbacks are optional.

  • showLoader: Called when the SDK wants to show a loader.
  • hideLoader: Called when the SDK wants to hide the loader.
  • onPaymentSuccess: Called when payment succeeds; receives the response map.
  • onPaymentError: Called when payment fails or on unsupported platform (Android); receives RzpPaymentError and optional response map.

open(Map<String, dynamic> config)

Opens the payment flow with the given config. On Android, does not call the native layer; instead invokes onPaymentError with RzpPaymentError.platformUnsupported.

dispose()

Cleans up resources. Call from your widget's dispose().

RzpPaymentError

Property Type Description
code int Error code. Use RzpPaymentError.platformUnsupported (-1) for unsupported platform (e.g. Android).
description String Human-readable error description

Config map

Key Type Required Description
config_type String Yes Payment flow type (e.g. "NTRP_PAYMENT")
ep String Yes Environment: "prod", "dev", or "uat"
data Map Yes Payment-specific data (merchIdVal, authKey, etc.)

E2E flow (example app → Dart → bridge → native)

Layer Class / component Role
Example app PaymentScreen (e.g. example/lib/main.dart) Creates RazorpayBankingPayment(), calls initialize(showLoader, hideLoader, onPaymentSuccess, onPaymentError), then open(config) on button tap. Handles callbacks to update UI and log.
Dart plugin RazorpayBankingPayment (lib/razorpay_flutter_banking_wrapper_sdk.dart) Holds callbacks from initialize. open(config) invokes method channel 'startPayment' with config. Sets MethodChannel('razorpay_flutter_banking').setMethodCallHandler to receive native events.
Bridge MethodChannel('razorpay_flutter_banking') Flutter → Native: method startPayment, args = config map. Native → Flutter: methods showLoader, hideLoader, onSuccess, onError (with args).
iOS plugin SwiftRazorpayBankingPlugin (ios/Classes/SwiftRazorpayBankingPlugin.swift) Handles startPayment, gets top VC, creates RazorpayPayment.initialize(delegate: self), calls razorpayPayment?.open(options: config, displayVC: topVC). Implements RazorpayPaymentDelegate: forwards showLoader, hideLoader, onPaymentSuccess, onPaymentFail back over the channel.
iOS native SDK RazorpayPayment + RazorpayPaymentDelegate (Checkout Bank Facade) open(options:displayVC:) parses config, runs payment flow (pre API → checkout UI → post API), calls delegate for loader and success/fail.

Callback names are aligned across stacks: showLoader / hideLoader / onPaymentSuccess / onPaymentError (Flutter) map to showLoader / hideLoader / onPaymentSuccess / onPaymentFail (iOS delegate); the bridge uses onSuccess and onError as method names for native→Flutter only.


Method checklist (Flutter ↔ bridge ↔ iOS native)

Use this to verify that the Flutter plugin and iOS bridge match the native SDK.

Flutter (Dart) Method channel (name) iOS plugin (Swift) iOS native SDK (RazorpayPaymentDelegate)
initialize(showLoader:, hideLoader:, onPaymentSuccess:, onPaymentError:) Registers handler for channel events Delegate set on RazorpayPayment.initialize(delegate:)
open(config) Invokes startPayment with config map Handles startPayment, calls RazorpayPayment.open(options:displayVC:) open(options:displayVC:)
Receives showLoader (no args) showLoader()channel.invokeMethod("showLoader", nil) showLoader()
Receives hideLoader (no args) hideLoader()channel.invokeMethod("hideLoader", nil) hideLoader()
Receives onSuccess (args: response map) onPaymentSuccess(paymentData:)channel.invokeMethod("onSuccess", paymentData.getData()) onPaymentSuccess(paymentData:)
Receives onError (args: code, description, response?) onPaymentFail(code:response:paymentData:)channel.invokeMethod("onError", ["code", "description", "response"]) onPaymentFail(code:response:paymentData:)
dispose()

Types: Config is Map<String, dynamic> (Dart) / [String: Any] (Swift). Success/error response is Map<String, dynamic>? (Dart) / [String: Any]? from PaymentData.getData() (Swift).


Summary of changes

  • Single entry point: Removed startPayment; public API to start payment is open(config) only (aligned with iOS open(options:displayVC:) and Android open(config)).
  • Initialize callbacks: Example and README use the same parameter names as the Dart API: showLoader, hideLoader, onPaymentSuccess, onPaymentError (replacing previous onShowLoader, onHideLoader, onSuccess, onError in docs/example).
  • Example app: Calls _payment.open(config), and initialize(showLoader: ..., hideLoader: ..., onPaymentSuccess: ..., onPaymentError: ...) so it compiles and matches the plugin and README.

Run iOS example app

From the example directory (iOS native SDK is pulled via CocoaPods when you run pod install):

# 1. Resync: get dependencies and install iOS pods
cd example
flutter pub get
cd ios && pod install && cd ..

# 2. Run on iOS simulator or device
flutter run

Or run from Xcode for console logs (e.g. [CheckoutBankFacade] API request/response when using debug xcframework):

cd example
flutter pub get
cd ios && pod install && cd ..
open ios/Runner.xcworkspace
# Then in Xcode: select a simulator or device and press Run (▶)

To run on a specific iOS simulator:

cd example
flutter pub get
cd ios && pod install && cd ..
flutter run -d "iPhone 16"

Build IPA for installation on a physical iPhone

To create an IPA file you can install directly on an iPhone (e.g. via Xcode, Apple Configurator, or a link):

1. One-time: Code signing in Xcode

You need an Apple ID (free or paid developer account) and a Development Team set for the app:

  1. Open the example app in Xcode:
    cd example
    open ios/Runner.xcworkspace
    
  2. In Xcode: select the Runner project → Runner target → Signing & Capabilities.
  3. Check Automatically manage signing, then choose your Team (sign in with your Apple ID if needed).
  4. For Ad Hoc install on specific devices: in Apple Developer → Certificates, Identifiers & Profiles → Devices, register your iPhone(s). Then create an Ad Hoc provisioning profile for the App ID com.razorpay.flutterbanking.example and include those devices. In Xcode you can still use “Automatically manage signing” and choose a profile if needed.

2. Build the IPA

From the example directory:

cd example
flutter build ipa --export-method ad-hoc
  • Ad Hoc (ad-hoc): install on registered devices only. IPA path:
    • build/ios/ipa/razorpay_flutter_banking_wrapper_sdk_example.ipa (or similar under build/ios/ipa/).
  • For App Store / TestFlight use:
    flutter build ipa
    
    (no --export-method; uses App Store distribution.)

3. Install the IPA on your iPhone

  • Xcode: Window → Devices and Simulators → select your iPhone → drag the .ipa into the “Installed Apps” area (or use the + button and choose the IPA).
  • Apple Configurator 2: Add the app and assign it to the device.
  • Over the air: Upload the IPA to a service like Diawi and open the link on the iPhone (device must be in your Ad Hoc profile).

If you see “No valid code signing certificates were found”, complete step 1 (Team and signing) in Xcode first, then run the flutter build ipa command again.