React-stripe-elements: Using card 4000000000003063 does not trigger SCA modal

Created on 7 Aug 2019  ยท  22Comments  ยท  Source: stripe/react-stripe-elements

As mentioned in the stripe docs (https://stripe.com/docs/payments/3d-secure#three-ds-cards), using this card should trigger the SCA modal but it does not:

Screen Shot 2019-08-07 at 09 01 45

However the card is added successfully on the BE and FE of my app, its just not authenticated with SCA when its supposedly should.

What could be the issue?

Most helpful comment

@sverraest ooh interesting. To help us dig into this, could you please email me ([email protected]) with request ids or PaymentIntent ids so we can look at exactly what is happening? Thanks!

All 22 comments

Hi @GavBaros, sorry for the confusion, that sounds unfortunate. To help us dig in, can you tell us more about what your backend and frontend code is doing and what Stripe APIs you are calling?

Hey my FE code is exactly like first one i posted here: https://github.com/stripe/react-stripe-elements/issues/395

Its for saving a card off_session, the BE pretty much issues a client secret, then the FE passes handleCardSetup the secret as an argument, asynchronously receives a payment_method in response, then sends the payment_method to the BE as a payment_method_id.

Sorry as i cant really provide the exact BE logic today but can on Monday.

All other cards work fine, except for also card 4000008400001629, which does not fail the authentication for saving a card.

I'm having the same issue with using the paymentRequest button together with the new SCA flow using handleCardPayment.

The test card is added to Chrome, the button shows up and after payment using card 3063 nothing happens. I do see the async response and also in the events I see that the paymentIntent now requires a next action but no modal is shown like when I just use a card form.

If I then retry with the 4242 card it just goes through immediately.

Using the latest Stripe React Elements and Stripe v3 JS

paymentRequest.on('paymentmethod', function(ev) {
      props.stripe.confirmPaymentIntent(props.clientSecret, {
        payment_method: ev.paymentMethod.id,
      }).then(function(confirmResult) {
        console.log(confirmResult)
        if (confirmResult.error) {
          // Report to the browser that the payment failed, prompting it to
          // re-show the payment interface, or show an error message and close
          // the payment interface.
          ev.complete('fail');
        } else {
          // Report to the browser that the confirmation was successful, prompting
          // it to close the browser payment method collection interface.
          ev.complete('success');
          // Let Stripe.js handle the rest of the payment flow.
          props.stripe.handleCardPayment(clientSecret).then(function(result) {
            if (result.error) {
              // The payment failed -- ask your customer for a new payment method.
            } else {
              // The payment has succeeded.
            }
          });
        }
      });
    });

Using the exact same code snippet as on the docs.
confirmResult is a correct paymentIntent object without errors and with a next_action but nothing shows.

This does work with a normal card form but not with the paymentRequest button and Google Pay / Apple Pay

EDIT:
I've did some more testing with different cards but the SCA or 3DS modal never pops up when using paymentIntents + paymentRequest button.

Test case: paymentIntent using confirm_method: automatic but confirm not set to true.

Google Pay Card 4242: Goes through, payment intent succeeds and charge automatically created, fulfilled using webhook

Google Pay Card โ 3220โ€ฌ: Goes through, payment intent confirm succeeds, has next action use_stripe_sdk with cryptographic tokens, no 3ds url, nothing happens

Google Pay Card 3181: Goes through, payment intent confirm succeeds, has next action use_stripe_sdk with 3ds hooks.stripe.com URL, nothing happens.

I guess for 3220 I will need to listen to the paymentIntent succeeds event and confirm on the server? Or should I create the paymentIntent with confirm:true?

Shouldn't the modal open automatically for card ending in 3181?

Any ideas what might cause the SCA modal not to appear and have the PaymentIntent remain as incomplete?

I think there are two separate issues in this thread.

@GavBaros: It is expected that "3063" does not perform 3DS when using SetupIntents. This card has been around for a while and mimics the behavior of a bank which has decided to require 3DS on all _payments_. This is somewhat different from SCA rules. In particular, because a SetupIntent does not actually perform a payment, Stripe would not know that the bank requires 3DS and would not perform it. If you then attempt to make a payment with this card, 3DS should be required. If you want to test what it looks like when SCA rules require Stripe to perform 3DS just to save a card, you should use one of our regulatory test cards.

@sverraest: I think you want to call handleCardPayment where you currently call confirmPaymentIntent. (handleCardPayment does a confirm, and then also carries out the actions like 3DS if needed). When you call handleCardPayment, you will want to pass in the payment_method parameter just like you are now to confirmPaymentIntent. (Right now, when you call handleCardPayment, that is re-confirming the PaymentIntent but not sending the payment_method that was gathered from the Payment Request button, which is why it isn't working.)

@asolove-stripe That indeed did the trick, it's a bit strange why it's not documented like that (using exact code snippet from the docs).
Unfortunately this also brings up another issue. The SCA modal is now blocked and hidden behind the browser popup. I've raised another issue for this here: https://github.com/stripe/react-stripe-elements/issues/406

if i'm using direct payment without scheduled payment ? and using both "CardElement" and "PaymentRequestButtonElement" should i need to edit my code to include the SCA ?

if so can anyone give me a link or example on how to implement it please

@sverraest: Oh my, I'm so sorry, I forgot about that! You're right, you want to follow the code in that doc. For this case, I think the change you want is to make sure you pass the payment_method to handleCardPayment, the same way you do to confirmPaymentIntent. We will update that doc to reflect this.

Hello @asolove-stripe.
So, we cannot use 3063 card for recurring subscriptions, correct, as it will require 3ds check which cannot be completed?

@joesalloum: can you tell us a little more about what your integration currently does? If you do not yet use the PaymentIntent API, you will need to make changes to the backend portion of your integration. We have some great SCA docs that can help you identify what your integration currently does, which bits might need to change for SCA, and how to start planning your migration.

@Mookker: a lot depends on how your subscription processing works. Are you using Stripe Billing? Do you have your own recurring billing logic? You probably want to start from our SCA migration guide to learn about making sure whatever recurring logic you do is SCA-safe.

@asolove-stripe. Yes, we're using Stripe Billing, and don't have own recurring billing logic.
I've checked the guide and implemented it using SetupIntents, which works perfectly, except case with 3063, as it doesn't generate hosted invoice page. So, I'm not sure, if this card is valid at all for our solution?

@Mookker: yeah, I think you want to test using our "SCA regulatory" card (ending in 3155) rather than the 3DS-required one. The 3155 card will correctly allow you to skip 3DS if you perform an initial SetupIntent on it.

@asolove-stripe, thanks 3155 really works. Nice just considering 3063, as 3220 also works fine, and it has the same description as 3063, but for 3ds2

@asolove-stripe Thanks for that, we have changed it back, flows work but in the end we still get an error.

We see that calling confirmPaymentIntent and then calling handleCardPayment like in the docs causes two requests to the confirm endpoint.

The second one returns a 400 payment_intent_unexpected_state and even though the payment went through the first time an error is triggered because of that 400 response.

@sverraest ooh interesting. To help us dig into this, could you please email me ([email protected]) with request ids or PaymentIntent ids so we can look at exactly what is happening? Thanks!

@joesalloum: can you tell us a little more about what your integration currently does? If you do not yet use the PaymentIntent API, you will need to make changes to the backend portion of your integration. We have some great SCA docs that can help you identify what your integration currently does, which bits might need to change for SCA, and how to start planning your migration.

@asolove-stripe i developed a website, you select a product in a box inside the taxi, you pay for it "one time payment" and when you successfully pay the driver give it to you

i read about the SCA and i figured that it's necessary if you have subscriptions or you pay HUGE amount, that's why i'm asking the question

@joesalloum: yep, all businesses that operate in Europe and sell to customers in Europe will need to meet new SCA requirements. Our SCA docs page can walk you through how to start doing that.

@asolove-stripe Getting below error when using the card ( 4000000000003063)

"message": "The payment attempt failed because of an invalid payment method.",

No SCA Modal opening.
3155 card is working fine.

The function used to trigger subscription is below

$user->newSubscription('main', $plan->stripe_plan)->withMetadata(['kroit' => $kroit])->create($request->stripePaymentMethod);

It's getting created as an Incomplete subscription.

JS side

    this.stripe.handleCardSetup(this.clientSecret, this.card, {
        payment_method_data: {
            billing_details: {name: cardHolderName.value}
        }
    }).then(function (result) {
        if (result.error) {
            self.cardError = result.error.message;
        } else {
            console.log(result);
            self.handleSubscription(result.setupIntent.payment_method);
        }
    });

Using Laravel Cashier ( latest )

@mujeebu did you fix this problem?

@dmarczydlo It will work fine in live mode.

Closing this as this project has migrated to React Stripe.js. If you believe this is still important, please re-open it there.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Dasyel picture Dasyel  ยท  4Comments

alenadrex picture alenadrex  ยท  3Comments

sciku1 picture sciku1  ยท  4Comments

cleemputc picture cleemputc  ยท  5Comments

kavsingh picture kavsingh  ยท  4Comments