How to Implement PayU in Laravel?

This manual offers a detailed, step-by-step procedure for integrating the PayU payment gateway into a PHP or Laravel application, without the need for any packages. While my preference leans towards Laravel, this method is equally effective for PHP or any other PHP-based framework.

Step 1 : Get API Credentials

1. Navigate to the following URL and log in to Merchant Dashboard : https://onboarding.payu.in/app/account

2. Navigate to Payment Gateway

3. You will get your API Credentials which are Merchant Key & Salt Key (We will be using version 2)


Step 2 : Create a Controller.

To create a controller please execute the provided command.

php artisan make:controller PaymentController
Step 3 : Create Routes.

Next, we'll construct a payment form to gather the necessary details and confirmations from the user. Following this, we'll process the payment. In the callback, we'll verify the payment and determine whether it was successful. So, let's start by creating some routes in the web.php file.

//PAYMENT FORM
Route::get('payu-payment-form', [\App\Http\Controllers\PaymentController::class, 'index'])->name('payu-payment-form');
//SUCCESS CALLBACK ROUTE
Route::get('payu-success', [\App\Http\Controllers\PaymentController::class, 'success'])->name('payu-success');
//FAILURE CALLBACK ROUTE
Route::get('payu-failure', [\App\Http\Controllers\PaymentController::class, 'failure'])->name('payu-failure');
Step 4 : Payment Form and Processing

We'll create a function named index in PaymentController.php. This function will be responsible for collecting data and executing the generating payment data.

public function index()
{
    $testMode = 1;

    if($testMode)
    {
        // test / sandbox
        $endpoint = 'https://test.payu.in/_payment';
    }
    else
    {
        // production / live
        $endpoint = 'https://secure.payu.in/_payment';
    }

    $saltKey = 'MIIEvAIBADANBg****';
    $merchantKey = 'Pw****';
    $txnid = time().rand(1000,9999);
    $amount = 10;
    $firstname = 'John';
    $lastname = 'Doe';
    $userName = str_replace(' ', '', $firstname);
    $userEmail = 'test@example.com';
    $productInfo = 'Life';

    $successUrl = route('payu-success');
    $failureUrl = route('payu-failure');

    // sha512(key|txnid|amount|productinfo|firstname|email|udf1|udf2|udf3|udf4|udf5||||||SALT)
    $hashData = $merchantKey.'|'.$txnid.'|'.$amount.'|'.$productInfo.'|'.$userName.'|'.$userEmail.'|||||||||||'.$saltKey;

    $hashedKey = strtolower(hash('sha512',$hashData));


    $formData = [
        'endpoint' => $endpoint,
        'key' => $merchantKey,
        'txnid' => $txnid,
        'amount' => $amount,
        'firstname' => $firstname,
        'lastname' => $lastname,
        'email' => $userEmail,
        'productinfo' => $productInfo,
        'surl' => $successUrl,
        'furl' => $failureUrl,
        'hash' => $hashedKey,
    ];

    return view('payu.payment-form',compact('formData'));
}

Now lets create a payment form,


resources/views/payu/payment-form.blade.php


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>PayU Payment Gateway</title>

    <!-- BOOTSTRAP -->
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />

    <!-- Styles -->
    <style>
        body {
            background: #f7f7f7;
        }

        .form-box {
            max-width: 500px;
            margin: auto;
            padding: 50px;
            background: #ffffff;
            border: 10px solid #f2f2f2;
            margin-top: 100px;
            margin-bottom: 100px;
        }

        h1, p {
            text-align: center;
        }

        input, textarea {
            width: 100%;
        }
    </style>
</head>
<body>
<div class="form-box">
    <h1>Pay with PayU</h1>
    <form action="{{ $formData['endpoint'] }}" method="post" style="text-align: center;margin-top: 50px;">
        @csrf
        <input type="hidden" name="key" value="{{ $formData['key'] }}">
        <input type="hidden" name="txnid" value="{{ $formData['txnid'] }}">
        <input type="hidden" name="productinfo" value="{{ $formData['productinfo'] }}">
        <input type="hidden" name="amount" value="{{ $formData['amount'] }}">
        <input type="hidden" name="email" value="{{ $formData['email'] }}">
        <input type="hidden" name="firstname" value="{{ $formData['firstname'] }}">
        <input type="hidden" name="lastname" value="{{ $formData['lastname'] }}">
        <input type="hidden" name="surl" value="{{ $formData['surl'] }}">
        <input type="hidden" name="furl" value="{{ $formData['furl'] }}">
        <input type="hidden" name="hash" value="{{ $formData['hash'] }}">
        <!--- You can add your custom fields here --->
        <button type="submit" class="btn btn-primary">Pay ${{ $formData['amount'] }}</button>
    </form>
</div>
</body>
</html>
Step 5 : Managing Post Callbacks

Now because PayU payment callback will be in post method and there will be no csrf token passed from PayU side, So we need to exclude csrf verification for callback urls, To do that we need to add callback urls in a middleware located in app/Http/Middleware/VerifyCsrfToken.php

<?php

namespace App\Http\Middleware;

use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;

class VerifyCsrfToken extends Middleware
{
    // NOTE : This are URL not route names
    protected $except = [
        'payu-success',
        'payu-failure',
    ];
}
Step 6 : Callbacks

To manage callbacks we need to create success and failure functions in PaymentController.php.

public function success(Request $request)
{
    // manage payment success here
    if($request->status == 'success')
    {
        $txnid = $request->txnid;
        $paymentmethod = $request->mode;
    }
    else
    {
         // handle your error message here
    }
}

public function failure(Request $request)
{
    // handle your error message here
    dd($request->all());
}
Step 7 : Usage

When user click on pay button they will be redirect to PayU hosted checkout page, Which will look something like this : 


Use credentials for test payments.


Test Card :

Debit Mastercard

Card : 5118 7000 0000 0003

Expiry: 12/24 (any future date)

CVV: 111

OTP : 123456

Name : Test (any name)

            

EMI Test Cards :

HDFC CC EMI

Card : 4453 3410 6587 6437

Expiry: 05/25 (any future date)

CVV: 123 (any random three-digit number)

OTP : 123456 (any six-digit number)

Name : Test (any name)

Mobile : 9123412345 (mandatory for EMIs)

            

International Payments or DCC :

Bank OF America

Card : 4020 2150 0767 7976

Expiry: 04/2038 (any future date)

CVV: 976

OTP : 677976

Name : Test (any name)

Mobile : 9123412345 (mandatory for EMIs)

            

Test UPI ID :

anything@payu

            

Test Net Banking Credentials :

Username : payu

Password: payu

OTP : 12345

            

Test Wallets :

There is already test wallet in list but you can use paytm as well

Vendor : PayTM

Mobile Number : 7777777777

OTP : 888888