Laravel cashier stripe issue with 3d secure cards not redirection to confirmation page

1.4k Views Asked by At

Im struggling to get a Laravel Cashier Strip integration to work with 3d secure cards. I have go it setup so subscription works and is showing up in my stripe dashboard and everything it getting to my local database. But when I test with cards that needs strong authntication as 3ds they get the status of incomplete in my stripe dashboard.

I get the cashier.payment response page in my console log. but isn't Cashier supposed to redirect to this confirmation window?

My code is as follows

In my subscription controller i have

public function index() {

    $data = [
        'intent' => auth()->user()->createSetupIntent(),
        // 'plans' => $available_plans
    ];

    return view('artists.subscription')->with($data);
}

public function checkout(Request $request) {
    $user = auth()->user();
    $paymentMethod = $request->payment_method;
    $planId = 'monthly_sub';

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

    // return response(['status' => 'Success']);
}

and in my stripe js file I have this

const stripe = Stripe('stripe_key'); // i have my test key here
const elements = stripe.elements();
const cardElement = elements.create('card',{hidePostalCode: true});
cardElement.mount('#card-element');
const cardHolderName = document.getElementById('card-holder-name');
const cardButton = document.getElementById('card-button');
const clientSecret = cardButton.dataset.secret;

cardButton.addEventListener('click', async (e) => {
    const { setupIntent, error } = await stripe.confirmCardSetup(
        clientSecret, {
            payment_method: {
                card: cardElement,
                billing_details: { name: cardHolderName.value }
            }
        }
    );


    axios.post('checkout', {
      payment_method: setupIntent.payment_method
    }).then(response => { 
      console.log(response.request.responseURL)
   })
   .catch(error => {
     console.log(error.response)
   });

});

My blade view is

@extends('layouts.app')

@section('head')
@php 
// dd($intent);
@endphp
<script src="https://js.stripe.com/v3/"></script>
<link href="{{ asset('css/stripe.css') }}" rel="stylesheet">
@endsection

@section('content')

<input id="card-holder-name" type="text">

<!-- Stripe Elements Placeholder -->
<div id="card-element"></div>

<button id="card-button" data-secret="{{ $intent->client_secret }}">
    subscribe
</button>

@endsection

@section('js')

  <script src="{{ asset('js/stripe.js') }}" type="text/javascript"></script>
@endsection

Everything seems to be working but I just get the 3ds confirmation page as a response in my console. How do I get laravel to redirect and open that page for the user?

1

There are 1 best solutions below

3
v3nkman On

I think the issue is the order of events, your code should wait for 3DS to be called and completed before calling back to your code after the result is handed back to you. Using this regulator card [1] you should be able to test that with some small changes like this (I had to remove some things but this should be a reference):

stripe.confirmCardSetup(
  "seti_xxx", {
    payment_method: {
      card: card,
      billing_details: { name: "Name" }
    }
  }).then(function(result) {
      // Check the result status here!!

      axios.post('checkout', {
        payment_method: result.setupIntent.payment_method
      }).then(response => { 
        console.log(response.request.responseURL)
      }).catch(error => {
       console.log(error.response)
     });    
    });

Hope this helps!

[1] https://stripe.com/docs/testing#regulatory-cards