If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.
The old, embedded form had a couple of nice formatting behaviors - like automatically adding a space between every 4 card numbers. Fortunately, Stripe has us covered once again here. Go back to the documentation and scroll down - they eventually reference something called jQuery.payment: a neat little JavaScript library for formatting checkout fields nicely.
It even provides validation, in case you want to make sure the numbers are sane before sending them off to Stripe.
I've already downloaded this library into the web/js
directory, so all we need
to do is include it on the page and point it at our form.
At the top, add a new script
tag and set its src="js/jQuery.payment.min.js"
:
... lines 1 - 3 | |
{% block javascripts %} | |
... lines 5 - 6 | |
<script type="text/javascript" src="https://js.stripe.com/v2/"></script> | |
<script src="{{ asset('js/jquery.payment.min.js') }}"></script> | |
... lines 9 - 57 | |
{% endblock %} | |
... lines 59 - 98 |
The asset
function is an optional helper function from Symfony - nothing magic
going on there.
Then, down below... try to ignore the ugly indentation that I should have fixed
earlier, and say $form.find()
. We need to find the credit card number input. But
don't worry! I planned ahead and gave it a special js-cc-number
class. I also
added js-cc-exp
and js-cc-cvc
:
<form action="" method="POST" class="js-checkout-form checkout-form"> | |
... lines 2 - 12 | |
<div class="row"> | |
<div class="col-xs-8 col-sm-6 col-sm-offset-2 form-group"> | |
<div class="input-group"> | |
... lines 16 - 18 | |
<input data-stripe="number" type="text" autocomplete="off" class="form-control js-cc-number" id="card-number" required placeholder="Card Number"/> | |
</div> | |
</div> | |
</div> | |
<div class="row"> | |
<div class="col-xs-4 col-sm-3 col-sm-offset-2 form-group"> | |
<div class="input-group"> | |
... lines 27 - 29 | |
<input data-stripe="exp" type="text" size="4" autocomplete="off" class="form-control js-cc-exp" id="card-expiration" required="required" placeholder="mm/yy"/> | |
</div> | |
</div> | |
<div class="col-xs-4 col-sm-3 form-group"> | |
<div class="input-group"> | |
... lines 35 - 37 | |
<input data-stripe="cvc" type="text" size="4" autocomplete="off" class="form-control js-cc-cvc" id="card-cvc" required="required" placeholder="CVC"/> | |
</div> | |
</div> | |
</div> | |
... lines 42 - 66 | |
</form> |
Fill in .js-cc-number
and then call .payment('formatCardNumber')
:
... lines 1 - 3 | |
{% block javascripts %} | |
... lines 5 - 9 | |
<script type="text/javascript"> | |
... lines 11 - 12 | |
... lines 17 - 28 | |
... lines 30 - 56 | |
</script> | |
{% endblock %} | |
... lines 59 - 98 |
Repeat this two more times for js-cc-exp
with formatCardExpiry
and formatCardCVC
.
Don't forget to update that class name too:
... lines 1 - 15 | |
... lines 19 - 98 |
Try it out! So sweet! The card field gets pretty auto-spacing and even more importantly, the library adds the slash automatically for the expiration field. It also limits the CVC field to a maximum of 4 numbers.
So custom forms are a little bit more work. But they fundamentally work the same.
Before we finish, there's one big hole left in our setup: failing gracefully when someone's card is declined.
"Houston: no signs of life"
Start the conversation!
// composer.json
{
"require": {
"php": ">=5.5.9, <7.4",
"symfony/symfony": "3.1.*", // v3.1.10
"doctrine/orm": "^2.5", // v2.7.2
"doctrine/doctrine-bundle": "^1.6", // 1.6.3
"doctrine/doctrine-cache-bundle": "^1.2", // 1.3.0
"symfony/swiftmailer-bundle": "^2.3", // v2.3.11
"symfony/monolog-bundle": "^2.8", // 2.11.1
"symfony/polyfill-apcu": "^1.0", // v1.2.0
"sensio/distribution-bundle": "^5.0", // v5.0.22
"sensio/framework-extra-bundle": "^3.0.2", // v3.0.16
"incenteev/composer-parameter-handler": "^2.0", // v2.1.2
"friendsofsymfony/user-bundle": "~2.0.1", // v2.0.1
"stof/doctrine-extensions-bundle": "^1.2", // v1.2.2
"stripe/stripe-php": "^3.15", // v3.23.0
"doctrine/doctrine-migrations-bundle": "^1.1", // 1.1.1
"twig/twig": "^1.24.1", // v1.35.2
"composer/package-versions-deprecated": "^1.11" // 1.11.99
},
"require-dev": {
"sensio/generator-bundle": "^3.0", // v3.0.7
"symfony/phpunit-bridge": "^3.0", // v3.1.2
"hautelook/alice-bundle": "^1.3", // v1.3.1
"doctrine/data-fixtures": "^1.2" // v1.2.1
}
}