Laravel Jquery Javascript

How to Integrate Razorpay Payment Gateway in Laravel

Razorpay is a widely used payment gateway in India that allows businesses to accept online payments securely and efficiently. In this article, we will explore how to integrate the Razorpay payment gateway with a Laravel web application. We'll create a simple checkout form that allows users to make payments and handle the payment success and failure scenarios.

Before we start, make sure you have the following prerequisites:

  1. Laravel installed on your system.
  2. A Razorpay account and API credentials (API Key and Secret Key).

Step 1: Install Razorpay SDK

Let's begin by installing the Razorpay PHP SDK using Composer. Open a terminal and run the following command:

composer require razorpay/razorpay

Step 2: Configure Razorpay Credentials

Next, configure your Razorpay API credentials in the config/services.php file. Add the following code to the array:

'razorpay' => [
   'key' => env('RAZORPAY_KEY'),
   'secret' => env('RAZORPAY_SECRET'),
],

Also, make sure to set your Razorpay API Key and Secret in the .env file like this:

RAZORPAY_KEY=your_razorpay_api_key
RAZORPAY_SECRET=your_razorpay_api_secret

Step 3: Create the RazorpayController

Now, let's create a controller named RazorpayController to handle the payment process. Run the following command in the terminal:

php artisan make:controller RazorpayController

In the RazorpayController.php file, add the necessary methods to handle payment creation and success/failure scenarios. The code for the RazorpayController can be found in the provided code snippet.

<?php
namespace App\Http\Controllers;
use Razorpay\Api\Api;
use Illuminate\Http\Request;
class RazorpayController extends Controller
{
   public function pay()
   {
       return view('payment.pay');
   }
   function create(Request $request)
   {
       $this->validate($request, [
           'name' => 'required',
           'phone' => 'required',
           'email' => 'required'
       ]);
       $api = new Api(config('services.razorpay.key'), config('services.razorpay.secret'));
       $order = $api->order->create(
           array(
               'amount' => (20 * 100),
               'currency' => 'INR',
               'notes' => ['testing payment..']
           )
       );
       return response()->json(($order->toArray() + $request->all()));
   }
   function success(Request $request)
   {
       if ($request->razorpay_order_id) {
           try {
               $api = new Api(config('services.razorpay.key'), config('services.razorpay.secret'));
               // Verify the payment
               $payment = $api->order->fetch($request->razorpay_order_id);
               if ($payment->status === 'attempted') {
                   // Payment is successful
                   return view('payment.success', compact('payment'));
               }
           } catch (\Throwable $th) {
               //throw $th;
           }
       }
       // Payment failed
       return view('payment.failure');
   }
}

Step 4: Create Blade Views

Create the Blade views (pay.blade.php, success.blade.php, and failure.blade.php) and place them in the resources/views/payment directory.

resources\views\payment\pay.blade.php

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <meta http-equiv="X-UA-Compatible" content="ie=edge">
   <meta name="csrf-token" content="{{ csrf_token() }}">
   <title>Document</title>
   <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
   <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</head>
<body>
   <div class="container">
       <div class="py-5 text-center">
           <h2>Checkout form</h2>
       </div>
       <div class="row">
           <div class="col-md-4 order-md-2 mb-4">
               <h4 class="d-flex justify-content-between align-items-center mb-3">
                   <span class="text-muted">Your cart</span>
                   <span class="badge badge-secondary badge-pill">3</span>
               </h4>
               <ul class="list-group mb-3">
                   <li class="list-group-item d-flex justify-content-between lh-condensed">
                       <div>
                           <h6 class="my-0">Product name</h6>
                           <small class="text-muted">Brief description</small>
                       </div>
                       <span class="text-muted">$12</span>
                   </li>
                   <li class="list-group-item d-flex justify-content-between lh-condensed">
                       <div>
                           <h6 class="my-0">Second product</h6>
                           <small class="text-muted">Brief description</small>
                       </div>
                       <span class="text-muted">$8</span>
                   </li>
                   <li class="list-group-item d-flex justify-content-between">
                       <span>Total (USD)</span>
                       <strong>$20</strong>
                   </li>
               </ul>
           </div>
           <div class="col-md-8 order-md-1">
               <h4 class="mb-3">Billing address</h4>
               <form action="{{ route('payment.create') }}" method="POST" class="payment_create needs-validation" novalidate>
                   <div class="row">
                       <div class="col-md-6 mb-3">
                           <label for="name">Name</label>
                           <input type="text" class="form-control" name="name" placeholder="" value="" required>
                       </div>
                       <div class="col-md-6 mb-3">
                           <label for="phone">Phone</label>
                           <input type="text" class="form-control" name="phone" placeholder="" value="" required>
                       </div>
                       <div class="col-md-12 mb-3">
                           <label for="email">Email</label>
                           <input type="text" class="form-control" name="email" placeholder="" value="" required>
                       </div>
                   </div>
                   <hr class="mb-4">
                   <h4 class="mb-3">Payment</h4>
                   <div class="d-block my-3">
                       <div class="custom-control custom-radio">
                           <input id="credit" name="paymentMethod" type="radio" class="custom-control-input" checked required>
                           <label class="custom-control-label" for="credit">Debit/Credit Card/UPI/Net Banking</label>
                       </div>
                   </div>
                   <hr class="mb-4">
                   <button class="btn btn-primary btn-lg btn-block" type="submit">Place Order</button>
               </form>
           </div>
       </div>
   </div>
   <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
   {{-- razorpay --}}
   <script src="https://checkout.razorpay.com/v1/checkout.js"></script>
   <script>
       $('.payment_create').submit(function(e) {
           e.preventDefault();
           var form = $(this)
           $.ajax({
               headers: {
                   'X-CSRF-Token': $('meta[name=csrf-token]').attr('content')
               },
               url: form.attr('action'),
               type: 'POST',
               data: form.serialize(),
               success: function(output) {
                   var options = {
                       "key": "{{ config('services.razorpay.key') }}",
                       "amount": output.amount * 100, // 2000 paise = INR 20
                       "currency": output.currency,
                       "name": "{{ config('app.name') }}",
                       "description": "Secure Payments Transaction",
                       "order_id": output.id,
                       "prefill": {
                           "name": output.name,
                           "email": output.email,
                           "contact": output.phone
                       },
                       "handler": function(response) {
                           console.log(response);
                           var url = '{{ route('payment.success') }}?razorpay_order_id='+response.razorpay_order_id;
                           window.location.replace(url);
                       },
                       "theme": {
                           "color": "#af7c7c"
                       },
                       "modal": {
                           "ondismiss": function() {
                               // window.location.replace('{{ route('payment.success') }}');
                           }
                       }
                   };
                   var rzp1 = new Razorpay(options);
                   rzp1.open();
               },
               error: function(xhr, textStatus, thrownError) {
                   $('.error').remove();
                   $.each(xhr.responseJSON.errors, function(index, value) {
                       form.find("input[name=" + index + "],select[name=" + index + "],textarea[name=" + index + "],select[name='" + index + "[]']").after("<span class='text-danger error'>" + value[0] + "</span>");
                   });
                   if (xhr.status == 401) {}
               }
           });
       });
   </script>
</body>
</html>

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">
   <meta http-equiv="X-UA-Compatible" content="ie=edge">
   <meta name="csrf-token" content="{{ csrf_token() }}">
   <title>Document</title>
   <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
   <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</head>
<body>
   <div class="container">
       <div class="py-5 text-center">
           <!-- Display payment success message -->
           <h1>Payment Successful!</h1>
           <h2>Transaction ID: {{ $payment->id }}</h2>
       </div>
   </div>
</body>
</html>

resources\views\payment\failure.blade.php

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <meta http-equiv="X-UA-Compatible" content="ie=edge">
   <meta name="csrf-token" content="{{ csrf_token() }}">
   <title>Document</title>
   <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
   <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</head>
<body>
   <div class="container">
       <div class="py-5 text-center">
           <h1>Payment Failed!</h1>
       </div>
   </div>
</body>
</html>

Step 5: Start the Development Server

We are almost ready to test the Razorpay integration. Start the Laravel development server by running the following command in the terminal:

php artisan serve

Step 6: Test the Payment Process

Visit http://localhost:8000/pay in your web browser. You will see a checkout form with billing address fields and a "Place Order" button.

Fill in the required details (name, phone, email) and click on the "Place Order" button. The Razorpay checkout modal will open, allowing you to complete the payment using various payment methods (Debit/Credit Card, UPI, Net Banking).

After completing the payment, you will be redirected to the payment success page (payment.success) if the payment is successful, or to the payment failure page (payment.failure) if the payment fails.

Leave A Comment