Processing Payments with Stripe
- Introduction to Stripe
- Creating a Stripe Payments Test Account
- Getting an SSL Certificate/Setting Up HTTPS
- Creating a Form for Handling Payments with Stripe
- Writing the PHP Code to Process Payments with Stripe
- Handling Stripe Errors
- Stripe Testing and Tricks
Once you’ve created a Stripe account and have acquired an SSL certificate, you’re ready to write the form through which you’ll accept payments to be processed via Stripe. This is surprisingly simple to do, and completely secure when done right. In this post, I’ll explain what you need to do with your HTML.
Two Traditional Payment Approaches
Before discussing the form, you should be clear as to how Stripe works compared to traditional payment processing approaches. Historically, depending upon the payment system in use, there were two possible processes:
- The user is sent from your site to the payment processor’s site, where the payment information will be taken. The user is then hopefully returned to your site.
- Your site takes the payment information and passes it to the payment processor behind the scenes. The user never leaves your site.
In both scenarios, the user’s payment information needs to get to the payment processor, and the payment processer needs to convey the success of that payment back to your site. What people normally think of as PayPal takes the first approach. Other payment gateways, such as Authorize.net, traditionally use the second approach.
Many payment processors, including PayPal and Authorize.net, now support both onsite or offsite payment processing (not at the same time, but you can choose which approach you want to use).
In the first scenario, the user is aware that she is leaving your site, you’re limited in how much you can customize that experience, and you have to put in a fair amount of work on your site to verify that the payment was made. On the other hand, because your site is not handling any of the payment information, you have a limited amount of risk.
With the second scenario, the user never leaves your site, you can completely customize the experience, and it’s easier to confirm that a successful payment was made. However, your security risk and exposure goes from being rather minimal to extremely serious.
If a user’s credit card or other payment information reaches your server, you must be PCI compliant and take many more steps to protect both the user and your business. In short, not only should you never store the user’s payment information, you really ought not to have it in your possession either, even momentarily.
- You create a form on your website that accepts the payment details.
- When the form is submitted, the user’s payment details are securely sent to Stripe via Ajax.
- Stripe will confirm that the payment information is valid and return a token that uniquely identifies that payment information.
- The server-side script (aka, the PHP code) that handles the form’s submission uses the token to actually process the payment.
So the customer never leaves your site but the payment information never hits your server: the best of both worlds. (This is the process when all works well; payment verification errors introduce new processes.)
The HTML Page and Form
To start, you need to include the Stripe.js library on your payment page:
As you can see, this library is hosted on Stripe’s server. You don’t have to download and install it on your site. Note that this library is loaded over HTTPS, and your HTML page (i.e., the one with the payment form on it) must be loaded via HTTPS, too.
When using Stripe.js, your only requirement to be PCI compliant is that the HTML form is loaded via HTTPS.
For the form itself, let’s assume that the name of the HTML page is buy.php, and it will both display and handle the form:
<form id="payment-form" action="buy.php" method="POST"> <div id="payment-errors"></div> </form>
For the form elements, it’s really up to you what all the form has. At the very least, you’ll need to have fields for the:
- Credit card number
- Expiration month
- Expiration year
Logically, you may also want to take the Card Verification Code (CVC) number.
Stripe does not have a set validation requirement; Stripe will only validate the information it receives. If you pass Stripe the CVC number, too, Stripe will validate that along with the credit card information. The user’s name and billing address is entirely optional from a payment validation perspective. The street address is not reliable for validation purposes, although the zip code can be checked (for US addresses).
You don’t have to ask for the credit card type, either, as that’s knowable information from just the credit card number.
It does not matter what input types you use for these elements; text is fine, although you can use the HTML5 number type for the month and year, if you’d rather. In any case, the most important factor is this: do not provide name values for these form elements! You should also set the autocomplete property to off for each element, so that the user’s browser does not attempt to save the values:
<label>Card Number</label> <input type="text" size="20" autocomplete="off"> <span>Enter the number without spaces or hyphens.</span> <label>CVC</label> <input type="text" size="4" autocomplete="off"> <label>Expiration (MM/YYYY)</label> <input type="text" size="2"> <span> / </span> <input type="text" size="4">
AGAIN: DO NOT PROVIDE NAME VALUES FOR YOUR PAYMENT FORM ELEMENTS!
If you want, you can add anything else you need to the form, such as the user’s email address or a password input (to create an account) or whatever. Those other fields will be standard HTML forms, with name attributes, whose values get sent to your server but not to Stripe.