In my previous post in this series, I covered how you create an HTML form for securely handling payments via Stripe. As explained in that post, thanks to the Stripe.js library, the proper HTML, and a bit of JavaScript, you can easily and securely handle payments on your site without getting mired in the PCI compliance muck. The secret is the Stripe.js library: it sends the customer’s payment information from the client to Stripe’s server and returns a token that Stripe associated with that payment information. Then, when the form is submitted, the token can be used by the PHP on your site to actually process the payment. The customer’s payment information, however, never touches your server. You get paid and the customer is protected.

In this post, I’ll walk through the necessary JavaScript to handle the client-side of that process. Note that this article assumes that you have read the previous article. And comfort with JavaScript and jQuery is required, too.

Recapping the Process

As previously explained, the Stripe payment process (when using the Stripe.js JavaScript library) works like so:

The customer loads an HTML form on your site. Let’s call that page buy.php.

The form does not use name attributes for the payment fields! This keeps the customer data from reaching your server (and therefore saving you lots of security headaches).

When the form is submitted, the payment information needs to be sent to Stripe via Ajax (i.e., JavaScript). This means that JavaScript must prevent the form’s actual submission.

Stripe will return a string of characters, called a token, that represents the payment information (assuming the payment information was valid).

The JavaScript that handles the Ajax request needs to store that token in the form as a hidden element. This makes the token available to the server-side code (the PHP) when the form is actually submitted.

The JavaScript that handles the Ajax request also needs to let the form submission go through (assuming there were no errors).

If any errors occurred, the JavaScript should report upon those and not submit the form.

When the form is submitted to the server, the server-side script will use the token to actually request that the payment be processed.

Steps 1-3 were discussed in the previous post. In this post, I’ll provide and explain the code for Steps 4-8. In the next post, I’ll address Step 9.

Note that this should go in the HEAD of your HTML page. Also, for performance reasons, only the page on your site that actually accepts payments should include all this JavaScript (in other words, don’t just put this into the header and footer files so it’s invoked by every page in your site). Next, you need to set your public Stripe key:

This can take place anywhere after you’ve included the Stripe.js library (which defines the Stripe object). The value here should be your public key, found in your Stripe account settings. Do not put your private key here as: 1) that won’t work, and 2) this value will be viewable in your source code.

As a tip, if you’re already using PHP for the page, I’d recommend storing your keys as constants in a configuration file:

By having PHP print this value, you can quickly change from testing to live mode by only editing your configuration file.

Next, I’d toss the rest of the JavaScript code—that which will hijack the form’s submission, make and handle the Ajax request, update the form, and submit the form—in an external JavaScript file:

<script type="text/javascript" src="js/buy.js"></script>

This script is going to do the bulk of the work, and the rest of the code explained will go in it.

Handling the Form’s Submission

The first thing the JavaScript has to do is setup an event handler for the form submission. The event handler should:

Disable the submit button to prevent a duplicate submission

Prevent the form’s submission

Validate the form data

Send the form data to Stripe via Ajax

You can do all this using straight JavaScript, of course, but I’ll use jQuery for my example. It’s easier, shorter, and more reliable. This does assume that the jQuery library will have been imported prior to this script.

Using jQuery, this code creates the event handler for the form’s submission:

This is standard jQuery stuff and only assumes that the form has a unique ID value of payment-form. Within the innermost function, you should disable the submit button and return false to prevent the form’s actual submission:

This takes care of the first two obligations (assuming that your submit button has an ID value of submitBtn).

Validating the Form Data

You can use any amount of standard JavaScript to perform minimal validation on the form data. However, it’s really best to be as thorough as you can in the validation, as there’s no need to send an incomplete request to Stripe, only to wait for that response to return an error. The Stripe object, defined in Stripe.js, has several validation methods built in:

validateCardNumber()

validateCVC()

validateExpiry()

The first will confirm that the provided number matches the right syntax for credit cards. The second does the same for the Card Verification Code (CVC). The third method confirms that the expiration month and year are both valid and in the future.

If any validation test failed, then the error variable is set to true and the Ajax request will not be performed (shown next). The reportError() function used in the above code will be explained later in this post. You may also want to validate any other form fields, but those aren’t pertinent to Stripe.

As you can see in that code, the request is made through the createToken() method of the Stripe object. It takes a generic object as its first parameter. That object should pass along the payment details. Note that you must match the names of the object attributes—number, cvc, exp_month, exp_year—exactly. You can pass along other values, such as the customer’s address, using other attributes enumerated in the Stripe documentation for Stripe.js.

The second argument to createToken() is the function that should handle the method result (aka the Ajax request response). I’m calling that stripeResponseHandler, to be written next.

Handling the Ajax

The stripeResponseHandler() function is called when Stripe responds to the Ajax request. The function should take two arguments: the status of the response and the response itself.

function stripeResponseHandler(status, response) {
}

The status argument will receive the status code, which loosely emulate standard HTTP status codes. Basically, 200 is good; 400, 401, 402, and 404 generally mean you screwed up; and codes in the 500’s means Stripe’s servers messed up. If you want to be thorough, you should check and address the status code, but I’m going to omit that step in this code and focus on the response value instead.

The response is going to be an object with several properties:

id, which is the token identifier

card, information about the card (but not the card number itself)

currency, indicating the payment currency, such as usd

livemode, which will be true or false

used, a Boolean indicating whether this token has already been used

If an error occurred, there will be an error property, with its own message property. You should check for this first (within the stripeResponseHandler() function):

And that’s that! If everything went smoothly, the token gets stored in a hidden form input and the form is submitted to the server, but the payment information is not provided to the server, because those form elements have no name attributes. The server will be able to use $_POST[‘stripeToken’] to actually process the payment, as will be explained in the next post.

Displaying Errors

Because errors could occur in several places, I think it best to create a JavaScript function that handles any error, which I’ll call reportError(). This function takes the error message as an argument and should:

Add that message to the page

Set the error class on the message

Enable the submit button

This last step is necessary because the form handling function disables the submit button. If you don’t re-enable it, then the customer can never resubmit the form after correcting the error.

For the first two steps, a single line of jQuery will do. Here’s the complete function:

This does assume that you’ve already created an element with an ID of payment-errors, that the submit button has an ID of submitBtn, and that you’ve defined a CSS class named error. This function is also written to only display a single error at a time. You could change it to concatenate each error to the #payment-errors content, in which case you’d need to write a clearErrors() function that gets called with each form submission (so that previous errors are not retained).

Conclusion

And there you have the JavaScript for handling the form and performing the Stripe request. It’s about 100 lines total, when well-spaced and documented (and, again, I’ll make all the code available via download later on).

In the next post, probably in two weeks, I’ll walk you through the PHP code that will handle the form data. In the meantime, if you have any questions or comments, please let me know.

When you get a stripe token back via the stripeResponseHandler, you then submit the form to the server. But, the form’s submit event has already been trapped earlier. You end up in an endless loop of resubmitting the form again and again ($(“#payment-form”).submit(function(event)).

Larry, I set up the code and tried it out and ran in to exactly the same problem that Jon described. This may not have been true when you wrote this article, but it certainly happens when I tested using jQuery 1.9.1. Perhaps something has changed.

I got around this infinite loop by adding this to the javascript inside of the submit handler:

Nope, I totally screwed up. My apologies to Jon and to anyone else caught by this. The solution is a bit esoteric: in the Ajax handler, submit the form using f.get(0).submit();. I’ve changed the code above and the downloads. Thanks, Adam, for the help, too.

The main thing is that f.get(0).submit() doesn’t trigger a form submission event on the form that f.submit() would. If there’s another form submission event, you end up in an endless loop (I made this mistake in my original posted code).

If we want to add and validate some additional form inputs for handling the credit card payment such as name, address and zip, does anyone have thoughts on the risks or disadvantages of doing this validation using jquery rather than waiting for the form to successfully post thereby allowing you to validate with PHP?

It’s not an either/or: You absolutely must do validation in PHP. Always. The client-side validation is a benefit to the user: provides immediate feedback without needing to submit the data to the server and await a server response.

I’m walking through this tutorial (I’m very appreciative for your thoroughness!) and I noticed that the form input values are being targeted with a class selector, i.e. expYear = $(‘.card-expiry-year’).val(); I’m curious, how does this select the value when the html has no classes defined?

Hi, I have follow the same process as mention. get success with validation and stripeToken gets. but when form get submitted then stripeToken is not append to form and also check with the account no success transaction is displayed. plz help me out.

Hi, I am using the stripe form you created and I have everything working but for some reason it keeps saying javascript is not enabled on my browsers and I have enabled it on all of them and I cannot submit the form to test it because of javascript Please help. Thanks

How is it that all the code examples on the Stripe web site are a complete and utter mess. They are filled with bugs that have to be fixed etc. How are people without much experience suppose to learn anything if you so called experts cannot even get it right! Thanks for the hours of wasted time; like getting the javascript is not enabled error even after I checked to see that Chrome was indeed running javascript! Bunch of Hacks.