The Stripe Payment Gateway is one of the most popular solutions for online payments due to its flexibility, security, and ease of integration. In this guide, you’ll learn how to integrate the Stripe Payment Gateway into a Laravel application for single product checkout, complete with shipping and discount support.
Whether you’re building an eCommerce site or a service platform, securely accepting payments is critical—and Stripe makes it straightforward.
🎯 Why Use Stripe Payment Gateway in Laravel?
The Stripe Payment Gateway allows developers to easily embed secure, PCI-compliant payment flows. Laravel, with its elegant syntax and powerful backend tools, is a great match.
By the end of this guide, you’ll have:
- Implemented a Stripe integration in Laravel
- Allowed users to input product details and pay via Stripe
- Configured dynamic Stripe payment gateway charges like shipping and discounts
- Handled success and failure events after checkout
⚙️ Step 1: Project Setup & Stripe Configuration
Start by creating a new Laravel project:
laravel new StripePaymentGateway

Install Stripe’s official PHP SDK:
composer require stripe/stripe-php

In your .env
file, add your Stripe Payment Gateway credentials:

Update your config/services.php:

This sets up basic stripe integration in Laravel.
📦 Step 2: Create Order Model and Migration
Generate the model:
php artisan make:model Order -m
Add the necessary required fields and then run:
php artisan migrate

🌐 Step 3: Define Routes for Stripe Payment Flow
Route::get('/order', [StripeController::class, 'order'])->name('order');
Route::post('/stripe', [StripeController::class, 'checkout'])->name('checkout');
Route::get('/success/{orderId}', [PaymentController::class, 'success'])->name('success');
Route::get('/fail/{orderId}', [PaymentController::class, 'fail'])->name('fail');

💳 Step 4: Build the Checkout Form
Use Bootstrap to create a form where users can:
- Enter product name and price
- Choose quantity
- Apply discounts (flat or percentage)
- Enter shipping charge
This form will post to your checkout
route
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Checkout</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container mt-5">
<h2 class="mb-4 text-center">Checkout - Single Product</h2>
<div class="row justify-content-center">
<div class="col-md-6">
<div class="card shadow-sm">
<div class="card-body">
<form action="{{ route('checkout') }}" method="POST">
@csrf
<div class="mb-3">
<label for="product_name" class="form-label">Product Name</label>
<input type="text" name="product_name" class="form-control" value="Sample Product" required>
</div>
<div class="mb-3">
<label for="unit_price" class="form-label">Unit Price (AUD)</label>
<input type="number" name="unit_price" class="form-control" value="15" min="0" required>
</div>
<div class="mb-3">
<label for="quantity" class="form-label">Quantity</label>
<input type="number" name="quantity" class="form-control" value="1" min="1" required>
</div>
<div class="mb-3">
<label for="discount_type" class="form-label">Discount Type</label>
<select name="discount_type" class="form-select">
<option value="flat">Flat (AUD)</option>
<option value="percent">Percentage (%)</option>
</select>
</div>
<div class="mb-3">
<label for="discount" class="form-label">Discount (AUD)</label>
<input type="number" name="discount" class="form-control" value="0" min="0">
</div>
<div class="mb-3">
<label for="shipping" class="form-label">Shipping Charge (AUD)</label>
<input type="number" name="shipping" class="form-control" value="0" min="0">
</div>
<button type="submit" class="btn btn-success w-100">Proceed to Stripe Payment</button>
</form>
</div>
</div>
</div>
</div>
</div>
</body>
</html>

🧠 Step 5: Handle Checkout with StripeController
Your controller will:
- Calculate the subtotal
- Apply a discount if selected
- Add shipping charges
- Create a Stripe Checkout session
It also saves the order to the database and redirects to the Stripe Payment Gateway.
This is where you manage the stripe payment gateway integration logic and handle secure payments using the stripe/stripe-php
package.
<?php
namespace App\Http\Controllers;
use App\Models\Order;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Stripe\Checkout\Session;
use Stripe\Coupon;
use Stripe\Stripe;
class StripeController extends Controller
{
public function order()
{
return view('order');
}
public function checkout(Request $request)
{
Stripe::setApiKey(config('services.stripe.secret'));
$shipping_array = [
[
'shipping_rate_data' => [
'type' => 'fixed_amount',
'fixed_amount' => [
'amount' => $request->shipping * 100,
'currency' => 'aud',
],
'display_name' => 'Standard shipping',
],
],
];
$lineItems[] = [
'price_data' => [
'currency' => 'aud',
'product_data' => [
'name' => $request->product_name,
'images' => [asset('images/img.png')],
],
'unit_amount' => $request->unit_price * 100,
],
'quantity' => $request->quantity,
];
$coupons = null;
$subtotal = $request->unit_price * $request->quantity;
$coupon_amount = 0;
if (!is_null($request->discount) && $request->discount > 0) {
if ($request->discount_type == 'flat') {
$coupon_amount = $request->discount;
$coupons = Coupon::create([
'name' => 'name',
'amount_off' => $request->discount * 100,
'currency' => 'aud',
'id' => Str::uuid(),
]);
} else {
$coupon_amount = ($request->discount / 100) * $subtotal;
$coupons = Coupon::create([
'name' => 'name',
'percent_off' => $request->discount,
'id' => Str::uuid(),
]);
}
}
$total = $subtotal + $request->shipping + $coupon_amount;
$order = Order::create([
'user_id' => auth()->user()->id ?? 1,
'product_name' => $request->product_name,
'quantity' => $request->quantity,
'unit_price' => $request->unit_price,
'status' => 'Pending',
'total_amount' => $total,
'payment_method' => "Stripe",
]);
$session = Session::create([
'payment_method_types' => ['card'],
'line_items' => $lineItems,
'mode' => 'payment',
'success_url' => route('success', ['orderId' => $order->id]),
'cancel_url' => route('fail', ['orderId' => $order->id]),
'discounts' => [
[
'coupon' => $coupons,
],
],
'shipping_options' => $shipping_array
]);
$order->update(['stripe_token' => $session->id,]);
return redirect()->to($session->url);
}
}

✅ Step 6: Payment Success and Failure
In PaymentController
, verify the session using Stripe’s API:
- If successful, mark the order as “Success”
- If the payment fails or is canceled, mark as “Failed”
You can retrieve the payment_intent
and compare totals to ensure safe and secure stripe payment gateway in PHP handling.
<?php
namespace App\Http\Controllers;
use App\Models\Order;
use Stripe\Checkout\Session;
use Stripe\PaymentIntent;
use Stripe\Stripe;
class PaymentController extends Controller
{
public function success($orderId)
{
$order = Order::findOrFail($orderId);
Stripe::setApiKey(config('services.stripe.secret'));
$session = Session::retrieve($order->stripe_token);
if ($session->payment_status == 'unpaid') {
flash()->addWarning("Payment Failed. Please try again.");
return redirect()->route('order');
}
$amount = $session->amount_total;
$paymentIntent = PaymentIntent::retrieve($session->payment_intent);
$payment_status = $paymentIntent->status;
if ($payment_status == 'succeeded' && $order->total_amount * 100 == $amount) {
$user = auth()->user()->id ?? 1;
$order->update(['status' => 'Success']);
flash()->addSuccess("Payment Successful. Thank you for your order!");
return redirect()->route('order');
} else {
flash()->addWarning("Payment Failed. Please try again.");
return redirect()->route('order');
}
}
public function fail($orderId)
{
$order = Order::findOrFail($orderId);
if ($order->payment == 'Pending' && \auth()->user()->id == $order->user_id) {
$order->update(['status' => 'Failed']);
}
flash()->addWarning("Payment Failed. Please try again.");
return redirect()->route('ecommerce');
}
}
🚀 Conclusion
By following this guide, you’ve successfully set up a complete Stripe Payment Gateway solution in Laravel. You’ve handled:
- Checkout with discount and shipping
- Order storage
- Payment verification with Stripe
- Error handling and secure payment flows
Whether you’re working on a simple project or a full-scale app, stripe integration in Laravel makes accepting payments seamless. Here is the Github link for this demo project.