Kritim Yantra
Jun 03, 2025
In today's digital world, accepting online payments is crucial for any web application. Laravel 12, the latest version of the popular PHP framework, makes integrating Stripe—one of the most secure and developer-friendly payment processors—remarkably simple. Whether you're building an e-commerce store, SaaS application, or any platform requiring payments, this guide will walk you through the entire process.
Before we begin, ensure you have:
php artisan --version
to check)First, let's install the required Stripe package via Composer:
composer require stripe/stripe-php
Add your Stripe keys to your .env
file:
STRIPE_KEY=your_stripe_publishable_key
STRIPE_SECRET=your_stripe_secret_key
You can find these in your Stripe Dashboard under "Developers" > "API keys".
Generate a new controller to handle payments:
php artisan make:controller PaymentController
Now, let's add some methods to our PaymentController.php
:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Stripe\Stripe;
use Stripe\PaymentIntent;
class PaymentController extends Controller
{
public function showPaymentForm()
{
return view('payment');
}
public function processPayment(Request $request)
{
Stripe::setApiKey(env('STRIPE_SECRET'));
try {
$paymentIntent = PaymentIntent::create([
'amount' => $request->amount * 100, // Convert to cents
'currency' => 'usd',
'description' => 'Payment for product/service',
'payment_method' => $request->payment_method,
'confirm' => true,
'return_url' => route('payment.success'),
]);
return redirect()->route('payment.success');
} catch (\Exception $e) {
return back()->withErrors(['error' => $e->getMessage()]);
}
}
public function paymentSuccess()
{
return view('payment_success');
}
}
Add these routes to your web.php
:
use App\Http\Controllers\PaymentController;
Route::get('/payment', [PaymentController::class, 'showPaymentForm'])->name('payment.form');
Route::post('/process-payment', [PaymentController::class, 'processPayment'])->name('payment.process');
Route::get('/payment/success', [PaymentController::class, 'paymentSuccess'])->name('payment.success');
Create a new file resources/views/payment.blade.php
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Payment Form</title>
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
<script src="https://js.stripe.com/v3/"></script>
</head>
<body class="bg-gray-100">
<div class="container mx-auto px-4 py-8">
<div class="max-w-md mx-auto bg-white rounded-xl shadow-md overflow-hidden md:max-w-2xl">
<div class="p-8">
<div class="uppercase tracking-wide text-sm text-indigo-500 font-semibold">Payment Information</div>
<form id="payment-form" action="{{ route('payment.process') }}" method="POST" class="mt-6">
@csrf
<div class="mb-4">
<label class="block text-gray-700 text-sm font-bold mb-2" for="amount">
Amount (USD)
</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
id="amount" name="amount" type="number" min="1" step="0.01" placeholder="10.00" required>
</div>
<div class="mb-4">
<label class="block text-gray-700 text-sm font-bold mb-2" for="card-element">
Credit or debit card
</label>
<div id="card-element" class="p-3 border rounded">
<!-- Stripe Elements will be inserted here -->
</div>
<div id="card-errors" role="alert" class="text-red-500 text-xs italic mt-2"></div>
</div>
<button id="submit-button" class="w-full bg-indigo-500 hover:bg-indigo-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline">
Pay Now
</button>
</form>
</div>
</div>
</div>
<script>
const stripe = Stripe('{{ env("STRIPE_KEY") }}');
const elements = stripe.elements();
const cardElement = elements.create('card');
cardElement.mount('#card-element');
const form = document.getElementById('payment-form');
const submitButton = document.getElementById('submit-button');
form.addEventListener('submit', async (event) => {
event.preventDefault();
submitButton.disabled = true;
const {paymentMethod, error} = await stripe.createPaymentMethod({
type: 'card',
card: cardElement,
});
if (error) {
document.getElementById('card-errors').textContent = error.message;
submitButton.disabled = false;
} else {
const hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'payment_method');
hiddenInput.setAttribute('value', paymentMethod.id);
form.appendChild(hiddenInput);
form.submit();
}
});
</script>
</body>
</html>
Create resources/views/payment_success.blade.php
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Payment Successful</title>
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
</head>
<body class="bg-gray-100">
<div class="container mx-auto px-4 py-8">
<div class="max-w-md mx-auto bg-white rounded-xl shadow-md overflow-hidden md:max-w-2xl">
<div class="p-8 text-center">
<svg class="mx-auto h-12 w-12 text-green-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
</svg>
<h2 class="mt-4 text-2xl font-bold text-gray-900">Payment Successful!</h2>
<p class="mt-2 text-gray-600">Thank you for your payment. Your transaction has been completed successfully.</p>
<div class="mt-6">
<a href="/" class="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
Return Home
</a>
</div>
</div>
</div>
</div>
</body>
</html>
Before going live, test your integration using Stripe's test cards:
4242 4242 4242 4242
4000 0000 0000 0002
Congratulations! You've successfully integrated Stripe payments into your Laravel 12 application. This implementation provides a secure, professional payment experience for your users. Remember to test thoroughly before going live and consider implementing additional features like email receipts or order tracking to enhance the user experience.
For more advanced implementations, check out the Laravel Cashier package which provides even more Stripe integration features out of the box.
Happy coding! 🚀
Transform from beginner to Laravel expert with our personalized Coaching Class starting June 11, 2025. Limited enrollment ensures focused attention.
1-hour personalized coaching
Build portfolio applications
Industry-standard techniques
Interview prep & job guidance
Complete your application to secure your spot
Thank you for your interest in our Laravel mentorship program. We'll contact you within 24 hours with next steps.
No comments yet. Be the first to comment!
Please log in to post a comment:
Sign in with Google