stripe / stripe-ios

Stripe iOS SDK
https://stripe.com
MIT License
2.09k stars 975 forks source link

Apple Pay payments failing because of (probably) 3D Secure v2 #1774

Closed glaures-ioki closed 3 years ago

glaures-ioki commented 3 years ago

Summary

First of all, a little bit of context: we are a ride hailing app so we are saving the Apple Pay payment method for later use (to charge when the customer is dropped off) so we use confirmSetupIntent to setup the payment method even for Apple Pay.

We noticed that some payments with Apple Pay are failing and started investigating them. It seems that when calling confirmSetupIntent, even though Apple Pay is already strongly authenticated, when the answer is received in STPPaymentHandler: aRes.isChallengeRequired is returning true.

So then it tries to present the web view to authenticate the card, but since this is Apple Pay, the _canPresent(with authenticationContext: STPAuthenticationContext, error: inout NSError?) method is always returning false. Which makes the payment to fail.

In addition, I noticed that you have this test in _canPresent:

// Is it the Apple Pay VC?
if presentingViewController is PKPaymentAuthorizationViewController {
  // Trying to present over the Apple Pay sheet silently fails. Authentication should never happen if you're paying with Apple Pay.
  canPresent = false
  errorMessage =
    "authenticationPresentingViewController is a PKPaymentAuthorizationViewController, which cannot be presented over."
}

but it does not go in there because PKPaymentAuthorizationViewController is not the presentingViewController but the presentingViewController.presentedViewController So in the end it goes in the following one:

// Is it already presenting something?
if presentingViewController.presentedViewController != nil {
  canPresent = false
  errorMessage =
    "authenticationPresentingViewController is already presenting. You should probably dismiss the presented view controller in `prepareAuthenticationContextForPresentation`."
}

Code to reproduce

The whole payment handling is not open source but if you need more info, feel free to ask.

iOS version

14.4.1

Installation method

Carthage

SDK version

21.2.1

Other information

I can always reproduce this issue with a N26 card. If you need more info, feel free to ask.

davidme-stripe commented 3 years ago

Hi @glaures-ioki,

Thanks for tracking down the client-side bug! We'll fix it in a future update.

The SDK shouldn't get into this state to begin with — purchases made with Apple Pay don't require additional authentication, and any attempt to present a 3DS2 challenge is likely a service-side issue. We'll investigate. If you can email me (davidme@stripe.com) an impacted PaymentIntent's stripeId, that would help us track it down. Thanks!

davidme-stripe commented 3 years ago

We resolved the service-level issue. I'll leave this open to track the client-side error handling fix.

yuki-stripe commented 3 years ago

Looks like we've already removed the apple pay check in _canPresent; the error that is vended in this case is appropriate imo.