BlissSol
BlissSol

Reputation: 418

Bootstrap website payments with Stripe

I'm completely new to using Stripe for payments, and as it's a Bootstrap site & I'm using Stripe.js v2.

From my understanding of how Stripe works, my HTML form needs to initially communicate with Stripe with the credit card num, cvc & expirary using Javascript, which will return a token (or an error) - and I then submit this token, and other payment information like the amount etc.. to the PHP script on my Server (which then sends this Stripe).

My problem is, my JavaScript is never executed first - and instead my page tries to run submit.php first.

What should I do to correct this - and have my JavaScript create the token, and then have the token passed to my submit.php code?

*Note - my HTML form does contain more than what's listed here (such as asking the user for Name, Address, State, Phone, Amount etc), but i shortened it, so it was easier to read.

HTML Code:

<form action="/PHP/submit.php" method="POST" class="contact-form" id="payment-form">
<div id="creditcard">
  <span class="payment-errors"></span>
    <div class="form-group has-feedback row">
      <label for="cardnumber" class="col-sm-2 form-control-sm">Card Number:</label>
        <div class="col-sm-5">
                        <!--<input type="text" autocomplete="off" class="form-control form-control-sm card-number" value="" pattern="[0-9]{10}" data-stripe="number">-->
                        <input type="text" autocomplete="off" class="form-control form-control-sm card-number" data-stripe="number">
                      </div>
                      <label for="cvc" class="col-sm-1 form-control-sm">CVC:</label>
                      <div class="col-sm-4">
                        <!--<input type="text" autocomplete="off" class="form-control form-control-sm card-cvc" maxlength="3" value="" pattern="[0-9]{3}" data-stripe="cvc">-->
                        <input type="text" autocomplete="off" class="form-control form-control-sm card-cvc" data-stripe="cvc">
                      </div>
                    </div>
                    <div class="form-group has-feedback row">
                        <label for="expiration" class="col-sm-2 form-control-sm">Expiration Date </label>
                        <div class="col-sm-2">
                          <select class="card-expiry-month form-control form-control-sm" data-stripe="exp-month">
                            <option value="01" selected>01</option>
                            <option value="02">02</option>
                            <option value="03">03</option>
                            <option value="04">04</option>
                            <option value="05">05</option>
                            <option value="06">06</option>
                            <option value="07">07</option>
                            <option value="08">08</option>
                            <option value="09">09</option>
                            <option value="10">10</option>
                            <option value="11">11</option>
                            <option value="12">12</option>
                          </select>
                        </div>
                        <div class="col-sm-2">
                          <select class="card-expiry-year form-control form-control-sm" data-stripe="exp-year">
                            <option value="2018" selected>2018</option>
                            <option value="2019">2019</option>
                            <option value="2020">2020</option>
                            <option value="2021">2021</option>
                            <option value="2022">2022</option>
                            <option value="2023">2023</option>
                            <option value="2024">2024</option>
                            <option value="2025">2025</option>
                        </select>
                      </div>
                    </div>
                    <div class="form-group row">
                      <label for="cardname" class="col-sm-2 form-control-sm">Name on Card:</label>
                      <div class="col-sm-10">
                        <input type="text" class="form-control form-control-sm" autocomplete="off" name="cardname" id="cardname">
                      </div>
                    </div>
                    <div class="form-row form-submit">
                        <button type="submit" class="btn btn-default submit-button">Submit Donation</button>
                    </div>
                  </div>
                </form> 

And my Javascript:

<script src="https://js.stripe.com/v2/"></script>
    <script>
      (function() {
        Stripe.setPublishableKey('pk_test_xxxxx');
      })();
      </script>
    <script>
    $(document).ready(function() {
    $('#payment-form').on('submit', generateToken);

    var generateToken = function(e) {
      var form = $(this);

      //No pressing the buy now button more than Once
      form.find('button').prop('disabled', true);

      //Create the token, based on the form object
      Stripe.create(form, stripeResponseHandler);

      //Prevent the form from submitting
      e.preventDefault();
    });
  });

    var stripeResponseHandler = function(status, response) {
      var form = $('#payment-form');

      //Any validation errors?
      if (response.error) {
        form.find('.payment-errors').text(response.error.message);
        alert(result.error.message);
        //Make the submit button clickable again
        form.find('button').prop('disabled', false);
      } else {
        //Otherwise, we're good to go! Submit the form.
        //Insert the unique token into the form
        $('<input>', {
          'type': 'hidden',
          'name': 'stripeToken',
          'value': response.id
        }).appendTo(form);
        alert(result.token.id);
        //Call tge native submit method on the form
        //to keep the submission from being cancelled
        form.get(0).submit();
      }
    };
    </script>

Upvotes: 0

Views: 1144

Answers (2)

BlissSol
BlissSol

Reputation: 418

I ended up going a slightly different direction, using an 'onsubmit' event on the form, to trigger the javascript before the PHP;

<form action="/PHP/submit.php" method="POST" class="contact-form" id="payment-form" onsubmit="return onSubmitDo()">

I also completely changed the Javascript so it looked like this:

Stripe.setPublishableKey('pk_test_******');

function onSubmitDo () {

  Stripe.card.createToken( document.getElementById('payment-form'), myStripeResponseHandler );

  return false;

};
function myStripeResponseHandler ( status, response ) {

  console.log( status );
  console.log( response );

  if ( response.error ) {
    document.getElementById('payment-error').innerHTML = response.error.message;
  } else {
    var tokenInput = document.createElement("input");
    tokenInput.type = "hidden";
    tokenInput.name = "stripeToken";
    tokenInput.value = response.id;
    var paymentForm = document.getElementById('payment-form');
    paymentForm.appendChild(tokenInput);
    paymentForm.submit();
  }
     };

The actual javascript code I used here, i found on this github account which has some Stripe payment samples; https://github.com/wsmoak/stripe/blob/master/php/test-custom-form.html

Now the form just needs to integrate jquery.payment (to format & validate card details), and it should all be complete. https://github.com/stripe/jquery.payment

Upvotes: 0

Carol Skelly
Carol Skelly

Reputation: 362380

You should define the generateToken function before the $('#payment-form').on('submit', generateToken);. Otherwise the submit event has no handler, and e.preventDefault(); is never reached.

$(document).ready(function() {
    $('#payment-form').on('submit', generateToken);

    var generateToken = function(e) {
      var form = $(this);

      //No pressing the buy now button more than Once
      form.find('button').prop('disabled', true);

      //Create the token, based on the form object
      Stripe.create(form, stripeResponseHandler);

      //Prevent the form from submitting
      e.preventDefault();
    });
});

Demo: https://www.codeply.com/go/wRcqjxfVmf

Upvotes: 0

Related Questions