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!
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.
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
You’ll need Stripe API keys to proceed. Visit your Stripe Dashboard:
.env
file:
STRIPE_PUBLISHABLE_KEY=your_publishable_key
STRIPE_SECRET_KEY=your_secret_key
Stripe Tax automatically calculates VAT based on the customer’s country. To set it up:
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'));
}
}
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>
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.
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');
Test your setup in Stripe’s test mode:
DE
for Germany, GB
for UK) to verify that VAT is applied correctly based on the country.4242 4242 4242 4242
).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.
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 :