How to Add VAT to Stripe Checkout in Laravel 12: Step-by-Step

Hey there! If you’re building an e-commerce app with Laravel 12 and want to use Stripe Checkout to handle payments with country-based VAT (Value Added Tax), I’ve got you covered.

In this guide, I’ll show you how to integrate VAT into Stripe Checkout sessions using the Stripe PHP package, without Laravel Cashier. The VAT will be automatically calculated based on the customer’s country, as configured in your Stripe Dashboard.

I’ll keep it simple, beginner-friendly, and include code examples to make it easy to follow. Let’s dive in and get your Laravel app ready to handle VAT seamlessly!

Step-by-Step Guide to Adding Country-Based VAT in Stripe Checkout with Laravel 12

how_to_add_vat_to_stripe_checkout_in_laravel_12

Here’s a clear guide to set up Stripe Checkout with automatic VAT calculation based on the customer’s country using Laravel 12 and the Stripe PHP package.

Step 1: Set Up Your Laravel 12 Project

Ensure you have a Laravel 12 project ready. If not, create one using Composer:

composer create-project laravel/laravel stripe-vat-checkout
cd stripe-vat-checkout

Install the Stripe PHP package to interact with Stripe’s API:

composer require stripe/stripe-php

Step 2: Get Your Stripe API Keys

You’ll need Stripe API keys to proceed. Visit your Stripe Dashboard:

  1. Go to Developers > API Keys.
  2. Copy your Publishable Key and Secret Key.
  3. Add them to your Laravel .env file:
STRIPE_PUBLISHABLE_KEY=your_publishable_key
STRIPE_SECRET_KEY=your_secret_key

Step 3: Configure Stripe Tax in Your Dashboard

Stripe Tax automatically calculates VAT based on the customer’s country. To set it up:

  1. In your Stripe Dashboard, navigate to Tax > Settings.
  2. Enable Stripe Tax and configure your tax settings, including your business address.
  3. Select the countries where you want to collect VAT (e.g., EU countries, UK, etc.). Stripe will use these settings to apply the correct VAT rate based on the customer’s billing address.
  4. Optionally, add tax rates for specific countries or products in the Tax Rates section.

Step 4: Configure Stripe in Laravel

Add Stripe configuration to your Laravel app. In config/services.php, include:

'stripe' => [
    'publishable_key' => env('STRIPE_PUBLISHABLE_KEY'),
    'secret_key' => env('STRIPE_SECRET_KEY'),
],

Create a controller to handle Stripe Checkout:

php artisan make:controller CheckoutController

In app/Http/Controllers/CheckoutController.php, initialize the Stripe client:

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Stripe\StripeClient;

class CheckoutController extends Controller
{
    protected $stripe;

    public function __construct()
    {
        $this->stripe = new StripeClient(config('services.stripe.secret_key'));
    }
}

Step 5: Create a Checkout Form

Create a Blade view to collect billing details and initiate the Stripe Checkout session. In resources/views/checkout.blade.php, add:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Checkout</title>
    <script src="https://js.stripe.com/v3/"></script>
</head>
<body>
    <form action="{{ route('checkout.create') }}" method="POST">
        @csrf
        <label for="name">Name</label>
        <input type="text" name="name" required><br>
        <label for="address_line1">Address Line 1</label>
        <input type="text" name="address_line1" required><br>
        <label for="city">City</label>
        <input type="text" name="city" required><br>
        <label for="state">State</label>
        <input type="text" name="state"><br>
        <label for="country">Country (e.g., US, GB, DE)</label>
        <input type="text" name="country" required><br>
        <label for="postal_code">Postal Code</label>
        <input type="text" name="postal_code" required><br>
        <label for="vat_id">VAT ID (Optional)</label>
        <input type="text" name="vat_id"><br>
        <button type="submit">Proceed to Checkout</button>
    </form>

    <script>
        document.addEventListener('DOMContentLoaded', async () => {
            const stripe = Stripe('{{ config('services.stripe.publishable_key') }}');
            const urlParams = new URLSearchParams(window.location.search);
            const sessionId = urlParams.get('session_id');

            if (sessionId) {
                const { error } = await stripe.redirectToCheckout({ sessionId });
                if (error) {
                    console.error(error.message);
                }
            }
        });
    </script>
</body>
</html>

Step 6: Create a Stripe Checkout Session with VAT

In CheckoutController, add a method to create a Checkout session with automatic tax calculation:

public function createCheckoutSession(Request $request)
{
    $validated = $request->validate([
        'name' => 'required|string',
        'address_line1' => 'required|string',
        'city' => 'required|string',
        'state' => 'nullable|string',
        'country' => 'required|string|max:2', // ISO 3166-1 alpha-2 country code (e.g., US, GB)
        'postal_code' => 'required|string',
        'vat_id' => 'nullable|string',
    ]);

    try {
        // Create or update customer
        $customer = $this->stripe->customers->create([
            'name' => $validated['name'],
            'address' => [
                'line1' => $validated['address_line1'],
                'city' => $validated['city'],
                'state' => $validated['state'],
                'country' => $validated['country'],
                'postal_code' => $validated['postal_code'],
            ],
        ]);

        // Add VAT ID if provided
        if (!empty($validated['vat_id'])) {
            $this->stripe->customers->createTaxId($customer->id, [
                'type' => 'eu_vat',
                'value' => $validated['vat_id'],
            ]);
        }

        // Create Checkout session
        $session = $this->stripe->checkout->sessions->create([
            'customer' => $customer->id,
            'payment_method_types' => ['card'],
            'line_items' => [[
                'price_data' => [
                    'currency' => 'usd',
                    'product_data' => [
                        'name' => 'Example Product',
                    ],
                    'unit_amount' => 1000, // $10.00 in cents
                ],
                'quantity' => 1,
                'tax_rates' => [], // Let Stripe Tax handle VAT based on country
            ]],
            'mode' => 'payment',
            'automatic_tax' => ['enabled' => true],
            'success_url' => route('checkout.success'),
            'cancel_url' => route('checkout.cancel'),
        ]);

        return redirect()->to($session->url);
    } catch (\Exception $e) {
        return back()->withErrors(['error' => $e->getMessage()]);
    }
}

The automatic_tax parameter enables Stripe to calculate VAT based on the customer’s country, as configured in your Stripe Dashboard.

Step 7: Define Routes

Add routes in routes/web.php to handle the checkout flow:

use App\Http\Controllers\CheckoutController;

Route::get('/checkout', fn() => view('checkout'))->name('checkout.form');
Route::post('/checkout', [CheckoutController::class, 'createCheckoutSession'])->name('checkout.create');
Route::get('/success', fn() => 'Payment Successful!')->name('checkout.success');
Route::get('/cancel', fn() => 'Payment Canceled.')->name('checkout.cancel');

Step 8: Test Your Integration

Test your setup in Stripe’s test mode:

  1. Use test API keys from your Stripe Dashboard.
  2. Enter different country codes (e.g., DE for Germany, GB for UK) to verify that VAT is applied correctly based on the country.
  3. Use Stripe’s test card numbers (e.g., 4242 4242 4242 4242).
  4. Check the Stripe Dashboard to confirm that VAT is included in the payment summary.
  5. Switch to live keys in your env file when ready for production.

Conclusion

Adding country-based VAT to Stripe Checkout sessions in Laravel 12 using the Stripe PHP package is straightforward and powerful. By leveraging Stripe Tax, you can automatically calculate VAT based on the customer’s country, ensuring compliance with global tax regulations. This approach keeps your codebase lightweight and gives you full control over the payment process. Follow these steps, test thoroughly, and you’ll have a VAT-ready checkout system in no time.

Frequently Asked Questions(FAQs)

Q: Do I need a Stripe account to use VAT with Checkout?
A: Yes, you need an active Stripe account to enable Stripe Tax and access API keys. Sign up at stripe.com.

Q: How does Stripe determine the VAT rate?
A: Stripe Tax uses the customer’s country (from their billing address) to apply the correct VAT rate, as configured in your Stripe Dashboard.

Q: Can I use Stripe Checkout for subscriptions?
A: Yes, Stripe Checkout supports both one-time payments and subscriptions. Set the mode to subscription in the Checkout session for recurring payments.

Q: What if a customer doesn’t provide a VAT ID?
A: Stripe will calculate VAT based on the customer’s country and address. A valid VAT ID can exempt certain customers from VAT in specific regions.

Q: Can I set different VAT rates for different products?
A: Yes, you can configure tax rates for specific products or countries in the Stripe Dashboard and apply them in the Checkout session.


You might also like :

techsolutionstuff

Techsolutionstuff | The Complete Guide

I'm a software engineer and the founder of techsolutionstuff.com. Hailing from India, I craft articles, tutorials, tricks, and tips to aid developers. Explore Laravel, PHP, MySQL, jQuery, Bootstrap, Node.js, Vue.js, and AngularJS in our tech stack.

RECOMMENDED POSTS

FEATURE POSTS