4

I've integrated stipe payment into a Flutter (using this plugin https://pub.dev/packages/stripe_payment) app and it all works fine except for the fact that stripe's 3d secure safari view controller is never closed after the payment is complete so the users must always close it by hand which is not too good

In my AppDelegate.swift I've implemented an application method override like so

override func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
        
        if (url.absoluteString.contains("stripe")) {
            /// this code works and I see in in console
            print("STRIPE CALLBACK WORKED");
            return true;
        }
        return false
    }

I've also added a deep link to be called by safari when the job is done

var paymentIntentResult = await StripePayment.confirmPaymentIntent(
  PaymentIntent(
    clientSecret: clientSecret,
    paymentMethodId: paymentMethodId,
    returnURL: 'mycoolapp://stripe-redirect',
  ),
);

and indeed the link is called, I can clearly see "STRIPE CALLBACK WORKED" output in xcode's console. So the question is why doesn't the sfsafariviewcontroller close and the process does not return to the Flutter app by itself?

Instead I see this window enter image description here

I even tried to remove it by hand using different hacks, like this for example

func popAfterDelay(view uiViewController:UIViewController?) {
    print("POP AFTER DELAY CALLED")
    DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
        if (uiViewController is SFSafariViewController) {
            print("DISMISS SAFARY VIEW..........")
            let safariController = uiViewController as? SFSafariViewController;
            safariController?.removeFromParent()
        }
    }
}

override func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
    if (url.absoluteString.contains("stripe")) {
        let curView = ViewUtils.getCurrentViewController();
        if (curView != nil) {
            popAfterDelay(view: curView)
        }
        return true;
    }
    return false
}

I could see "DISMISS SAFARY VIEW.........." output but to no avail. I'm completely stuck with this. Any help would be highly appreciated

Konstantin
  • 1,150
  • 13
  • 31
  • Have you tried calling [`dismiss(animated:completion:)`](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621505-dismiss) on the `SFSafariViewController` instance? – Justin Michael Dec 26 '20 at 22:17
  • 1
    Yep. It brings yet another problem. Flutter never receives a result of a previous route and it remains hanging somewhere – Konstantin Dec 27 '20 at 14:13
  • I haven't found a solution to this yet but I suppose this problem is related to the plugin itself – Konstantin Dec 27 '20 at 14:14
  • The redirect flow should be handled by the Stripe iOS SDK, including dismissing the Safari View Controller, but it sounds like something in the plugin and/or in your project is overriding that behavior. If you can figure out why [the code that would normally dismiss the Safari View Controller](https://github.com/stripe/stripe-ios/blob/a05b307c8a9ef6ee6c53726da2392073b5292f19/Stripe/STPRedirectContext.swift#L521-L527) isn't being called maybe you can figure out a solution. – Justin Michael Dec 27 '20 at 20:47
  • 1
    In my project nothing overrides it but maybe something is wrong in the plugin. Unfortunately I'm not that good in objective c to understand what exactly is going on there. I've made a ticket in the author's repository for it but it seems like I'll still have to fork it an fix the problem myself – Konstantin Dec 28 '20 at 23:21
  • 1
    Hello Did you find the solution for this? – Gaurav Oct 22 '21 at 13:57
  • 1
    Hi, unfortunately not. But the guys from stripe have implemented the official flutter plugin which works differently – Konstantin Nov 26 '21 at 04:26

0 Answers0