Laravel Cashier Incomplete Exception Handling for 3D Secure / SCA
Asked Answered
B

1

46

I'm currently trying to use Laravel Cashier to handle Billing inside a React application. When using a test card that requires 3D secure (pulled directly from Stripes Documentation) (4000000000003220), I get an IncompletePayment exception throw.

This is apparently normal as described in the documentation:https://laravel.com/docs/6.x/billing#payments-requiring-additional-confirmation

try {
    $subscription = $user->newSubscription('default', $planId)
                            ->create($paymentMethod);
} catch (IncompletePayment $exception) {
    return redirect()->route(
        'cashier.payment',
        [$exception->payment->id, 'redirect' => route('home')]
    );
}

Now, Laravel recommends that I forward to their 'confirm' page in that scenario. However, this is where my confusion lies. Firstly, I've already asked the customer for their credit card via Stripe Elements inside my React application, so forwarding to a server-side page generated from Laravel is probably going to be a hard NO. I'd like to handle this all gracefully inside my React Application.

enter image description here

I've also already confirmed that the card is valid against 3D secure via a popup like the above, prior to sending anything to the server (which Stripe Elements javascript has already handled for me) so the documentation stating:

On the payment confirmation page, the customer will be prompted to enter their credit card info again and perform any additional actions required by Stripe, such as "3D Secure" confirmation.

Seems like this would be a repetition in any case. Can anyone guide me what I need to do in this scenario? Loosely inside my React App I have the done the following:

Generated a server side intent, and fired it back to react: During the billing process:

stripe.confirmCardSetup(
            billingStatus.paymentIntent.client_secret,
            { 
              payment_method: {
                card: card,
                billing_details: {
                  name: 'Jenny Rosen'
                }
              }
            }
          )
            .then((res)=>{
              console.log(res);
              processPayment(  res );
            });

The process Payment method hits the server:

 var data = new FormData();
            data.append( "coreId", plan.id );
            data.append( "productId", plan.product_id );
            data.append( "planId", plan.stripe_plan_id );
            data.append( "paymentMethod", res.setupIntent.payment_method );

            billingApi.pay( data, function(res){
                BIG FAT 500 SERVER ERROR HERE. (IncompletePayment Exception)
            });

I came across an example issue on Github: https://github.com/laravel/cashier/issues/743 Which mirrors very closely my problem.

However, I'm running the latest version of Laravel and Cashier, and checked the line of code quoted in the closed solution is present (which it is) so there may be something else going on.

I'm a bit lost as to what the flow of control should look like to get this working for these types of cards. For standard cards that don't require 3DS, everything works fine. Should I be catching the Exception and handling things differently in React? e.g. Asking for the user to confirm their card details twice?

I should also mention that I have webhooks enabled, and these are resolving successfully locally - I checked in the dashboard.

Brittni answered 19/11, 2019 at 19:51 Comment(9)
did you try this solution? github.com/laravel/cashier/issues/743#issuecomment-525818592Barbel
@TouqeerShafi - that solution was merged into the core Laravel code base, but yes I've traced through the code and it is already in place.Brittni
Based on this answer github.com/laravel/cashier/issues/743#issuecomment-525817530 adding off_session => true to buildPayload fixes the issue.Verdha
@EyadJaabo - As previously stated, that fix has already been merged to Laravel Cashier, and as a result, is in place within my codebase.Brittni
Check this github.com/laravel/cashier/issues/848Officeholder
If you want you can use Laravel Checkout, it's very to easy to setup ;)Worshipful
@Worshipful - have you a link to this new package? I Googled Laravel Checkout and can't see any reference to it.Brittni
@Brittni laravel.com/docs/8.x/billing#checkoutWorshipful
Since it is supported and well documented, you might consider using the Stripe Web SDK (@stripe/react-stripe-js @stripe/stripe-js) directly in your React application to handle the 3D Secure flow, rather than relying on Laravel Cashier.Intyre
B
1

Since you are on React, you could use the Stripe React SDK https://stripe.com/docs/libraries/react-native

And use Laravel only for creating references and checking payment status.

This way you don't need to worry about creating 3D pages or doing any redirects.

Blanka answered 19/1 at 10:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.