laraditz/razorpay

Laravel package for interacting with Razorpay API.

Maintainers

Package info

github.com/laraditz/razorpay

pkg:composer/laraditz/razorpay

Transparency log

Statistics

Installs: 12

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.0.3 2026-08-03 08:17 UTC

This package is auto-updated.

Last update: 2026-08-03 08:17:29 UTC


README

Latest Version on Packagist Total Downloads License GitHub Actions

A Laravel wrapper package for the Razorpay Curlec API. Built directly on Laravel's HTTP client, it provides a fluent facade for Payment Links, Orders, Payments, Refunds, and Settlements with database persistence and webhook-driven, event-based sync out of the box.

Features

  • ๐Ÿ”— Payment Links โ€” create, fetch, update, cancel, list, resend notification
  • ๐Ÿงพ Orders โ€” create, fetch, list, update, fetch payments for an order, plus Checkout payment-signature verification
  • ๐Ÿ’ณ Payments โ€” fetch, capture, update, list โ€” synced locally from both the API response and the payment.authorized/captured/failed webhooks
  • ๐Ÿ’ธ Refunds โ€” create, fetch, list (account-wide and per-payment), update
  • ๐Ÿฆ Settlements โ€” fetch, list โ€” synced locally from both the API response and the settlement.processed webhook
  • ๐Ÿ—„๏ธ Local database persistence for every resource (RazorpayPaymentLink, RazorpayOrder, RazorpayPayment, RazorpayRefund, RazorpaySettlement), each a payment_id/razorpay_id join away from the others
  • ๐Ÿ“œ API request/response logging โ€” every outbound call recorded, with customer PII redacted and configurable retention
  • ๐Ÿ•ต๏ธ Webhook audit log โ€” every signature-valid inbound webhook recorded for later audit, separately from signature-failure diagnostics in your app's log channel
  • ๐Ÿ”” Automatic webhook handling with HMAC-SHA256 signature verification
  • ๐Ÿ” Idempotent webhook sync โ€” local records stay correct even if Razorpay retries a delivery
  • ๐ŸŽฏ Generic + typed events for every webhook-driven state change
  • ๐Ÿ“ฆ Uses Laravel's HTTP client only โ€” no Guzzle, no vendor SDK
  • ๐Ÿ›ก๏ธ Type-safe with PHP 8.2+ backed enums
  • ๐Ÿšซ Package-owned exception hierarchy โ€” never leaks raw HTTP or vendor exceptions

Requirements

  • PHP 8.2+ (Laravel 13.x itself requires PHP 8.3+)
  • Laravel 10.x, 11.x, 12.x, or 13.x

Installation

Install the package via composer:

composer require laraditz/razorpay

Publish the configuration and migrations:

php artisan vendor:publish --tag=razorpay-config
php artisan vendor:publish --tag=razorpay-migrations

Run the migrations:

php artisan migrate

Add your Razorpay credentials to .env:

RAZORPAY_KEY_ID=rzp_test_your_key_id
RAZORPAY_KEY_SECRET=your_key_secret
RAZORPAY_WEBHOOK_SECRET=your_webhook_secret
RAZORPAY_CURRENCY=MYR

Configuration

config/razorpay.php:

return [
    'key_id' => env('RAZORPAY_KEY_ID'),
    'key_secret' => env('RAZORPAY_KEY_SECRET'),
    'base_url' => env('RAZORPAY_BASE_URL', 'https://api.razorpay.com/v1'),
    'default_currency' => env('RAZORPAY_CURRENCY', 'MYR'),
    'timeout' => env('RAZORPAY_TIMEOUT', 30),
    'webhook_secret' => env('RAZORPAY_WEBHOOK_SECRET'),
    'webhook_path' => env('RAZORPAY_WEBHOOK_PATH', '/razorpay/webhook'),
    'log_api_calls' => env('RAZORPAY_LOG_API_CALLS', true),
    'api_log_retention_days' => env('RAZORPAY_API_LOG_RETENTION_DAYS', 30),
    'log_webhook_calls' => env('RAZORPAY_LOG_WEBHOOK_CALLS', true),
    'webhook_log_retention_days' => env('RAZORPAY_WEBHOOK_LOG_RETENTION_DAYS', 30),
];

Usage

Every service is accessed through the Razorpay facade. Full method reference, parameters, and more examples for each are in /docs โ€” linked below and in the Documentation section.

Payment Links

use Laraditz\Razorpay\Facades\Razorpay;

$link = Razorpay::paymentLink()->create([
    'amount' => 50000, // smallest currency subunit
    'currency' => 'MYR',
    'customer' => ['name' => 'John Doe', 'email' => 'john@example.com'],
    'reference_id' => 'ORDER-123',
]);

return redirect($link['short_url']);

โ†’ Full documentation

Orders

use Laraditz\Razorpay\Facades\Razorpay;

$order = Razorpay::order()->create(['amount' => 50000, 'currency' => 'MYR']);

// Pass $order['id'] to Checkout.js, then verify the signature it returns:
$isValid = Razorpay::order()->verifyPaymentSignature(
    $request->input('razorpay_order_id'),
    $request->input('razorpay_payment_id'),
    $request->input('razorpay_signature'),
);

โ†’ Full documentation

Payments

use Laraditz\Razorpay\Facades\Razorpay;

$payment = Razorpay::payment()->fetch('pay_29QQoUBi66xm2f');
$payment = Razorpay::payment()->capture('pay_29QQoUBi66xm2f', ['amount' => 50000, 'currency' => 'MYR']);

โ†’ Full documentation

Refunds

use Laraditz\Razorpay\Facades\Razorpay;

$refund = Razorpay::refund()->create('pay_29QQoUBi66xm2f', ['amount' => 10000]);

โ†’ Full documentation

Settlements

use Laraditz\Razorpay\Facades\Razorpay;

$settlements = Razorpay::settlement()->all(['count' => 20]);

โ†’ Full documentation

Querying local records

Every create() call (and, for Payments/Settlements, every fetch()/capture()/update()/all() call too) persists a local Eloquent record, kept in sync automatically as webhooks arrive โ€” no manual polling required:

use Laraditz\Razorpay\Models\RazorpayOrder;

$order = RazorpayOrder::where('razorpay_id', 'order_EKwxwAgItmmXdp')->first();

if ($order->status->isPaid()) {
    // ...
}

$order->payment; // the RazorpayPayment that settled it, via the payment_id column

Error Handling

Every non-2xx API response is caught and rethrown as a package-owned exception โ€” you never need to catch raw HTTP client exceptions:

use Laraditz\Razorpay\Exceptions\AuthenticationException; // 401
use Laraditz\Razorpay\Exceptions\ValidationException;     // 400, carries field errors via getErrors()
use Laraditz\Razorpay\Exceptions\ApiException;             // any other 4xx/5xx, carries the full body via getResponse()

try {
    Razorpay::paymentLink()->create(['amount' => 50000]);
} catch (ValidationException $e) {
    logger()->warning('Razorpay validation failed', $e->getErrors());
} catch (ApiException $e) {
    logger()->error('Razorpay API error', $e->getResponse());
}

Webhooks

A webhook route is registered automatically at POST /razorpay/webhook (configurable via RAZORPAY_WEBHOOK_PATH) โ€” never part of Laravel's web middleware group, so the X-Razorpay-Signature header is the sole authentication boundary. Point your Razorpay Dashboard's webhook URL at it and set RAZORPAY_WEBHOOK_SECRET.

Typed events fire for the events this package understands (PaymentLinkPaid, PaymentAuthorized, PaymentCaptured, PaymentFailed, OrderPaid, RefundCreated/Processed/Failed, SettlementProcessed), each keeping the matching local record in sync โ€” plus a generic RazorpayWebhookReceived event for every verified delivery, regardless of type.

class FulfillOrder
{
    public function handle(\Laraditz\Razorpay\Events\PaymentLinkPaid $event): void
    {
        if ($event->paymentLink === null) {
            return;
        }

        // $event->paymentLink->status is already PaymentLinkStatus::Paid here
    }
}

โ†’ Full documentation โ€” event reference, listener setup, idempotency notes

Logging

Outbound API calls and inbound webhook deliveries can each be optionally recorded for troubleshooting/audit, independently toggled and retained:

RAZORPAY_LOG_API_CALLS=false
RAZORPAY_LOG_WEBHOOK_CALLS=false

โ†’ Full documentation

Documentation

For detailed documentation on each service, please refer to:

  • Payment Links โ€” create, fetch, update, cancel, list, resend notification
  • Orders โ€” create, fetch, list, update, fetch payments for an order, Checkout signature verification
  • Payments โ€” fetch, capture, update, list
  • Refunds โ€” full/partial refunds, account-wide and per-payment listing
  • Settlements โ€” fetch, list, reconciliation
  • Webhooks โ€” event reference, listener setup, idempotency
  • Logging โ€” API request/response logging and webhook audit log

Testing

composer test

The test suite uses Http::fake()/Event::fake() throughout โ€” no real network access or live Razorpay credentials are required.

Security

If you discover any security related issues, please email raditzfarhan@gmail.com instead of using the issue tracker.

License

The MIT License (MIT).