Laravel 9 Cashfree Payment Gateway Integration Tutorial

Laravel 9 Cashfree Payment Gateway Integration Tutorial

Last Updated: 30 Nov, 2022

Dear friends, greetings. In this tutorial, we will learn How to Integrate Cashfree Payment Gateway in Laravel 9 Application. To acheive this, we will be using Cashfree API. Follow the below mentioned step-by-step guidance.

How to Integrate Cashfree Payment Gateway in Laravel 9?

  • Step 1: Install Fresh Laravel 9 Application
  • Step 2: Configure Database Connection
  • Step 3: Configure Cashfree Credentials
  • Step 4: Create Database Migration & Model
  • Step 5: Create Route
  • Step 6: Create Controller
  • Step 7: Create View Pages (Blade Files)
  • Step 8: Run Laravel Application

Now, we will go through the above given steps one-by-one to and get it done.

Step 1: Install Fresh Laravel 9 Application

First of all, lets install a fresh laravel 9 application. Open your terminal and run the following command:

composer create-project laravel/laravel laravel9app

Step 2: Configure Database Connection

Next, lets update database configuration in .env file as follows:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel9db
DB_USERNAME=dbusername
DB_PASSWORD=dbpassword

Step 3: Configure Cashfree Credentials

Next, go to https://www.cashfree.com/ website and login to your account. If you do not have your account created, you can create a new account. You can get your API_KEY and API_SECRET from your cashfree panel and configure it in .env file as follows:

CASHFREE_API_KEY=4875706e148d6g7wea309961075784
CASHFREE_API_SECRET=a178d51e892h5def32f3350ab32f2abcc5c3647
CASHFREE_ENDPOINT=https://test.cashfree.com/

Next, open app/config/services.php file and copy the below given code in it:

'cashfree' => [
    'api_key' => env('CASHFREE_API_KEY'),
    'api_secret' => env('CASHFREE_API_SECRET'),
    'endpoint' => env('CASHFREE_ENDPOINT')
],

Step 4: Create Database Model & Migration

Next, we need to create model and migration files to capture and store payment details in it. Run below command in therminal:

php artisan make:model CashfreePayment -m

Above command will create a model file named app/Models/CashfreePayment.php and a migration file named databse/migrations/*_create_cashfree_payments_table.php. Open the migration file and copy below code in it:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('cashfree_payments', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email');
            $table->string('mobile');
            $table->string('amount');
            $table->string('purpose');
            $table->string('payment_request_id');
            $table->string('payment_link');
            $table->string('payment_status');
            $table->string('payment_id')->nullable();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('cashfree_payments');
    }
};

Next, run the below command to migrate the table:

php artisan migrate

Step 5: Create Route

Next, open routes/web.php file and copy the below code in it:

<?php

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

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::group(['prefix' => 'cashfree'], function () {
    Route::group(['prefix' => 'payments'], function () {
        Route::get('/', [CashfreePaymentController::class, 'index']);
        Route::get('/create', [CashfreePaymentController::class, 'create']);
        Route::post('/', [CashfreePaymentController::class, 'store']);
        Route::any('/success', [CashfreePaymentController::class, 'success']);
    });
});

Step 6: Create Controller

Next, open app/Http/Controllers/CashfreePaymentController.php file and copy below given code in it:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Validator;

use App\Models\CashfreePayment;

class CashfreePaymentController extends Controller
{
    protected $rpp = 10;

    public function index(Request $request)
    {
        $request_data = $request->all();

        $view_data = [];
        
        if (!$request->ajax()){

            $view_data['title'] = 'Payment List';
            return view('cashfree.payments.index')->with($view_data);

        } else {

            $page = $request_data['page'];
            $view_data['page'] = $page;
        
            $records = CashfreePayment::orderBy('created_at', 'desc')->paginate($this->rpp);
            
            $record_starts = $this->rpp * ($page - 1) + 1;
            $record_ends = $this->rpp * ($page - 1) + count($records);
            
            $view_data['records'] = $records;
            $view_data['record_starts'] = $record_starts;
            $view_data['record_ends'] = $record_ends;
            return view('cashfree.payments.list')->with($view_data);
        }
    }

    public function create(Request $request)
    {
        $view_data['title'] = 'Create New Payment';
        return view('cashfree.payments.create')->with($view_data);
    }

    public function store(Request $request)
    {
        $posted_data = $request->all();

        $validator = Validator::make($posted_data, array(
            'name' => 'required|min:3',
            'email' => 'required',
            'mobile' => 'required',
            'amount' => 'required'
        ), array(
            'name.required' => 'Enter your name.',
            'name.min' => 'Name must be min of 3 characters.',
            'email.required' => 'Enter your email address.',
            'mobile.required' => 'Enter your mobile number.',
            'amount.required' => 'Enter your amount.'
        ));

        if ($validator->fails()) {
            return redirect()->back()->withInput($request->only('name', 'email', 'mobile', 'amount'))->withErrors($validator->errors());
        }

        try {
            $cashfree = config('services.cashfree');

            $name = trim($request->name);
            $email = trim($request->email);
            $mobile = trim($request->mobile);
            $amount = intval($request->amount);
            $purpose = 'Cashfree Invoice Payment';

            $payload = array(
                'appId' => $cashfree['api_key'],
                'secretKey' => $cashfree['api_secret'],
                'orderId' => 'CFORDER-' . Str::random(9),
                'orderAmount' => $amount,
                'orderCurrency' => 'INR',
                'orderNote' => $purpose,
                'customerName' => $name,
                'customerPhone' => $mobile,
                'customerEmail' => $email,
                'returnUrl' => url('/cashfree/payments/success')
            );

            $request_string = "";
            foreach($payload as $key=>$value) {
                $request_string .= $key.'='.rawurlencode($value).'&';
            }

            $end_point = $cashfree['endpoint'];
            $opUrl = $end_point . "api/v1/order/create";

            try {
                $ch = curl_init();
                curl_setopt($ch, CURLOPT_URL, "$opUrl?");
                curl_setopt($ch, CURLOPT_POST, count($payload));
                curl_setopt($ch, CURLOPT_POSTFIELDS, $request_string);
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
                curl_setopt($ch, CURLOPT_TIMEOUT, 60);
                $curl_result=curl_exec ($ch);
                curl_close ($ch);
                $response = json_decode($curl_result);
                if ($response->{'status'} == "OK") {
                    $paymentLink = $response->{"paymentLink"};
                    CashfreePayment::insert([
                        'name' => $name,
                        'email' => $email,
                        'mobile' => $mobile,
                        'amount' => $amount,
                        'purpose' => $purpose,
                        'payment_request_id' => $cf_request["orderId"],
                        'payment_link' => $paymentLink,
                        'payment_status' => 'created',
                        'created_at' => now(),
                        'updated_at' => now()
                    ]);
                    header('Location: ' . $paymentLink);
                    exit();
                } else {
                    echo "<pre>";
                    print_r($response);
                    exit;
                }
            } catch (Exception $e) {
                $return_data = array(
                    'status' => 'ERROR',
                    'message' => $e->getMessage()
                );
            }
        }catch (Exception $e) {
            echo "<pre>";
            print('Error: ' . $e->getMessage());
            exit;
        }
    }

    public function success(Request $request)
    {
        $request_data = $request->all();

        $payment_id = $request_data['referenceId'];
        $payment_status = trim($request_data['txStatus']);
        $payment_request_id = $request_data['orderId'];

        $cf_payment = CashfreePayment::where('payment_request_id', $payment_request_id)->first();
        
        if (strtolower($payment_status) == 'success') {
            $cf_payment->payment_status = $payment_status;
            $cf_payment->payment_id = $payment_id;
            $cf_payment->save();
            dd('Payment Successful');
        } else {
            dd('Payment Failed!');
        }
        dd($request_data);
    }
}

Step 7: Create View Pages (Blade Files)

Next, create the below given blade files under resources/views/cashfree/payments directory:

resources/views/cashfree/payments/index.blade.php

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Laravel 9 Cashfree Payment Gateway Integration Tutorial</title>
    <meta name="csrf-token" content="{{ csrf_token() }}">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
    <script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
</head>
<body>
<div class="container mt-3">
    <div class="row text-center"><h1>Laravel 9 Cashfree Payment Gateway Integration Tutorial</h1></div>
    <div class="row" id="result-div"><strong style="color: #0cf;text-align: center;">Fetching records...</strong></div>
</div>
<script>
var pageNo = 1;
$(function(){
    $.ajax({
        url: "{{url('cashfree/payments')}}",
        type: "GET",
        dataType: "HTML",
        data: {
            'page': pageNo
        }
    }).done(function(data){
        $("#result-div").empty().html(data);
    }).fail(function(jqXHR, ajaxOptions, thrownError){
        console.log('No response from server');
    }).always(function(){
    });
});
</script>
</body>
</html>

resources/views/cashfree/payments/list.blade.php

<div class="col-12 mb-3">
    <div class="card text-white bg-success mb-3">
        <div class="card-header">
            <h3 class="card-title" style="display: inline-block;">Payments List</h3>
            <a href="{{url('/cashfree/payments/create')}}" class="btn btn-primary float-end">Create New Payment</a>
        </div>
        <div class="card-body table-responsive">
            <table class="table table-striped text-white">
                <thead>
                <tr style="text-transform: uppercase;">
                    <th>#</th>
                    <th>Name</th>
                    <th>EMail</th>
                    <th>Mobile</th>
                    <th>Amount</th>
                    <th>Purpose</th>
                    <th>Status</th>
                    <th>PaymentId</th>
                    <th>CreatedAt</th>
                </tr>
                </thead>
                <tbody>
                @if($records->count() > 0)
                    @foreach($records as $rec)
                    <tr>
                        <td>{{$loop->iteration}}</td>
                        <td>{{$rec->name}}</td>
                        <td>{{$rec->email}}</td>
                        <td>{{$rec->mobile}}</td>
                        <td>{{$rec->amount}}</td>
                        <td>{{$rec->purpose}}</td>
                        <td><button class="btn btn-info">{{$rec->payment_status}}</button></td>
                        <td>{{$rec->payment_id}}</td>
                        <td>{{$rec->created_at}}</td>
                    </tr>
                    @endforeach
                @else
                    <tr class="text-center"><td colspan="8">Record not found!!</td></tr>
                @endif
                </tbody>
            </table>
            {!! $records->links() !!}
        </div>
    </div>
</div>

resources/views/cashfree/payments/create.blade.php

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Laravel 9 Cashfree Payment Gateway Integration Tutorial</title>
    <meta name="csrf-token" content="{{ csrf_token() }}">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
</head>
<body>
    <div class="container mt-3">
        <div class="row justify-content-center">
            <div class="col-12 col-md-6 mb-3">
                <div class="card text-dark bg-success mb-3">
                    <div class="card-header">
                        <h3 class="card-title text-white" style="display: inline-block;">Create New Payment</h3>
                        <a href="{{url('/cashfree/payments')}}" class="btn btn-primary float-end">Payments List</a>
                    </div>
                    <div class="card-body">
                        <form action="{{ url('cashfree/payments') }}" method="POST" name="laravel9-cashfree-integration">
                            {{ csrf_field() }}
                            <div class="form-floating">
                              <input type="text" class="form-control" name="name" id="name" value="{{ old('name') }}" placeholder="name">
                              <label for="name">Full Name</label>
                            </div>
                            <div class="form-floating">
                              <input type="email" class="form-control" name="email" id="email" value="{{ old('email') }}" placeholder="email">
                              <label for="email">Email Address</label>
                            </div>
                            <div class="form-floating">
                              <input type="text" class="form-control" name="mobile" id="mobile" value="{{ old('mobile') }}" placeholder="mobile">
                              <label for="mobile">Mobile Number</label>
                            </div>
                            <div class="form-floating">
                              <input type="text" class="form-control" name="amount" id="amount" value="{{ old('amount') }}" placeholder="amount">
                              <label for="amount">Amount</label>
                            </div>
                            <button class="w-100 btn btn-lg btn-primary" type="submit">Place Order</button>
                        </form>
                        @if ($errors->any())
                        <div class="alert alert-danger text-start" role="alert">
                            <strong>Opps!</strong> Something went wrong<br>
                            <ul>
                            @foreach ($errors->all() as $error)
                                <li>{{ $error }}</li>
                            @endforeach
                            </ul>
                        </div>
                        @endif
                    </div>
                </div>
            </div>
        </div>
    </div>
</body>
</html>

Step 8: Run Laravel Application

Great, we are all set. Lets start the application now by using below command in terminal:

php artisan serve

Once development server is started, in your browser, open below URL:

http://127.0.0.1:8000/cashfree/payments

HAPPY LEARNING:)

Note: You can use below given link to get Test Card Credentials to test your application:

https://docs.cashfree.com/docs/data-to-test-integration

Thank You, Please Share.