0

Context:

  • Laravel 5.5 Stripe Payment Form with cartalyst/stripe
  • BookingController return the view with the PaymentIntent associated with the logged in user.

If the user use the mouse to click "PAY" all is working fine (error check and successful payment). But when he clicks enter on the keyboard the form is submitted also with empty values.

To avoid fake booking the store function on the controller look like this:

public function store(CreditCardRequest $request)
{

    if ($request->payment_method == null) {
        // Empty Card
        return back()->withErrors('empty card')->withInput();
    }

    // ok, process booking
    ...
}

But I would like to stop this on front end also so I tried this but is not working at all. I can't figure it out.

Blade

 {!! Form::open(array('url' => url('/booking'), 'method' => 'post', 'id' => 'payment-form')) !!}
    <script src="https://js.stripe.com/v3/"></script>
    {{ Form::hidden('payment_method', '', array('id' => 'payment-method')) }}
    {{ Form::hidden('payment_intent', $pay_intent['id'])}}
    {{ Form::hidden('pax', $pax) }}
    <div class="row col-md-8">
        <h4>{{$pay_intent['id']}}</h4>
        <div class="field">
          <label for="card-number">card number</label>
          <div id="card-number" class="form-control input empty"></div>
          <div class="baseline"></div>
        </div>
        <div class="field half-width">
          <label for="card-expiry">Expire</label>
          <div id="card-expiry" class="form-control input empty"></div>
          <div class="baseline"></div>
        </div>
        <div class="field half-width">
          <label for="card-cvc">CVC</label>
          <div id="card-cvc" class="form-control input empty"></div>
          <div class="baseline"></div>
        </div>
      </div>
      <button type="button" class="mt-5 btn btn-md btn-success" id="payment-button">PAY</button>
      @if (session('error'))
        <div class="alert alert-danger mt-4">{{ session('error') }}</div>
      @endif
      <div class="d-none alert alert-danger mt-4" style="display:none;" id="card-error"></div>
{!! Form::close() !!}

Stripe JS on submit

$('#payment-button').on('click', function() {
    $('#payment-button').attr('disabled', true);

    stripe
        .confirmCardPayment('{{$pay_intent['client_secret']}}', {
            payment_method: {
                card: cardNumber,
            },
        })
        .then(function(result) {
            if (result.error) {
                $('#card-error').text(result.error.message).removeClass('d-none');
                $('#card-error').css('display', 'block');
                $('#payment-button').attr('disabled', false);
            } else {
                $('#payment-method').val(result.paymentIntent.payment_method);
                $('#payment-form').submit();
            }
        });
})
Atomos
  • 17
  • 6

1 Answers1

2

Grab your form, listen for submit and prevent the default action

$('#payment-form').on('submit', function(e) {
    e.preventDefault()
    
   $('#payment-button').attr('disabled', true);

    stripe
        .confirmCardPayment('{{$pay_intent['client_secret']}}', {
        ...

    .then(function(result) {
            if (result.error) {
                $('#card-error').text(result.error.message).removeClass('d-none');
                $('#card-error').css('display', 'block');
                $('#payment-button').attr('disabled', false);
            } else {
                $('#payment-method').val(result.paymentIntent.payment_method);
// After succesful validation remove the event listener and submit the form
                $('#payment-form').off('submit');
                $('#payment-form').submit();
            }
        });
})
NICO
  • 1,695
  • 1
  • 12
  • 11
  • Thanks NICO, tried both and they managed to prevent the form from being submitted, but they actually made the form unsendable at all, I can no longer process the payment. – Atomos May 08 '21 at 13:06
  • Ah yes, just saw you actually want to submit your form. Thought you just want to make the ajax request. Updated the answer. – NICO May 09 '21 at 09:51