Integrating the Razorpay Payment API with Laravel for Seamless Checkout Experiences in Indian E‑Commerce
In today’s fast-growing Indian e-commerce market, a smooth and secure checkout experience is critical. Customers expect quick payments, multiple payment options, and trust in the platform they are buying from. Razorpay has become one of the most popular payment gateways in India, and Laravel is a preferred framework for building scalable web applications.
In this tutorial, we’ll walk through how to integrate the Razorpay Payment API with a Laravel application to create a seamless checkout flow tailored for Indian startups and e-commerce businesses.
Why Razorpay and Laravel?
Razorpay offers a developer-friendly API, support for UPI, cards, net banking, wallets, and EMI, and strong security features. It is widely used by Indian businesses for online payments.
Laravel provides a clean, expressive syntax, built-in security features, and a robust ecosystem that makes it easier to build and maintain complex applications. Together, Razorpay and Laravel can help you build a reliable and scalable e-commerce platform.
Prerequisites
Before we start, make sure you have:
- PHP 8.x and Composer installed
- Laravel 9 or 10 project set up
- A Razorpay account with API keys (Key ID and Key Secret)
- Basic understanding of Laravel routes, controllers, and Blade views
Step 1: Install the Razorpay PHP SDK
Razorpay provides an official PHP SDK that simplifies API interactions. Install it via Composer:
composer require razorpay/razorpay
This package will handle API requests, signature verification, and webhook validation.
Step 2: Configure Razorpay Credentials
Store your Razorpay API keys in your .env file:
RAZORPAY_KEY=your_key_id
RAZORPAY_SECRET=your_key_secret
Then, add these to your config/services.php:
'razorpay' => [
'key' => env('RAZORPAY_KEY'),
'secret' => env('RAZORPAY_SECRET'),
],
Never expose your secret key in client-side code or version control.
Step 3: Create a Payment Controller
Generate a controller to handle payment logic:
php artisan make:controller PaymentController
In PaymentController.php, add methods to create an order and verify the payment:
use Razorpay\Api\Api;
use Illuminate\Support\Facades\Log;
class PaymentController extends Controller
{
public function showCheckout()
{
return view('checkout');
}
public function createOrder(Request $request)
{
$api = new Api(config('services.razorpay.key'), config('services.razorpay.secret'));
$order = $api->order->create([
'receipt' => 'order_rcptid_' . uniqid(),
'amount' => $request->input('amount') * 100, // in paise
'currency' => 'INR',
'payment_capture' => 1,
]);
return response()->json([
'order_id' => $order->id,
'amount' => $order->amount,
'currency' => $order->currency,
]);
}
public function verifyPayment(Request $request)
{
$api = new Api(config('services.razorpay.key'), config('services.razorpay.secret'));
$attributes = [
'razorpay_order_id' => $request->input('razorpay_order_id'),
'razorpay_payment_id' => $request->input('razorpay_payment_id'),
'razorpay_signature' => $request->input('razorpay_signature'),
];
try {
$api->utility->verifyPaymentSignature($attributes);
// Payment is verified
return response()->json(['status' => 'success', 'message' => 'Payment verified']);
} catch (\Exception $e) {
Log::error('Razorpay verification failed: ' . $e->getMessage());
return response()->json(['status' => 'error', 'message' => 'Payment verification failed'], 400);
}
}
}
Step 4: Build the Checkout View
Create a Blade view resources/views/checkout.blade.php with a simple checkout form and Razorpay’s JavaScript integration:
<!DOCTYPE html>
<html>
<head>
<title>Checkout</title>
<script src="https://checkout.razorpay.com/v1/checkout.js"></script>
</head>
<body>
<h1>Checkout</h1>
<form id="payment-form">
<label>Amount (INR):</label>
<input type="number" id="amount" name="amount" required>
<button type="button" id="pay-button">Pay Now</button>
</form>
<script>
document.getElementById('pay-button').addEventListener('click', function () {
const amount = document.getElementById('amount').value;
fetch('/create-order', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': '{{ csrf_token() }}'
},
body: JSON.stringify({ amount: amount })
})
.then(response => response.json())
.then(data => {
const options = {
"key": "{{ config('services.razorpay.key') }}",
"amount": data.amount,
"currency": data.currency,
"order_id": data.order_id,
"handler": function (response) {
fetch('/verify-payment', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': '{{ csrf_token() }}'
},
body: JSON.stringify({
razorpay_order_id: response.razorpay_order_id,
razorpay_payment_id: response.razorpay_payment_id,
razorpay_signature: response.razorpay_signature
})
})
.then(res => res.json())
.then(result => {
if (result.status === 'success') {
alert('Payment successful!');
} else {
alert('Payment verification failed.');
}
});
},
"theme": {
"color": "#3399cc"
}
};
const rzp = new Razorpay(options);
rzp.open();
});
});
</script>
</body>
</html>
Step 5: Define Routes
Add routes in routes/web.php:
use App\Http\Controllers\PaymentController;
Route::get('/checkout', [PaymentController::class, 'showCheckout']);
Route::post('/create-order', [PaymentController::class, 'createOrder']);
Route::post('/verify-payment', [PaymentController::class, 'verifyPayment']);
Step 6: Handle Webhooks for Reliable Payment Updates
Webhooks notify your application about payment events like successful payments, failures, and refunds. This is important for keeping your system in sync with Razorpay.
Create a webhook controller:
php artisan make:controller WebhookController
In WebhookController.php:
use Razorpay\Api\Api;
use Illuminate\Support\Facades\Log;
class WebhookController extends Controller
{
public function handle(Request $request)
{
$webhookSecret = config('services.razorpay.webhook_secret');
$signature = $request->header('X-Razorpay-Signature');
$payload = $request->getContent();
$api = new Api(config('services.razorpay.key'), config('services.razorpay.secret'));
try {
$api->utility->verifyWebhookSignature($payload, $signature, $webhookSecret);
$event = $request->input('event');
switch ($event) {
case 'payment.captured':
// Update order status in your database
Log::info('Payment captured: ' . json_encode($request->input('payload.payment.entity')));
break;
case 'payment.failed':
Log::warning('Payment failed: ' . json_encode($request->input('payload.payment.entity')));
break;
}
return response()->json(['status' => 'ok']);
} catch (\Exception $e) {
Log::error('Webhook verification failed: ' . $e->getMessage());
return response()->json(['status' => 'error'], 400);
}
}
}
Add the route in routes/web.php:
Route::post('/webhook/razorpay', [WebhookController::class, 'handle']);
Configure this URL in your Razorpay dashboard under Webhooks and set a strong webhook secret.
Best Practices for Secure Checkout
- Always verify payment signatures on the server side before updating order status.
- Use HTTPS for all pages handling payments.
- Store API keys and secrets in environment variables, not in code.
- Log payment events for auditing and debugging.
- Handle edge cases like network failures, duplicate webhooks, and partial payments.
- Test thoroughly in Razorpay’s test mode before going live.
How This Helps Indian E-Commerce Businesses
By integrating Razorpay with Laravel, you can:
- Offer multiple payment methods (UPI, cards, wallets, net banking) preferred by Indian customers.
- Build a fast, mobile-friendly checkout that reduces cart abandonment.
- Automate payment verification and order updates using webhooks.
- Scale your platform as your business grows, thanks to Laravel’s architecture.
For startups and small businesses, this setup provides a professional, secure, and cost-effective way to accept online payments without building a complex payment system from scratch.
When to Consider Professional Help
While this tutorial covers the basics, real-world e-commerce platforms often need:
- Custom checkout flows with coupons, taxes, and shipping calculations.
- Integration with inventory, CRM, and accounting systems.
- Advanced fraud detection and compliance measures.
- Performance optimization for high-traffic stores.
If you’re building a production-ready e-commerce platform, working with an experienced Laravel development company or eCommerce development company in India can save time and reduce risks.
Conclusion
Integrating Razorpay with Laravel gives you a solid foundation for building a secure and user-friendly checkout experience for Indian customers. With proper setup, payment verification, and webhook handling, you can create a reliable payment flow that supports your business growth.
At D&D Technology, a software company in Jaipur, we help startups and businesses build custom e-commerce platforms, integrate payment gateways, and implement API integration services that fit their specific needs. If you’re planning to launch or upgrade your online store, we can help you design and develop a solution that is secure, scalable, and ready for the Indian market.
Contact us for a free consultation to discuss your e-commerce project and how we can help you deliver a seamless checkout experience.
Join the Conversation
0 Comments