Skip to content

Can't open Razorpay in mixed React Native & Flutter Project [iOS] #461

@sriharsha-y

Description

@sriharsha-y

Description

We have our shell app with react native and some of of our features / screens are in flutter.
We invoke flutter view controller which is presented when user starts a flutter journey.
In one of our flutter journeys we are using razorpay-flutter and we wanted to present razorpay screen on click of a button.
When we tried to click nothing happens and we don't see razorpay screen presented. From console app logs we saw we were getting Attempt to present <UINavigationController: 0x137267000> on <UIViewController: 0x109d0d4d0> (from <UIViewController: 0x109d0d4d0>) which is already presenting <FlutterViewController: 0x137264600>

Which i think is related to same issue as here razorpay/razorpay-pod#38
especially this comment razorpay/razorpay-pod#38 (comment) where it is mentioned how the native pod behaves.

It was clear from this that underlying react native was not using UINavigationController and Razorpay is trying to present from underlying React Native View Controller which is already presenting Flutter view controller which is causing the issue. To make this work we have made patch to razorpay-flutter to query and send the top most view controller instead of root view controller to native pod like below

public func open(options: Dictionary<String, Any>, result: @escaping FlutterResult) {
        
        self.pendingResult = result
        
        let key = options["key"] as? String
        
        let razorpay = RazorpayCheckout.initWithKey(key ?? "", andDelegateWithData: self)
        razorpay.setExternalWalletSelectionDelegate(self)
        var options = options
        options["integration"] = "flutter"
        options["FRAMEWORK"] = "flutter"
        if let presentingVC = Self.getTopMostViewController() {
            razorpay.open(options, displayController: presentingVC)
            return
        }
        razorpay.open(options)
    }

static func getTopMostViewController() -> UIViewController? {
        guard let rootVC = UIApplication.shared.windows.filter({ $0.isKeyWindow }).first?.rootViewController else {
            return nil
        }
        
        return getTopMostViewController(base: rootVC)
    }

    static func getTopMostViewController(base: UIViewController?) -> UIViewController? {
        if let presented = base?.presentedViewController {
            return getTopMostViewController(base: presented)
        }
        if let nav = base as? UINavigationController {
            return getTopMostViewController(base: nav.visibleViewController)
        }
        if let tab = base as? UITabBarController {
            return getTopMostViewController(base: tab.selectedViewController)
        }
        return base
    }

After this everything started to work since the native razorpay pod accepts additional displayController argument while opening razorpay.

My question is, will it be possible for razorpay-flutter to make this fix ?
Since this is a valid case as like ours at least i think there should be some provision to let the integrating apps decide on which view controller razorpay needs to present.

Flutter Version :

3.29.0

Xcode Version :

16.2

Cocoapod Version :

1.14.3

razorpay-flutter :

1.4.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions