Learn how to fix Stripe "verification failed" errors for webhooks, identity, payments, and API keys with step-by-step troubleshooting and best practices.
Book a call with an Expert
Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.
Understanding and Fixing Stripe "Verification Failed" Error: A Comprehensive Guide
Introduction
When working with Stripe, you might encounter the "verification failed" error, which can happen during webhook verification, identity verification, or payment processing. This tutorial will guide you through identifying the cause and resolving the error step by step, covering all possible scenarios.
Step 1: Understand what causes Stripe verification failures
Stripe verification failures typically occur due to:
Step 2: Fix Webhook Signature Verification Failures
If you're receiving a webhook signature verification error, follow these steps:
Step 2.1: Check your webhook secret key
Ensure you're using the correct webhook signing secret:
// Incorrect implementation
const event = stripe.webhooks.constructEvent(
request.body,
signature,
'whsec_incorrect_or_old_secret'
);
// Correct implementation
const event = stripe.webhooks.constructEvent(
request.body,
signature,
process.env.STRIPE_WEBHOOK_SECRET // Store securely in environment variables
);
Step 2.2: Verify raw request body
Make sure you're passing the raw request body to the verification function:
// Node.js Express example with proper body parsing
app.post('/webhook', express.raw({type: 'application/json'}), (req, res) => {
const signature = req.headers['stripe-signature'];
try {
const event = stripe.webhooks.constructEvent(
req.body, // Raw body
signature,
process.env.STRIPE_WEBHOOK_SECRET
);
// Handle the event
console.log('Webhook verified:', event.type);
res.json({received: true});
} catch (err) {
console.error('Webhook verification failed:', err.message);
return res.status(400).send(`Webhook Error: ${err.message}`);
}
});
Step 2.3: Check for body parsing issues
For frameworks like Express, ensure the webhook route receives the raw body:
// Incorrect: Using general body parser middleware for all routes
app.use(express.json());
// Correct: Use raw body parser only for webhook route
app.post('/webhook', express.raw({type: 'application/json'}), webhookHandler);
// For other routes, use JSON parsing
app.use(express.json());
Step 3: Fix Identity Verification Failures
If you or your users are facing identity verification issues:
Step 3.1: Complete missing verification information
Navigate to the Stripe Dashboard and check for missing information:
Step 3.2: Improve document quality for verification
When uploading verification documents:
Step 3.3: Update user verification process in your application
If you're building a platform with connected accounts:
// Create an AccountLink to direct users to Stripe's verification flow
app.post('/create-verification-session', async (req, res) => {
try {
const accountLink = await stripe.accountLinks.create({
account: req.body.stripeAccountId,
refresh\_url: 'https://example.com/reauth',
return\_url: 'https://example.com/return',
type: 'account\_onboarding',
});
res.json({ url: accountLink.url });
} catch (error) {
console.error('Error creating account link:', error);
res.status(500).json({ error: error.message });
}
});
Step 4: Fix Payment Method Verification Failures
If card verification is failing during payments:
Step 4.1: Implement proper card validation
Use Stripe Elements or Checkout for secure card collection:
// Client-side implementation with Stripe Elements
const stripe = Stripe('pk_test_your_publishable_key');
const elements = stripe.elements();
const cardElement = elements.create('card');
cardElement.mount('#card-element');
// Handle form submission
const form = document.getElementById('payment-form');
form.addEventListener('submit', async (event) => {
event.preventDefault();
const { error, paymentMethod } = await stripe.createPaymentMethod({
type: 'card',
card: cardElement,
});
if (error) {
// Show error to customer
const errorElement = document.getElementById('card-errors');
errorElement.textContent = error.message;
} else {
// Send paymentMethod.id to your server
const result = await fetch('/create-payment-intent', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ payment_method_id: paymentMethod.id, amount: 1000 })
});
const paymentIntent = await result.json();
handlePaymentIntentResult(paymentIntent);
}
});
Step 4.2: Implement 3D Secure authentication correctly
Ensure you're handling 3D Secure authentication properly:
// Server-side handling of PaymentIntent
app.post('/create-payment-intent', async (req, res) => {
try {
const paymentIntent = await stripe.paymentIntents.create({
amount: req.body.amount,
currency: 'usd',
payment_method: req.body.payment_method\_id,
confirmation\_method: 'manual',
confirm: true,
return\_url: 'https://example.com/order/success',
});
res.json(handlePaymentIntentStatus(paymentIntent));
} catch (error) {
res.status(400).json({ error: error.message });
}
});
// Client-side handling of authentication
function handlePaymentIntentResult(paymentIntent) {
if (paymentIntent.status === 'requires\_action' &&
paymentIntent.next_action.type === 'use_stripe\_sdk') {
// Use Stripe.js to handle the required card action
stripe.confirmCardPayment(paymentIntent.client\_secret).then(function(result) {
if (result.error) {
// Show error to customer
showError(result.error.message);
} else {
// The payment has succeeded
orderComplete(paymentIntent.id);
}
});
} else if (paymentIntent.status === 'succeeded') {
// The payment succeeded
orderComplete(paymentIntent.id);
} else {
// Invalid status
showError('Payment unsuccessful. Please try again.');
}
}
Step 5: Fix API Key Issues
Step 5.1: Ensure you're using the correct API keys
Verify you're using the proper API keys for your environment:
// Development environment
const stripe = require('stripe')('sk_test_YourTestSecretKey');
// Production environment
const stripe = require('stripe')('sk_live_YourLiveSecretKey');
Step 5.2: Check for API key restrictions
If you've set up restricted API keys, make sure they have the necessary permissions:
Step 6: Debug with Stripe Logs
Step 6.1: Check Stripe Dashboard logs
Review the logs in your Stripe Dashboard:
Step 6.2: Implement detailed logging in your application
Add comprehensive logging to help diagnose issues:
try {
const event = stripe.webhooks.constructEvent(
req.body,
signature,
process.env.STRIPE_WEBHOOK_SECRET
);
// Process event
} catch (err) {
console.error('Webhook Error:', {
message: err.message,
requestBody: req.body.toString(),
signatureHeader: signature,
webhookSecret: process.env.STRIPE_WEBHOOK_SECRET.substring(0, 4) + '...',
stripeLibraryVersion: stripe.VERSION
});
return res.status(400).send(`Webhook Error: ${err.message}`);
}
Step 7: Update Stripe Libraries
Ensure you're using the latest Stripe libraries:
// For Node.js
npm update stripe
// For PHP
composer update stripe/stripe-php
// For Python
pip install --upgrade stripe
// For Ruby
gem update stripe
Step 8: Contact Stripe Support
If you've tried all the above steps and still encounter verification issues:
Conclusion
Stripe verification errors can occur at different points in the payment and integration process. By following this comprehensive guide, you should be able to identify and resolve most verification issues. Remember to always keep your Stripe libraries updated, use proper error handling, and implement best practices for security when dealing with payment information.
When it comes to serving you, we sweat the little things. That’s why our work makes a big impact.