#pingu-vevo_3ds-ios-server-side

1 messages · Page 1 of 1 (latest)

next gyroBOT
#

👋 Welcome to your new thread!

⏲️ We'll be here soon! Typically we respond in a few minutes, but sometimes we might take a bit longer if the server is busy or if you have a particularly tricky question.

⏱️ We close idle threads, which makes them read-only. Once a thread is closed it won't be reopened, but you can always start a new thread if you have another question.

🔗 This thread will always be available, even after it's closed. You can find it again using Discord's search, or you can save this link: https://discord.com/channels/841573134531821608/1304188668000473088

📝 Have more to share? Add more details, code, screenshots, videos, etc. below.

twilit sinewBOT
crisp pollen
#

Hi there 👋 I'm pretty sure your server doesn't need to do anything different for the payment sheet to handle surfacing a 3DS challenge if required, I'm pretty sure the Payment Sheet handles that by default.

The only thing coming to mind that may play a factor there, is having a return URL setup.

What behavior are you seeing in your flow if you use one of our 3DS test cards?

past hawk
#

Hi Toby! Thanks for chatting with me. I'm wondering if the Payment Element itself is polling the server for the status of the payment intent and making 3DS happen, or is 3DS being triggered by a server error sent down?

#

This is what I'm seeing right now. j

#

Our endpoint to purchase returns an error JSON that we format like this:

{
  "object": "error",
  "type": "api_error",
  "message": "Please try again later. If you continue to have issues, please contact customer service (https://support.tokentransit.com).",
  "code": "stripe_requires_action",
  "continuation_token": "eyJ0eXBlIjoicHVyY2hhc2UiLCJwdXJjaGFzZV9hY3Rpb24iOnsib3JkZXJfaWQiOiJVajlUSXVWX1R1LWJibC0zQktXOFdnIn19"
}

I'm wondering if there's anything we can do to cause this error to trigger 3DS

crisp pollen
#

Hm, that's an error you're returning? In response to what kind of call?

I'm a little surprised because the Payment Sheet handles 3DS automatically:

PaymentSheet and PaymentSheet.FlowController automatically support 3DS authentication. If you’re using one of these classes, this guide doesn’t apply.
https://docs.stripe.com/payments/3d-secure/authentication-flow#when-to-use-3d-secure:~:text=PaymentSheet and PaymentSheet.FlowController automatically support 3DS authentication. If you’re using one of these classes%2C this guide doesn’t apply

So I'm trying to get my bearings and understand you flow a bit better.

Integrate 3D Secure (3DS) into your checkout flow.

past hawk
#

Yeah, so we make a call to an endpoint /purchase, which attempts to make a purchase call to Stripe and then if it fails, it returns this error.

#

We have our own API that we maintain with our own kind of errors, so I want to see if I massage my error into a Stripe error message, I'll trigger the 3DS payment flow. Maybe something like this:

            switch result {
            case let .failure(error):
                if let error = error as? TokenTransitAPIClient.APIError, error.code == .stripeRequiresAction {
                    // Massage the error into a Stripe error message
                }
                self?.purchaseIdempotencyKey = UUID()
                intentCreationCallback(.failure(error))
            case .success():
                intentCreationCallback(.success(secret))
            }
crisp pollen
#

I'm not sure I'm following. The Payment Sheet is intended to be used with our APIs. How are you using the Payment Sheet, and for what, if you're making calls to your own API instead?

past hawk
#

We have an endpoint /purchase that makes a call to Stripe (similar to the example in this guide. Our client calls this endpoint and if the 3DS card is used, we return an error stripe_requires_action.

crisp pollen
#

Are you using the PaymentSheet or PaymentSheet.FlowController approach?

past hawk
#

PaymentSheet

crisp pollen
past hawk
#

Ooh I see. Thank you!

#

Let me play around with this.

next gyroBOT
#

pingu-vevo_3ds-ios-server-side

past hawk
#

Hmmm, now I'm getting a concurrency error when I try to special-case the requiresAction error and resume the purchase:

            switch result {
            case let .failure(error):
                if let error = error as? TokenTransitAPIClient.APIError, error.code == .stripeRequiresAction {
                    // Continue as if it succeeded to trigger required action
                   intentCreationCallback(.success(secret))
                }
                self?.purchaseIdempotencyKey = UUID()
                intentCreationCallback(.failure(error))
            case .success():
                intentCreationCallback(.success(secret))
            }

So now, I get an error:

Thread 26: Fatal error: SWIFT TASK CONTINUATION MISUSE: fetchIntentClientSecretFromMerchant(intentConfig:paymentMethod:shouldSavePaymentMethod:) tried to resume its continuation more than once, throwing API Error code: stripe_requires_action, message: Please try again later. If you continue to have issues, please contact customer service (https://support.tokentransit.com).!

Any idea what's happening here?

next stream
#

Hello! I'm taking over and catching up...

past hawk
#

Hi! Thanks for jumping on 🙂

next stream
#

I think it's because you're calling intentCreationCallback more than once. If it requires action you shouldn't call it twice like you're doing now.

past hawk
#

omg i forgot to return

#

trying now hang tight

#

AMAZING. We're cooking with gas here.

#

Thank you SO MUCH.