/stripe-guides

How to validate card inputs using Stripe.js?

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.

Matt Graham, CEO of Rapid Developers

Book a call with an Expert

Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.

Book a free consultation

How to validate card inputs using Stripe.js?

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:

  • Visit Stripe.com and sign up for an account
  • Complete the verification process
  • Navigate to the Developer section to retrieve your API keys (you'll need both publishable and secret keys)

 

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:

  • Use Stripe Radar for fraud detection
  • Implement 3D Secure authentication
  • Set up webhook endpoints to handle payment events

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:

  • Success: 4242 4242 4242 4242
  • Requires authentication: 4000 0025 0000 3155
  • Declined card: 4000 0000 0000 0002
  • Incorrect CVC: 4000 0000 0000 0127
  • Expired card: 4000 0000 0000 0069

 

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.

Want to explore opportunities to work with us?

Connect with our team to unlock the full potential of no-code solutions with a no-commitment consultation!

Book a Free Consultation

Client trust and success are our top priorities

When it comes to serving you, we sweat the little things. That’s why our work makes a big impact.

Rapid Dev was an exceptional project management organization and the best development collaborators I've had the pleasure of working with. They do complex work on extremely fast timelines and effectively manage the testing and pre-launch process to deliver the best possible product. I'm extremely impressed with their execution ability.

CPO, Praction - Arkady Sokolov

May 2, 2023

Working with Matt was comparable to having another co-founder on the team, but without the commitment or cost. He has a strategic mindset and willing to change the scope of the project in real time based on the needs of the client. A true strategic thought partner!

Co-Founder, Arc - Donald Muir

Dec 27, 2022

Rapid Dev are 10/10, excellent communicators - the best I've ever encountered in the tech dev space. They always go the extra mile, they genuinely care, they respond quickly, they're flexible, adaptable and their enthusiasm is amazing.

Co-CEO, Grantify - Mat Westergreen-Thorne

Oct 15, 2022

Rapid Dev is an excellent developer for no-code and low-code solutions.
We’ve had great success since launching the platform in November 2023. In a few months, we’ve gained over 1,000 new active users. We’ve also secured several dozen bookings on the platform and seen about 70% new user month-over-month growth since the launch.

Co-Founder, Church Real Estate Marketplace - Emmanuel Brown

May 1, 2024 

Matt’s dedication to executing our vision and his commitment to the project deadline were impressive. 
This was such a specific project, and Matt really delivered. We worked with a really fast turnaround, and he always delivered. The site was a perfect prop for us!

Production Manager, Media Production Company - Samantha Fekete

Sep 23, 2022