Skip to main content

Overview

Razorpay is India’s leading payment gateway, enabling businesses to accept payments via credit cards, debit cards, net banking, UPI, and wallets. The integration supports seamless checkout with INR currency.

Prerequisites

  • Razorpay account (Sign up here)
  • KYC verification completed
  • API keys from Razorpay Dashboard

Configuration

Step 1: Get Razorpay API Keys

1

Login to Razorpay Dashboard

2

Navigate to Settings

Go to SettingsAPI Keys
3

Generate Keys

Click Generate Test Keys for testing or Generate Live Keys for production
4

Copy Credentials

Copy Key ID and Key Secret
Keep your Key Secret confidential. Never expose it in client-side code.

Step 2: Configure Environment Variables

Add Razorpay credentials to .env:
.env
# Razorpay Configuration
RAZOR_KEY=rzp_test_...
RAZOR_SECRET=...
Use rzp_test_ prefix for test keys and rzp_live_ for production keys

Step 3: Enable Razorpay in Admin Panel

1

Access Admin Dashboard

Login to your admin panel
2

Configure Payment Methods

Navigate to Setup & ConfigurationsPayment Methods
3

Activate Razorpay

Toggle Razorpay to Active and save

Implementation Details

Controller Location

app/Http/Controllers/Payment/RazorpayController.php

Payment Flow

1

Create Razorpay Order

System creates an order using Razorpay API
app/Http/Controllers/Payment/RazorpayController.php
public function pay(Request $request)
{
    $payment_track = array();
    $api = new Api(env('RAZOR_KEY'), env('RAZOR_SECRET'));
    
    if (Session::has('payment_type')) {
        if (Session::get('payment_type') == 'cart_payment') {
            $combined_order = CombinedOrder::findOrFail(Session::get('combined_order_id'));
            $res = $api->order->create(array(
                'receipt' => '123', 
                'amount' => round($combined_order->grand_total) * 100, 
                'currency' => 'INR', 
                'notes' => array(
                    'key1' => 'value3', 
                    'key2' => 'value2'
                )
            ));

            return view('frontend.razor_wallet.order_payment_Razorpay', compact('combined_order', 'res'));
        }
    }
}
2

Display Razorpay Checkout

Customer sees Razorpay checkout form with payment options
3

Capture Payment

After customer completes payment, verify and capture
app/Http/Controllers/Payment/RazorpayController.php
public function payment(Request $request)
{
    $input = $request->all();
    $api = new Api(env('RAZOR_KEY'), env('RAZOR_SECRET'));

    // Fetch payment information
    $payment = $api->payment->fetch($input['razorpay_payment_id']);
    
    if (count($input) && !empty($input['razorpay_payment_id'])) {
        $payment_detalis = null;
        try {
            // Verify Payment Signature
            $attributes = array(
                'razorpay_order_id' => $input['razorpay_order_id'],
                'razorpay_payment_id' => $input['razorpay_payment_id'],
                'razorpay_signature' => $input['razorpay_signature']
            );
            $api->utility->verifyPaymentSignature($attributes);
            
            // Capture payment
            $response = $api->payment->fetch($input['razorpay_payment_id'])->capture(array(
                'amount' => $payment['amount']
            ));
            
            $payment_detalis = json_encode(array(
                'id' => $response['id'], 
                'method' => $response['method'], 
                'amount' => $response['amount'], 
                'currency' => $response['currency']
            ));
        } catch (\Exception $e) {
            \Session::put('error', $e->getMessage());
            return redirect()->back();
        }
    }
}
4

Complete Order

System processes the successful payment
app/Http/Controllers/Payment/RazorpayController.php
if (Session::has('payment_type')) {
    if (Session::get('payment_type') == 'cart_payment') {
        return (new CheckoutController)->checkout_done(Session::get('combined_order_id'), $payment_detalis);
    } elseif (Session::get('payment_type') == 'wallet_payment') {
        return (new WalletController)->wallet_payment_done(Session::get('payment_data'), $payment_detalis);
    }
}

Currency and Amount Format

Important: Razorpay requires amounts in paise (smallest currency unit)
'amount' => round($combined_order->grand_total) * 100
Example: ₹100.00 = 10000 paise
Razorpay only supports INR currency:
'currency' => 'INR'

Payment Signature Verification

For security, always verify payment signatures:
$attributes = array(
    'razorpay_order_id' => $input['razorpay_order_id'],
    'razorpay_payment_id' => $input['razorpay_payment_id'],
    'razorpay_signature' => $input['razorpay_signature']
);
$api->utility->verifyPaymentSignature($attributes);
Signature verification prevents payment tampering and ensures the payment actually came from Razorpay

Dependencies

Razorpay PHP SDK is included via Composer:
composer.json
"require": {
    "razorpay/razorpay": "2.*"
}
If not installed:
composer require razorpay/razorpay

Payment Methods Supported

Razorpay supports multiple payment methods:
  • Cards: Credit & Debit cards (Visa, Mastercard, RuPay, Amex)
  • Net Banking: 50+ banks
  • UPI: Google Pay, PhonePe, Paytm, BHIM
  • Wallets: Paytm, PhonePe, Freecharge, Mobikwik
  • EMI: Credit card EMI options
  • Cardless EMI: ZestMoney, ePayLater

Testing

Test Mode

Use test API keys during development:
.env
RAZOR_KEY=rzp_test_...
RAZOR_SECRET=...

Test Card Numbers

Card NumberCVVDescription
4111 1111 1111 1111AnySuccessful payment
4012 8888 8888 1881AnySuccessful payment
5555 5555 5555 4444AnyMastercard success
Use any future expiry date and any CVV.

Test UPI IDs

success@razorpay

Test Net Banking

Select any bank and use credentials:
  • Username: razorpay
  • Password: razorpay

View Templates

Razorpay payment requires blade templates:
resources/views/frontend/razor_wallet/
├── order_payment_Razorpay.blade.php
├── wallet_payment_Razorpay.blade.php
├── customer_package_payment_Razorpay.blade.php
└── seller_package_payment_Razorpay.blade.php
Each template includes the Razorpay checkout script:
<script src="https://checkout.razorpay.com/v1/checkout.js"></script>

Supported Payment Types

Cart Payment

if (Session::get('payment_type') == 'cart_payment') {
    $combined_order = CombinedOrder::findOrFail(Session::get('combined_order_id'));
    $res = $api->order->create(array(
        'receipt' => '123', 
        'amount' => round($combined_order->grand_total) * 100, 
        'currency' => 'INR'
    ));
    return view('frontend.razor_wallet.order_payment_Razorpay', compact('combined_order', 'res'));
}

Wallet Payment

elseif (Session::get('payment_type') == 'wallet_payment') {
    $res = $api->order->create(array(
        'receipt' => '123', 
        'amount' => Session::get('payment_data')['amount'] * 100, 
        'currency' => 'INR'
    ));
    return view('frontend.razor_wallet.wallet_payment_Razorpay', compact('res'));
}

Package Payments

elseif (Session::get('payment_type') == 'customer_package_payment') {
    $customer_package = \App\Models\CustomerPackage::findOrFail(Session::get('payment_data')['customer_package_id']);
    $res = $api->order->create(array(
        'receipt' => '123', 
        'amount' => $customer_package->amount * 100, 
        'currency' => 'INR'
    ));
    return view('frontend.razor_wallet.customer_package_payment_Razorpay', compact('res'));
}

User Authentication

Razorpay controller can handle guest users during payment:
if ($payment->notes['user_id']) {
    $user = User::find((int) $payment->notes['user_id']);
    Auth::login($user);
}

Error Handling

Comprehensive error handling:
try {
    $attributes = array(
        'razorpay_order_id' => $input['razorpay_order_id'],
        'razorpay_payment_id' => $input['razorpay_payment_id'],
        'razorpay_signature' => $input['razorpay_signature']
    );
    $api->utility->verifyPaymentSignature($attributes);
    $response = $api->payment->fetch($input['razorpay_payment_id'])->capture(array('amount' => $payment['amount']));
} catch (\Exception $e) {
    \Session::put('error', $e->getMessage());
    return redirect()->back();
}

Troubleshooting

Cause: Invalid signature or tampered payment dataSolution:
  • Ensure you’re passing correct razorpay_order_id, razorpay_payment_id, and razorpay_signature
  • Verify API secret is correct in .env
  • Check for any modifications to payment data
Cause: Amount not in paiseSolution:
// Correct: multiply by 100
'amount' => round($amount) * 100

// Wrong: direct amount
'amount' => $amount
Cause: Wrong API key or using test key in live modeSolution:
  • Verify RAZOR_KEY in .env
  • Check key prefix: rzp_test_ for test, rzp_live_ for production
Cause: Payment method not activated in Razorpay DashboardSolution:
  • Login to Razorpay Dashboard
  • Go to SettingsConfigurationPayment Methods
  • Enable desired payment methods (Cards, UPI, Wallets, etc.)

Going Live

1

Complete KYC Verification

Submit required documents in Razorpay Dashboard:
  • PAN card
  • Business registration documents
  • Bank account details
2

Activate Payment Methods

Enable live payment methods in Dashboard → SettingsPayment Methods
3

Generate Live API Keys

Go to SettingsAPI Keys and generate live keys
4

Update Environment

.env
RAZOR_KEY=rzp_live_...
RAZOR_SECRET=<your-live-secret>
5

Test Live Payment

Make a small test transaction with real payment method

Webhooks

For automated payment confirmations:
1

Configure Webhook

Go to Razorpay Dashboard → SettingsWebhooks
2

Add Webhook URL

https://yourdomain.com/razorpay/webhook
3

Select Events

  • payment.captured
  • payment.failed
  • order.paid
4

Get Webhook Secret

Copy webhook secret and add to .env:
RAZORPAY_WEBHOOK_SECRET=...

Security Best Practices

Security Checklist
  • Always verify payment signatures
  • Never expose Key Secret in frontend
  • Use HTTPS for all payment pages
  • Validate amounts server-side
  • Implement webhook signature verification
  • Log all payment transactions
  • Set up fraud detection in Razorpay Dashboard

Payment Overview

Learn about payment architecture

SSLCommerz Integration

Configure SSLCommerz for Bangladesh

Build docs developers (and LLMs) love