Razorpay Payment setup In Laravel

In this blog, you will integrate the Razorpay payment gateway with Laravel.

  1. Razorpay Account
  2. Create Razorpay Account
  3. Create Laravel Application
  4. Install Razorpay Package
  5. Setting Razorpay Credentials
  6. Create Necessary Routes
  7. Create Razorpay Controller
  8. Create Views

Create Razorpay Account

Before starting this integration, we need to create a Razorpay account and get your Key Id from Razorpay. You can create a new account using this link: Razorpay

Razorpay provides test and live dashboard mode. Now, you will need API keys for the payment process. If you are a developer and want to test your payment gateway then my suggestion is to use the test key otherwise you can get the business key by completing KYC and getting the live key.

Create Laravel Application

First of all, Let’s create a new Laravel application. To create a new application, open the terminal or command prompt and run this command :

composer create-project --prefer-dist laravel/laravel RPay

Install the Razorpay Package

For performing payments using Razorpay, we need to install razorpay/razorpay package in our Laravel application.

Package Installation Command :

composer require razorpay/razorpay

In the Razorpay package, all necessary methods are already defined. We can use it as per our requirement.

Setting Razorpay Credentials in Our Application

After installing the package, we need to set the Razorpay key in either .env file or create a new config file. In this example, we are going to set our Razorpay’s account razor_key and razor_secret in the .env file so make the following changes to the .env file.

RAZORPAY_KEY=***********
RAZORPAY_SECRET=************

Creating Required Web Routes

Here We are going to create two new routes and we will load payment details input into a welcome page. The first route will load the payment process based on user input. The second route will be payment and return response to the welcome page.

Modify routes\web.php file as below :

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\RazorpayController;

Route::get('/', function () {
    return view('welcome');
});
Route::post('/payment',[RazorpayController::class,'PaymentView'])->name('payment_view');
Route::post('/make-payment',[RazorpayController::class,'MakePayment'])->name('make_payment');

Create Razorpay Controller

Make a new controller that will handle Razorpay payment-related processes like show the payment page and processing payments. So let’s create RazorpayController with the below command :

php artisan make:controller RazorpayController

This command will create a RazorpayController controller in the app\Http\Controller folder. Now we’ll modify the controller to handle payment processes :

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Razorpay\Api\Api;
use Illuminate\Support\Str;

class RazorpayController extends Controller
{
    public function PaymentView(Request $request){
        $receiptId = Str::random(20);

        $api = new Api(env('RAZORPAY_KEY'), env('RAZORPAY_SECRET'));
        //Create Order with user inputted amount
        $order = $api->order->create(array(
            'receipt' => $receiptId,
            'amount' => $request->all()['amount'] * 100,
            'currency' => 'INR'
            )
        );

        // Return response on payment page
        $response = [
            'orderId' => $order['id'],
            'razorpayId' => env('RAZORPAY_KEY'),
            'amount' => $request->all()['amount'] * 100,
            'name' => $request->all()['name'],
            'currency' => 'INR',
            'email' => $request->all()['email'],
            'contactNumber' => $request->all()['contactNumber'],
            'address' => $request->all()['address'],
            'description' => 'Testing description',
        ];
        return view('payment',compact('response'));
    }
    public function MakePayment(Request $request){
        //Let's validate
        $paymentStatus = $this->ValidateOrderID(
            $request->all()['rzp_signature'],
            $request->all()['rzp_paymentid'],
            $request->all()['rzp_orderid']
        );
        if($paymentStatus == true)
        {
            $message = "Success";
        }
        else{
            $message = "Fail";
        }
        return view('welcome',compact('message'));
    }
    private function ValidateOrderID($signature,$paymentId,$orderId)
    {
        try
        {
            $api = new Api(env('RAZORPAY_KEY'), env('RAZORPAY_SECRET'));
            $attributes  = array('razorpay_signature'  => $signature,  'razorpay_payment_id'  => $paymentId ,  'razorpay_order_id' => $orderId);
            $order  = $api->utility->verifyPaymentSignature($attributes);
            return true;
        }
        catch(\Exception $e)
        {
            return false;
        }
    }
}

In this controller, we have created two methods. First will load or initialize Razorpay payment integration and make payment using the JavaScript library. The second method validates payment and returns a response to the welcome page.

Create Views

Now we will modify the welcome page to take user input. Here user will insert basic info and payment amount (This webpage is used for testing purposes in the actual payment process payment amount is processed by server/service logic) and load the Razorpay payment view. So let’s modify the welcome view :

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Laravel</title>
    <!-- Fonts -->
    <link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap" rel="stylesheet">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet">
    <style type="text/css">
        @import url('https://fonts.googleapis.com/css?family=PT+Sans');
        body{
          background: #fff;
          font-family: 'PT Sans', sans-serif;
        }
        h2{
          padding-top: 1.5rem;
        }
        a{
          color: #333;
        }
        a:hover{
          color: #da5767;
          text-decoration: none;
        }
        .card{
          border: 0.40rem solid #f8f9fa;
          top: 10%;
        }
        .form-control{
          background-color: #f8f9fa;
          padding: 20px;
          padding: 25px 15px;
          margin-bottom: 1.3rem;
        }
        .form-control:focus {
            color: #000000;
            background-color: #ffffff;
            border: 3px solid #da5767;
            outline: 0;
            box-shadow: none;
        }
        .btn{
          padding: 0.6rem 1.2rem;
          background: #da5767;
          border: 2px solid #da5767;
        }
        .btn-primary:hover {
            background-color: #df8c96;
            border-color: #df8c96;
            transition: .3s;
        }
    </style>
</head>

<body class="antialiased">
    <div class="relative flex items-top justify-center min-h-screen bg-gray-100 dark:bg-gray-900 sm:items-center py-4 sm:pt-0">
        <div class="container">
            <div class="row justify-content-center">
                @isset ($message)
                    @if($message == "Success")
                        <div class="alert alert-success" role="alert">
                            Payment Received
                        </div>
                    @else
                        <div class="alert alert-danger" role="alert">
                            Payment Failed
                        </div>
                    @endif
                @endisset
            </div>
            <div class="row justify-content-center">
                <div class="col-md-5">
                    <div class="card">
                        <h2 class="card-title text-center">Make Payment Now</h2>
                        <div class="card-body py-md-4">
                            <form action="{{route('payment_view')}}" method="POST">
                                @csrf
                                <div class="form-group">
                                    <input type="text" class="form-control" id="name" placeholder="Name" name="name">
                                </div>
                                <div class="form-group">
                                    <input type="email" class="form-control" id="email" placeholder="Email" name="email">
                                </div>
                                <div class="form-group">
                                    <input type="number" class="form-control" id="email" placeholder="Contact Number" name="contactNumber">
                                </div>

                                <div class="form-group">
                                    <input type="number" class="form-control" id="amount" placeholder="amount" name="amount">
                                </div>

                                <div class="form-group">
                                    <input type="text" class="form-control" name="address" placeholder="Address">
                                </div>
                                <div class="d-flex flex-row align-items-center justify-content-between">
                                    <button class="btn btn-primary">Pay</button>
                                </div>
                            </form>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</body>
</html>

After the modification of the welcome view, we need to create another view that will handle the payment process.

Create a new view file at resources\view\payment.blade.php and add the following code :

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Razorpay Payment Intregration</title>
</head>
<body>
    <button id="rzp-button1" hidden>Pay</button>
    <script src="https://checkout.razorpay.com/v1/checkout.js"></script>
    <script>
        var options = {
            "key": "{{$response['razorpayId']}}", // Razorpay ID
            "amount": "{{$response['amount']}}", // Amount
            "currency": "{{$response['currency']}}",
            "name": "{{$response['name']}}",
            "description": "{{$response['description']}}",
            "image": "https://example.com/your_logo", // replace this link with actual logo
            "order_id": "{{$response['orderId']}}", //Created Order id in first method
            "handler": function (response){
                document.getElementById('rzp_paymentid').value = response.razorpay_payment_id;
                document.getElementById('rzp_orderid').value = response.razorpay_order_id;
                document.getElementById('rzp_signature').value = response.razorpay_signature;
                document.getElementById('rzp-paymentresponse').click();
            },
            "prefill": {
                "name": "{{$response['name']}}",
                "email": "{{$response['email']}}",
                "contact": "{{$response['contactNumber']}}"
            },
            "notes": {
                "address": "{{$response['address']}}"
            },
            "theme": {
                "color": "#F37254"
            }
        };
        var rpay = new Razorpay(options);
        window.onload = function(){
            document.getElementById('rzp-button1').click();
        };

        document.getElementById('rzp-button1').onclick = function(e){
            rpay.open();
            e.preventDefault();
        }
    </script>
    <form action="{{route('make_payment')}}" method="POST" hidden>
            <input type="hidden" value="{{csrf_token()}}" name="_token" />
            <input type="text" class="form-control" id="rzp_paymentid"  name="rzp_paymentid">
            <input type="text" class="form-control" id="rzp_orderid" name="rzp_orderid">
            <input type="text" class="form-control" id="rzp_signature" name="rzp_signature">
        <button type="submit" id="rzp-paymentresponse" class="btn btn-primary">Submit</button>
    </form>
</body>
</html>

When the user fills welcome page form then we’ll send the user to this view and load the payment library.

Testing Razorpay Payment Gateway

For testing our application, we’ll run our artisan server using the below command :

php artisan serve

Open your browser and go to http://127.0.0.1:8000 and test your application.

Test your payment process using these two UPI IDs:

  • Success: success@razorpay
  • Fail: failure@razorpay

Payment methods can be tested using a card that will pay domestic/international payments using the Razorpay payment Test.