Razorpay Payment Gateway Integration In Laravel
A Complete guide to Integrate Razorpay In Laravel
Razorpay Payment Gateway Integration In Laravel
In this tutorial, you will learn how to integrate RazorPay in your Laravel 10 application. Read on to know the essential steps for the integration. This article will cover the all the cases involved in the payment feature.
Steps to Integrate Razorpay Payment Gateway In Laravel
The Step by Step process to implement this feature in Laravel 10 Application.
Step 1 - Install the Laravel 10 Application
Install the laravel application directory where ever you want to using this command.
composer create-project laravel/laravel IntegrateRazorpayInLaravel
Step 2 - Connect Database to an Application
Update the database configuration in .env
DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=razorpay
DB_USERNAME=root
DB_PASSWORD=
Step 3 - Add RazorPay Credentials From Dashboard
Access the API KEY and SECRET KEY from your Razorpay Dashboard. First, log in to the dashboard, then go to Account Settings > API keys. Add the keys in .env
RAZORPAY_API_KEY=rzp_test_XXXXXXXXXX
RAZORPAY_API_SECRET=XXXXXXXXXXXXXXXXX
Step 4 - Install the Razorpay Composer Package
Install the razorpay composer package to handle the payment related activities in Laravel Application.
composer require razorpay/razorpay
This command will download and install the Razorpay PHP SDK into your Laravel project.
Step 5 - Create a Table and Model to Store the Razorpay Events Response
Now we are going to create a model and table for this setup using this below command.
php artisan make:model Payment --migration
Now the Migration and Model Files are generated. Update the table schema based on your need.
Here the below code for above migration and model creation.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Payment extends Model
{
use HasFactory;
protected $table = 'payments';
protected $guarded = ['id'];
}
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('payments', function (Blueprint $table) {
$table->id();
$table->string('r_payment_id');
$table->string('method');
$table->string('currency');
$table->string('email');
$table->string('phone');
$table->string('amount');
$table->string('status');
$table->longText('json_response');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('payments');
}
};
Execute the below command to run the migration
php artisan migrate
Step 6 - Create a Controller and Views
Create a RazorpayController to handle the request and response based actions in the application and UI Design in the views.
Execute the below command to create the controller and view
php artisan make:controller RazorpayController
php artisan make:view razorpay/index
php artisan make:view components/razorpay-form
php artisan make:view errors/402
The View Command is Only Applicable in After Laravel V10.30
In the RazorpayController Add the Business Logic to handle the Razorpay success and failure events scenario.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Session;
use App\Models\Payment;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\DB;
use Razorpay\Api\Api;
class RazorpayController extends Controller
{
public function index(): View
{
try {
return view('razorpay.index');
} catch (\Throwable $th) {
Log::error('PAYMENT_INDEX_ERROR'.$th->getMessage());
}
}
public function store(Request $request): JsonResponse
{
DB::beginTransaction();
try {
$paymentResponse = $request->input('response', []);
if (count($paymentResponse) > 0 && empty($paymentResponse['razorpay_payment_id'])) {
Session::put('error', 'No Payment ID Found');
return redirect()->back();
}
$api = new Api(env('RAZORPAY_API_KEY'), env('RAZORPAY_API_SECRET'));
$payment = $api->payment->fetch($paymentResponse['razorpay_payment_id']);
$response = $payment->capture(['amount' => $payment['amount']]);
Payment::create([
'r_payment_id' => $response->id,
'method' => $response->method,
'currency' => $response->currency,
'email' => $response->email,
'phone' => $response->contact,
'amount' => $response->amount / 100,
'status' => 'success',
'json_response' => json_encode((array) $response)
]);
Session::put('success', 'Payment Successful');
DB::commit();
return response()->json(['success' => true, 'message' => 'Payment successfully recorded']);
} catch (\Throwable $th) {
DB::rollBack();
Log::error('PAYMENT_STORE_ERROR'.$th->getMessage());
Session::put('error', $th->getMessage());
return response()->json(['success' => false, 'error' => 'Internal Server Error'], 500);
}
}
public function failure(Request $request): JsonResponse {
DB::beginTransaction();
try {
$responseData = $request->input('response', []);
$errorData = $responseData['error'] ?? [];
Payment::create([
'r_payment_id' => $errorData['metadata']['payment_id'] ?? null,
'method' => $errorData['source'] ?? null,
'currency' => 'INR',
'email' => '', //email id for the the user
'phone' => '', // mobile number for the user,
'amount' => 100, // amount for the payment process
'status' => 'failed',
'json_response' => json_encode($responseData)
]);
DB::commit();
return response()->json(['success' => true, 'message' => 'Payment failure recorded']);
} catch (\Throwable $th) {
DB::rollBack();
Log::error('PAYMENT_FAILURE_ERROR: '.$th->getMessage());
return response()->json(['success' => false, 'error' => 'Internal Server Error'], 500);
}
}
}
To handle the payment gateway via View.
{{-- resources/views/razorpay/index.blade.php --}}
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
</head>
<body>
<div>@include('components.razorpay-form')</div>
</body>
</html>
We have created a component form to manage Razorpay payment activities, allowing for seamless integration of the payment gateway page throughout the application, accessible via a button click.
{{-- resources/views/components/razorpay-form.blade.php --}}
<form action="{{ route('razorpay.payment.store') }}" method="POST">
@csrf
<script src="https://checkout.razorpay.com/v1/checkout.js"></script>
<button id="payBtn">Pay 100 INR
</button>
</form>
<script>
var options = {
"key": "{{ env('RAZORPAY_API_KEY') }}",
"amount": "10000",
"name": "Dhanar98",
"description": "Razorpay payment",
"image": "https://cdn.razorpay.com/logos/NSL3kbRT73axfn_medium.png",
"prefill": {
"name": "ABC",
"email": "abc@gmail.com"
},
"theme": {
"color": "#0F408F"
},
"handler" : function(res) {
console.log(res);
$.ajax({
url: "/payment/create",
type: 'POST',
dataType: 'json',
data: {
_token: "{{ csrf_token() }}", // CSRF token
response: {
razorpay_payment_id: res.razorpay_payment_id
}
},
success: function(res) {
console.log('Payment data sent to server', res);
if (res.success = true) {
window.location.href = '/'; //payment failure
}
},
error: function(jqXHR, textStatus, errorThrown) {
console.log('Error sending payment failure information:', textStatus, errorThrown);
}
});
},
"modal": {
"ondismiss": function() {
// This function is called when the user closes the modal
window.location.href = '/'; // Redirect to your failure page
}
}
};
var rzp = new Razorpay(options);
document.getElementById('payBtn').onclick = function(e) {
rzp.open();
e.preventDefault();
}
rzp.on('payment.failed', function(response) {
event.preventDefault();
if (response.reason = "payment_failed") {
const {
error,
reason
} = response;
$.ajax({
url: "/payment/failure",
type: 'POST',
dataType: 'json',
data: {
_token: "{{ csrf_token() }}", // CSRF token
response: {
error,
reason
}
},
success: function(response) {
console.log('Payment failure data sent to server', response);
if (response.success = true) {
window.location.href = '/402'; //payment failure
}
},
error: function(jqXHR, textStatus, errorThrown) {
console.log('Error sending payment failure information:', textStatus, errorThrown);
}
});
}
});
</script>
Handling payment Failure created a error page in errors folder in views.
<!DOCTYPE html>
<html>
<head>
<title>Payment Required</title>
</head>
<body>
<h1>402 Payment Required</h1>
</body>
</html>
Step 7 - Create a Routes To Handle Requests
To create a requests in the web.php
to handle the success and failure events.
<?php
use App\Http\Controllers\RazorpayController;
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
return view('welcome');
});
Route::get('payment',[RazorpayController::class,'index']);
Route::post('payment/create',[RazorpayController::class,'store'])->name('razorpay.payment.store');
Route::post('payment/failure',[RazorpayController::class,'failure'])->name('razorpay.payment.failure');
Route::get('/402', function () {
return view('errors.402');
});
Step 8 - Run the Application
To run the application execute the command in terminal.
php artisan serve
I run my application in laragon it creates a seperate APP_URL for every project i created. if you're working very long in XAMPP try laragon you will never go XAMPP again. so i don't need this command also (Windows OS) only.
Conclusion:
In this article I covered all the steps to integrate razorpay in Laravel 10 Application and handling success and error response in the payment gateway controller.
Share your colleague or friend who is struggling to integrate razorpay and support my work from coindrop.
GITHUB Repository:
Article Commits step by step - https://github.com/dhanar98/IntegrateRazorpayInLaravel/commits/master/