Learn how to integrate Cashfree payment gateway in Laravel with a step-by-step guide. Includes migration, controller setup, payment processing, and success handling with Bootstrap UI.
If you haven’t already set up a Laravel project, install Laravel using Composer:
composer create-project --prefer-dist laravel/laravel cashfree-laravel
Navigate to the project directory:
cd cashfree-laravel
.env
file:
CASHFREE_API_KEY=*****************
CASHFREE_API_SECRET=*********************
CASHFREE_ENV=sandbox # or production
Generate the migration file:
php artisan make:migration create_payments_table
Edit the generated file in:
database/migrations/xxxx_xx_xx_xxxxxx_create_payments_table.php
:
public function up()
{
Schema::create('payments', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email');
$table->string('phone');
$table->decimal('amount', 10, 2);
$table->string('payment_id')->nullable();
$table->string('order_id')->nullable();
$table->boolean('status')->default(0); // 0 = Pending, 1 = Success
$table->json('other')->nullable();
$table->timestamps();
});
}
Run the migration:
php artisan migrate
Run the following command:
php artisan make:model Payment
Edit app/Models/Payment.php
:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Payment extends Model
{
use HasFactory;
protected $fillable = ['name', 'email', 'phone', 'amount', 'order_id', 'payment_id', 'status','other'];
protected $casts = [
'other' => 'array'
];
}
php artisan make:controller CashfreeController
Edit app/Http/Controllers/CashfreeController.php
:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Payment;
class CashfreeController extends Controller
{
public function index()
{
return view('cashfree.index');
}
public function payment(Request $request)
{
$request->validate([
'name' => 'required|string',
'email' => 'required|email',
'phone' => 'required|digits:10',
'amount' => 'required|numeric|min:1',
]);
// Generate unique order IDs
$orderId = 'order_'.rand(1111111111, 9999999999);
$customerId = 'customer_'.rand(111111111, 999999999);
$url = env('CASHFREE_ENV') === 'sandbox'
? "https://sandbox.cashfree.com/pg/orders"
: "https://api.cashfree.com/pg/orders";
$headers = [
"Content-Type: application/json",
"x-api-version: 2022-01-01",
"x-client-id: ".env('CASHFREE_API_KEY'),
"x-client-secret: ".env('CASHFREE_API_SECRET')
];
$data = json_encode([
'order_id' => $orderId,
'order_amount' => $request->amount,
"order_currency" => "INR",
"customer_details" => [
"customer_id" => $customerId,
"customer_name" => $request->name,
"customer_email" => $request->email,
"customer_phone" => $request->phone,
],
"order_meta" => [
"return_url" => route('cashfree.success').'?order_id={order_id}&order_token={order_token}'
],
]);
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
return back()->with('error', 'Failed to create payment order: '.$err);
}
$responseData = json_decode($response);
// Store payment details in database
$payment = Payment::create([
'name' => $request->name,
'email' => $request->email,
'phone' => $request->phone,
'amount' => $request->amount,
'order_id' => $orderId,
'status' => 0 // pending
]);
// Redirect to Cashfree payment page
return redirect()->to($responseData->payment_link);
}
public function success(Request $request)
{
$orderId = $request->input('order_id');
if (!$orderId) {
return redirect('/')->with('error', 'Payment verification failed: Missing order ID');
}
// Verify payment status with Cashfree API
$url = (env('CASHFREE_ENV') === 'sandbox'
? "https://sandbox.cashfree.com/pg/orders/"
: "https://api.cashfree.com/pg/orders/") . $orderId;
$headers = [
"Content-Type: application/json",
"x-api-version: 2022-01-01",
"x-client-id: ".env('CASHFREE_API_KEY'),
"x-client-secret: ".env('CASHFREE_API_SECRET')
];
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
return redirect('/')->with('error', 'Payment verification failed: '.$err);
}
$responseData = json_decode($response);
//dd($responseData);
// Update payment status in database
$payment = Payment::where('order_id', $orderId)->first();
if ($payment) {
$status = ($responseData->order_status === 'PAID') ? 1 : 0;
$payment->update([
'status' => $status,
'other' => $responseData,
'payment_id' => $responseData->cf_order_id ?? null,
'payment_method' => $responseData->payment_method ?? null
]);
if ($status === 1) {
return redirect('/')->with([
'success' => 'Payment Successful!',
'payment' => $payment,
]);
}
}
return redirect('/')->with('error', 'Payment verification failed for Order ID: ' . $orderId);
}
}
Edit routes/web.php
:
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\CashfreeController;
Route::get('/', [CashfreeController::class, 'index']);
Route::post('/cashfree/payments/store', [CashfreeController::class, 'payment'])->name('cashfree.payment');
Route::any('/cashfree/payments/success', [CashfreeController::class, 'success'])->name('cashfree.success');
resources/views/cashfree/index.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cashfree Payment</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
</head>
<body>
<section class=" pt-5">
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6">
@if (session('success'))
<div class="alert alert-success alert-dismissible fade show" role="alert">
<strong>Success!</strong> {{ session('success') }}
<button type="button" class="btn-close" data-bs-dismiss="alert"
aria-label="Close"></button>
</div>
@endif
@if (session('error'))
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<strong>Error!</strong> {{ session('error') }}
<button type="button" class="btn-close" data-bs-dismiss="alert"
aria-label="Close"></button>
</div>
@endif
@if (session('payment'))
<div class="card my-3">
<div class="card-header bg-success text-white">
<h5 class="mb-0">Payment Details</h5>
</div>
<div class="card-body">
<p><strong>Payment ID:</strong> {{ session('payment')->payment_id }}</p>
<p><strong>Order Id:</strong> {{ session('payment')->order_id }}</p>
<p><strong>Amount:</strong> ₹{{ session('payment')->amount }}</p>
</div>
</div>
@endif
<div class="card p-3">
<h2>Cashfree Payment Integration</h2>
<form action="{{ route('cashfree.payment') }}" method="POST">
@csrf
<div class="mb-3">
<label for="name" class="form-label">Full Name</label>
<input type="text" name="name" value="{{ old('name') }}"
class="form-control @error('name') is-invalid @enderror">
@error('name')
<span class="text-danger">{{ $message }}</span>
@enderror
</div>
<div class="mb-3">
<label for="email" class="form-label">Email Address</label>
<input type="email" name="email" value="{{ old('email') }}"
class="form-control @error('email') is-invalid @enderror">
@error('email')
<span class="text-danger">{{ $message }}</span>
@enderror
</div>
<div class="mb-3">
<label for="phone" class="form-label">Phone Number</label>
<input type="tel" name="phone" value="{{ old('phone') }}"
class="form-control @error('phone') is-invalid @enderror">
@error('phone')
<span class="text-danger">{{ $message }}</span>
@enderror
</div>
<div class="mb-3">
<label for="amount" class="form-label">Amount (INR)</label>
<input type="number" name="amount" value="{{ old('amount') }}"
class="form-control @error('amount') is-invalid @enderror">
@error('amount')
<span class="text-danger">{{ $message }}</span>
@enderror
</div>
<button type="submit" class="btn btn-primary">Proceed to Pay</button>
</form>
</div>
</div>
</div>
</div>
</section>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-VQqxDN0EQCkWoxt/0vsQvZswzTHUVOImccYmSyhJTp7kGtPed0Qcx8rK9h9YEgx+" crossorigin="anonymous"></script>
</body>
</html>
Now Run the server and it should work as it suppose to be:
php artisan serve
You have successfully integrated Cashfree Payment Gateway with Laravel! 🎉