Learn how to validate card inputs using Stripe.js with this step-by-step tutorial covering setup, real-time feedback, advanced validation, security, and responsive design.
Book a call with an Expert
Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.
How to Validate Card Inputs Using Stripe.js: A Comprehensive Tutorial
Step 1: Set up your Stripe account
Before implementing Stripe.js for card validation, you need to have a Stripe account. Here's how to set it up:
Step 2: Include Stripe.js in your HTML
Add the Stripe.js library to your payment page by including the script in your HTML file:
Stripe Card Validation
Step 3: Create a payment form in HTML
Set up a basic payment form structure with fields for card details. We'll use Stripe Elements, which are pre-built UI components:
Step 4: Initialize Stripe and create a card element
In your JavaScript file (payment.js), initialize Stripe with your publishable key and create a card element:
// Initialize Stripe.js with your publishable key
const stripe = Stripe('pk_test_your_publishable_key');
// Create an instance of Elements
const elements = stripe.elements();
// Custom styling for the card element
const style = {
base: {
color: '#32325d',
fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
fontSmoothing: 'antialiased',
fontSize: '16px',
'::placeholder': {
color: '#aab7c4'
}
},
invalid: {
color: '#fa755a',
iconColor: '#fa755a'
}
};
// Create a card Element and mount it to the div with id 'card-element'
const cardElement = elements.create('card', {style: style});
cardElement.mount('#card-element');
Step 5: Set up real-time validation feedback
Add event listeners to provide real-time feedback as users enter their card details:
// Handle real-time validation errors from the card Element
cardElement.addEventListener('change', function(event) {
const displayError = document.getElementById('card-errors');
if (event.error) {
displayError.textContent = event.error.message;
} else {
displayError.textContent = '';
}
});
Step 6: Handle form submission and validate the card
Set up a form submission handler to validate the card completely before processing the payment:
// Handle form submission
const form = document.getElementById('payment-form');
form.addEventListener('submit', function(event) {
event.preventDefault();
// Disable the submit button to prevent repeated clicks
document.querySelector('button').disabled = true;
// Create a token or confirm a PaymentIntent depending on your integration
stripe.createToken(cardElement).then(function(result) {
if (result.error) {
// Inform the user if there was an error
const errorElement = document.getElementById('card-errors');
errorElement.textContent = result.error.message;
// Re-enable the submit button
document.querySelector('button').disabled = false;
} else {
// Send the token to your server
stripeTokenHandler(result.token);
}
});
});
Step 7: Send the token to your server
After successful validation, you need to send the token to your server:
// Submit the form with the token ID
function stripeTokenHandler(token) {
// Insert the token ID into the form so it gets submitted to the server
const form = document.getElementById('payment-form');
const hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'stripeToken');
hiddenInput.setAttribute('value', token.id);
form.appendChild(hiddenInput);
// Submit the form
form.submit();
}
Step 8: Implement advanced validation with custom forms (Optional)
For more control, you can use individual Elements for card number, expiry, and CVC:
Advanced Stripe Validation
Step 9: Add ZIP code validation (Optional)
To enhance security, you can add ZIP code validation:
// When creating the card Element, add postal code collection
const cardElement = elements.create('card', {
style: style,
hidePostalCode: false, // Set to false to collect postal code
});
Step 10: Server-side validation and charge processing
After client-side validation, you need to validate the token on your server before creating a charge. Here's an example using Node.js with Express:
// Server-side code (Node.js with Express)
const express = require('express');
const bodyParser = require('body-parser');
const stripe = require('stripe')('sk_test_your_secret_key');
const app = express();
// Parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({extended: false}));
// Process payment
app.post('/charge', async (req, res) => {
try {
// Get the token from the request
const token = req.body.stripeToken;
// Create a charge
const charge = await stripe.charges.create({
amount: 1000, // Amount in cents
currency: 'usd',
description: 'Example charge',
source: token,
});
// Success
res.send('Payment successful!');
} catch (error) {
// Error
res.status(500).send(error.message);
}
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});
Step 11: Implement additional security measures
To enhance security further, consider implementing these measures:
Here's an example of implementing 3D Secure:
// Client-side code for 3D Secure
stripe.confirmCardPayment('pi_your_payment_intent_id', {
payment\_method: {
card: cardElement,
billing\_details: {
name: 'Customer Name'
}
}
}).then(function(result) {
if (result.error) {
// Show error to your customer
console.log(result.error.message);
} else {
if (result.paymentIntent.status === 'succeeded') {
// The payment succeeded!
console.log('Payment succeeded!');
}
}
});
Step 12: Testing card validation
Use Stripe's test card numbers to verify your validation is working correctly:
Step 13: Handling validation edge cases
Add code to handle edge cases in card validation:
// Client-side validation for edge cases
cardElement.addEventListener('change', function(event) {
const displayError = document.getElementById('card-errors');
if (event.error) {
displayError.textContent = event.error.message;
// Log specific error types for debugging
console.log('Error type:', event.error.type);
console.log('Error code:', event.error.code);
// Handle specific error cases
switch(event.error.code) {
case 'incomplete\_number':
// Specific UI feedback for incomplete card number
break;
case 'invalid_expiry_year\_past':
// Specific UI feedback for expired card
break;
case 'incorrect\_cvc':
// Specific UI feedback for incorrect CVC
break;
default:
// Generic error handling
}
} else {
displayError.textContent = '';
}
});
Step 14: Responsive styling for the form
Add CSS to make your form look good on all devices:
/_ In your styles.css file _/
#payment-form {
max-width: 500px;
margin: 0 auto;
padding: 20px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
border-radius: 4px;
}
.form-row {
margin-bottom: 16px;
}
label {
display: block;
margin-bottom: 8px;
font-weight: 500;
color: #32325d;
}
#card-element {
padding: 12px;
border: 1px solid #e6e6e6;
border-radius: 4px;
background-color: white;
}
#card-errors {
color: #fa755a;
margin-top: 8px;
font-size: 14px;
min-height: 20px;
}
button {
background-color: #6772e5;
color: white;
border: none;
padding: 12px 16px;
border-radius: 4px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s ease;
display: block;
width: 100%;
margin-top: 12px;
}
button:hover {
background-color: #5469d4;
}
button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
/_ Responsive styles _/
@media (max-width: 600px) {
#payment-form {
padding: 12px;
}
}
Step 15: Implementing complete payment flow with PaymentIntents API
For a modern approach, use the PaymentIntents API which supports SCA (Strong Customer Authentication):
// Server-side: Create a PaymentIntent
// Node.js/Express example
app.post('/create-payment-intent', async (req, res) => {
try {
const paymentIntent = await stripe.paymentIntents.create({
amount: 1000, // Amount in cents
currency: 'usd',
});
res.send({
clientSecret: paymentIntent.client\_secret
});
} catch (error) {
res.status(500).send({ error: error.message });
}
});
// Client-side: Complete the payment
// In your payment.js file
let paymentIntentClientSecret;
// Fetch the client secret from the server
fetch('/create-payment-intent', {
method: 'POST',
})
.then(function(response) {
return response.json();
})
.then(function(data) {
paymentIntentClientSecret = data.clientSecret;
});
// Handle form submission
const form = document.getElementById('payment-form');
form.addEventListener('submit', function(event) {
event.preventDefault();
// Disable the submit button to prevent repeated clicks
document.querySelector('button').disabled = true;
stripe.confirmCardPayment(paymentIntentClientSecret, {
payment\_method: {
card: cardElement,
billing\_details: {
name: document.getElementById('name').value
}
}
}).then(function(result) {
if (result.error) {
// Show error to your customer
const errorElement = document.getElementById('card-errors');
errorElement.textContent = result.error.message;
document.querySelector('button').disabled = false;
} else {
// The payment succeeded!
if (result.paymentIntent.status === 'succeeded') {
// There's a risk of the customer closing the window before callback
// execution. Set up a webhook or plugin to listen for the
// payment\_intent.succeeded event that handles any business critical
// post-payment actions.
window.location.href = '/payment-success';
}
}
});
});
By following this comprehensive guide, you should now have a fully functional and secure card validation system using Stripe.js. Remember to test thoroughly with various test card numbers and edge cases before going live with your payment processing system.
When it comes to serving you, we sweat the little things. That’s why our work makes a big impact.