PHPackages                             squareboat/razorpay-cashier - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. squareboat/razorpay-cashier

ActiveLibrary

squareboat/razorpay-cashier
===========================

A Laravel package for Razorpay payment gateway integration similar to Cashier

v1.0.6(11mo ago)256↓100%1MITPHPPHP ^8.2

Since Apr 1Pushed 11mo ago1 watchersCompare

[ Source](https://github.com/squareboat/razorpay-cashier)[ Packagist](https://packagist.org/packages/squareboat/razorpay-cashier)[ RSS](/packages/squareboat-razorpay-cashier/feed)WikiDiscussions main Synced today

READMEChangelog (5)Dependencies (2)Versions (8)Used By (0)

[![Laravel Logo](src/public/razorpay_and_laravel-removebg-preview.png)](https://laravel.com)

Razorpay Cashier for Laravel
============================

[](#razorpay-cashier-for-laravel)

A Laravel package that provides an expressive, fluent interface to integrate [Razorpay](https://razorpay.com/) payment gateway, inspired by Laravel Cashier. This package simplifies handling one-time charges and subscriptions for Laravel applications, tailored for the Indian market with support for INR and 100+ payment methods.

Features
--------

[](#features)

- Seamless integration with Razorpay's payment gateway
- Fluent API for charging users and managing subscriptions
- Supports Razorpay's extensive payment methods (cards, UPI, netbanking, wallets)
- Compatible with Laravel 12+

Installation
------------

[](#installation)

### Step 1: Install via Composer

[](#step-1-install-via-composer)

```
composer require squareboat/razorpay-cashier
```

### Step 2: Publish Configuration

[](#step-2-publish-configuration)

Publish the configuration file to customize settings:

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

This creates `config/razorpay.php` in your project.

### Step 3: Configure Environment

[](#step-3-configure-environment)

Add your Razorpay API keys to your `.env` file. You can get these from the Razorpay Dashboard:

```
RAZORPAY_KEY=rzp_test_xxxxxxxxxxxxxx
RAZORPAY_SECRET=xxxxxxxxxxxxxxxx
```

### Step 4: Run Migrations

[](#step-4-run-migrations)

If your application uses subscriptions, run the migration to create the necessary tables:

```
php artisan migrate
```

This sets up a subscriptions table to track user subscriptions.

Configuration
-------------

[](#configuration)

The `config/razorpay.php` file contains default settings:

```
return [
    'key' => env('RAZORPAY_KEY'),
    'secret' => env('RAZORPAY_SECRET'),
    'currency' => 'INR',
];
```

Adjust these as needed (e.g., change currency for multi-currency support, if implemented).

Usage
-----

[](#usage)

### Adding the Billable Trait

[](#adding-the-billable-trait)

Add the Billable trait to your User model (or any model you want to bill):

```
namespace App\Models;

use Illuminate\Foundation\Auth\User as Authenticatable;
use Squareboat\RazorpayCashier\Traits\Billable;

class User extends Authenticatable
{
    use Billable;
}
```

### One-Time Charges

[](#one-time-charges)

Charge a user a specific amount (e.g., 100 INR):

```
$user = auth()->user();
$payment = $user->charge(10000); // Amount in paise (100 INR = 10000 paise)
```

Frontend: Use Razorpay's checkout.js to collect payment details.

### Creating Subscriptions

[](#creating-subscriptions)

Subscribe a user to a Razorpay plan:

```
$user = auth()->user();
$subscription = $user->newSubscription('default', 'plan_id_from_razorpay')
    ->create($paymentMethodId);
```

Replace `plan_id_from_razorpay` with a plan ID created in your Razorpay Dashboard. `$paymentMethodId` is the `razorpay_payment_id` returned from the frontend.

### Frontend Integration

[](#frontend-integration)

Use Razorpay's checkout.js to initiate payments:

```
    Pay 100 INR
    Subscribe (100 INR)

        function pay(amount, endpoint) {
            const csrfToken = document.querySelector('meta[name="csrf-token"]')?.content;
            if (!csrfToken) {
                console.error('CSRF token not found');
                return;
            }
            var options = {
                key: "{{ config('razorpay.key') }}",
                amount: amount,
                currency: "INR",
                name: "Razorpay charge",
                description: endpoint === '/charge' ? 'One-time Charge' : 'Subscription',
                handler: function(response) {
                    console.log('Razorpay response:', response); // Log Razorpay response

                    fetch(endpoint, {
                            method: 'POST',
                            headers: {
                                'Content-Type': 'application/json',
                                'X-CSRF-TOKEN': csrfToken
                            },
                            body: JSON.stringify({
                                payment_method_id: response.razorpay_payment_id
                            })
                        })
                        .then(res => {
                            console.log('Raw response:', res);
                            return res.json();
                        })
                        .then(data => {
                            console.log('Parsed JSON:', data);
                        })
                        .catch(error => {
                            console.error('Fetch error:', error);
                        });
                }

            };
            var rzp = new Razorpay(options);
            rzp.open();
        }

        document.getElementById('charge-btn').onclick = function() {
            pay({{ $charge_amount }}, '/charge');
        };
        document.getElementById('subscribe-btn').onclick = function() {
            pay({{ $plan_amount }}, '/subscribe');
        };

```

Backend Route (e.g., `routes/web.php`):

```
Route::get('/test-payment', function () {
    $razorpayApi = new \Razorpay\Api\Api(env('RAZORPAY_KEY'), env('RAZORPAY_SECRET'));
    $plan = $razorpayApi->plan->fetch('plan_QEv23lVNekinmU');
    return view('payment', [
        'plan_amount' => $plan->item->amount, // Access amount from item
        'charge_amount' => 10000,
    ]);
});

Route::post('/charge', function (Request $request) {
    $user = auth()->user();

    $paymentMethodId = $request->input('payment_method_id');
    if (!$paymentMethodId) {
        return response()->json(['error' => 'Payment method ID missing'], 400);
    }

    $razorpay = new \Squareboat\RazorpayCashier\RazorpayCashier();
    $payment = $razorpay->capturePayment($paymentMethodId, 10000); // 100 INR
    return response()->json(['message' => 'Payment successful', 'payment' => $payment]);
});

Route::post('/subscribe', function (Request $request) {

    $user = auth()->user();

    $paymentMethodId = $request->input('payment_method_id');
    if (!$paymentMethodId) {
        return response()->json(['error' => 'Payment method ID missing'], 400);
    }

    // Replace 'plan_xxxxxxxxxx' with a real Razorpay plan ID from your dashboard
    $subscription = $user->newSubscription('default', 'plan_QEv23lVNekinmU')
        ->trialDays(7) // 7-day trial
        ->create($paymentMethodId);

    return response()->json(['message' => 'Subscription created with trial', 'subscription' => $subscription]);
});
```

Trial Periods
-------------

[](#trial-periods)

The package supports trial periods for subscriptions, allowing users to access a plan for a specified number of days before billing begins. This feature integrates with Razorpay's `start_at` parameter to delay the initial payment and uses a local `trial_ends_at` column in the `subscriptions` table to track the trial end date.

### Setup

[](#setup)

1. **Migration**:

    - Ensure the `subscriptions` table includes the `trial_ends_at` column. The package provides a migration to add this column: ```
        php artisan migrate
        ```
    - The migration (2025\_04\_08\_000001\_add\_trial\_ends\_at\_to\_subscriptions.php) adds a nullable trial\_ends\_at timestamp. If you haven't run it yet, apply it with the above command.
2. **Model**:

    - The Subscription model (Squareboat\\RazorpayCashier\\Models\\Subscription) is pre-configured to handle trial\_ends\_at as a date field and includes helper methods to check trial status.

### Usage

[](#usage-1)

To create a subscription with a trial period, use the trialDays() method on the SubscriptionBuilder instance returned by newSubscription():

```
use App\Models\User;

$user = User::firstOrCreate([
    'email' => 'test@example.com',
    'name' => 'Test User',
    'password' => bcrypt('password'),
]);

$subscription = $user->newSubscription('default', 'plan_xxxxxxxxxx')
    ->trialDays(7) // Set a 7-day trial
    ->create($paymentMethodId);

return response()->json(['message' => 'Subscription created with trial', 'subscription' => $subscription]);
```

- `trialDays($days)`: Specifies the number of days for the trial period. If omitted, the subscription starts immediately with no trial.

**Behavior**:

- During the trial, no payment is captured. The `start_at` parameter is set to `now() + $trialDays`, delaying Razorpay's first billing cycle.
- The `trial_ends_at` column is set to `now() + $trialDays` in the local database.
- After the trial, Razorpay automatically charges the subscription amount based on the plan's interval (e.g., monthly) if the payment method is valid.

### Checking Trial Status

[](#checking-trial-status)

The Subscription model provides methods to check the trial status:

- `onTrial()`: Returns true if the current date is before trial\_ends\_at.
- `hasTrialEnded()`: Returns true if the current date is after trial\_ends\_at.
- `endTrial()`: Updates the subscription status to trialed and clears trial\_ends\_at if the trial has ended (optional manual action).

Example:

```
$subscription = $user->subscriptions()->first();
if ($subscription->hasTrialEnded()) {
    $subscription->endTrial();
    logger('Trial has ended for subscription: ' . $subscription->id);
}
```

### Syncing with Razorpay

[](#syncing-with-razorpay)

To keep the local subscription status in sync with Razorpay after the trial, use the syncTrialStatus method:

```
Route::get('/test-trial-status/{subscriptionId}', function ($subscriptionId) {
    $razorpay = new \Squareboat\RazorpayCashier\RazorpayCashier();
    $subscription = $razorpay->syncTrialStatus($subscriptionId);
    return response()->json(['message' => 'Trial status synced', 'subscription' => $subscription]);
});
```

### Notes

[](#notes)

- Replace 'plan\_xxxxxxxxxx' with your actual Razorpay plan ID from the dashboard.
- Ensure the payment method ($paymentMethodId) is valid for the initial capture after the trial.
- For production, consider integrating webhooks to handle trial end events automatically (see Webhook Handling section when implemented).

### Troubleshooting

[](#troubleshooting)

- **Trial Not Starting**: Verify trialDays() is called before create().
- **No Billing After Trial**: Ensure start\_at is correctly set and the payment method is active.
- **Errors**: Check logs (storage/logs/laravel.log) for Razorpay API responses or database issues.

Subscription Management
-----------------------

[](#subscription-management)

The `squareboat/razorpay-cashier` package provides methods to manage subscriptions, including pausing, resuming, canceling, and swapping plans.

### Usage

[](#usage-2)

Use the following methods on a `Billable` model (e.g., `User`):

- **`pauseSubscription($subscriptionId)`**: Pauses billing for the subscription.

    ```
    $user->pauseSubscription('sub_QGXpowM0Ewrq0');
    ```

    - Endpoint: POST /pause-subscription/{subscriptionId}
    - Note: Replace sub\_QGXpowM0Ewrq0 with a valid Razorpay subscription ID.
- **`resumeSubscription($subscriptionId)`**: Resumes billing for a paused subscription.

    ```
    $user->resumeSubscription('sub_QGXpowM0Ewrq0');
    ```

    - Endpoint: POST /resume-subscription/{subscriptionId}
- **`cancelSubscription($subscriptionId, $graceDays = 0)`**: Cancels the subscription with an optional grace period.

    ```
    $user->cancelSubscription('sub_QGXpowM0Ewrq0', 7); // 7-day grace period
    ```

    - Endpoint: POST /cancel-subscription/{subscriptionId}
- **`swapPlan($subscriptionId, $newPlanId)`**: Changes the subscription to a new plan.

    ```
    $user->swapPlan('sub_QGXpowM0Ewrq0', 'plan_yyyyyyyyyy');
    ```

    - Endpoint: POST /swap-plan/{subscriptionId}/{newPlanId}
    - Response:
        - Success: `{"success": true, "message": "Plan swapped successfully", "subscription_id": "...", "new_plan_id": "..."}`
        - Failure: `{"success": false, "message": "Swap failed: [reason]", "subscription_id": "..."}` (e.g., invalid status, local record not found, or API error).

### Notes

[](#notes-1)

- Replace `sub_QGXpowM0Ewrq0` and `plan_yyyyyyyyyy` with actual Razorpay subscription and plan IDs.
- Ensure the subscription is in an active or paused state for swapping (check via `$subscription->status`).
- Grace periods are stored in the `grace_ends_at` column and respected locally, but Razorpay handles the actual cancellation.
- For API testing (e.g., Postman), the routes use a custom `bypass.csrf` middleware to skip CSRF verification, registered in `bootstrap/app.php`.

### Troubleshooting

[](#troubleshooting-1)

- **419 Error**: Ensure the `bypass.csrf` middleware is registered and applied. Clear cache with `php artisan config:clear`.
- **Swap Fails**: Check the response message and logs (`storage/logs/laravel.log`) for details (e.g., status, API errors).
- **Database Mismatch**: Sync with Razorpay using `syncTrialStatus` if needed.
- **Errors**: Review `storage/logs/laravel.log` for API or database issues.

Invoicing
---------

[](#invoicing)

The `squareboat/razorpay-cashier` package integrates with Razorpay's official invoicing feature and syncs details to a local invoices table for hybrid management.

### Setup

[](#setup-1)

- Run the migration to create the invoices table: ```
    php artisan migrate
    ```
- Ensure you have configured Razorpay API keys in your .env: ```
    RAZORPAY_KEY=your_razorpay_key_id
    RAZORPAY_SECRET=your_razorpay_secret
    ```
- Enable invoicing in your Razorpay Dashboard under **Invoicing**.

### Usage

[](#usage-3)

Use the following methods on a `Billable` model (e.g., `User`):

- **`createRazorpayInvoice($subscriptionId, $customerId = null, $notes = null, array $lineItems = [])`**: Creates a Razorpay invoice linked to a subscription and syncs it locally.

    ```
    $user->createRazorpayInvoice('sub_QGXpowM0Ewrq0', null, 'First invoice', [
        ['name' => 'Subscription Fee', 'amount' => 1000, 'quantity' => 1]
    ]);
    ```

    - **Endpoint**: POST /create-razorpay-invoice/{subscriptionId}
    - **Response**: `{"success": true, "message": "Razorpay invoice created and synced locally", "razorpay_invoice": {...}, "local_invoice": {...}}` or failure details.
    - **Note**: Amount is derived from the subscription plan unless lineItems are provided (amount in rupees, converted to paise). Provide a customerId if available.
- **`getRazorpayInvoice($invoiceId)`**: Retrieves a Razorpay invoice and syncs with the local record.

    ```
    $user->getRazorpayInvoice('inv_1abcde');
    ```

    - **Endpoint**: GET /get-razorpay-invoice/{invoiceId}
    - **Response**: `{"success": true, "razorpay_invoice": {...}, "local_invoice": {...}}` or failure details.
- **`updateRazorpayInvoiceStatus($invoiceId, $action)`**: Updates the Razorpay invoice status and syncs locally (e.g., issue, cancel).

    ```
    $user->updateRazorpayInvoiceStatus('inv_1abcde', 'issue');
    ```

    - **Endpoint**: POST /update-razorpay-invoice-status/{invoiceId}/{action}
    - **Response**: `{"success": true, "message": "Razorpay invoice issued successfully", "razorpay_invoice": {...}, "local_invoice": {...}}` or failure details.

### Notes

[](#notes-2)

- Replace `sub_QGXpowM0Ewrq0` and `inv_1abcde` with valid Razorpay subscription and invoice IDs.
- Currency defaults to INR; contact Razorpay for international support.
- Local invoices table syncs with Razorpay data for offline access or custom reporting.
- For testing, use the `bypass.csrf` middleware (registered in `bootstrap/app.php`).

### Troubleshooting

[](#troubleshooting-2)

- **Failure Responses**: Check the message field and logs (`storage/logs/laravel.log`) for details (e.g., invalid subscription).
- **API Errors**: Ensure API keys are correct and invoicing is enabled in Razorpay.
- **Database Sync**: Verify the invoices table is populated and subscription IDs are valid.

Upcoming Features
-----------------

[](#upcoming-features)

1. **Webhook Handling:**

    - Process Razorpay webhook events (e.g., `subscription.charged`, `payment.failed`, `subscription.cancelled`).
    - Store events in a `razorpay_events` table for idempotency and debugging.
2. **Payment Method Management:**

    - Store and manage customer payment methods (e.g., cards) using Razorpay's Customer API.
    - Allow updating or deleting payment methods.
3. **Multi-Currency Support:**

    - Support payments and subscriptions in multiple currencies (e.g., INR, USD).
    - Configure currency dynamically via options or config.
4. **Retries for Failed Payments:**

    - Automatically retry failed subscription charges with configurable rules.
    - Queue retries using Laravel's job system.
5. **Grace Periods:**

    - Allow a grace period after subscription cancellation or payment failure before deactivating services.
    - Track `ends_at` for grace period logic.
6. **Coupons/Discounts:**

    - Apply Razorpay coupons to subscriptions or one-time charges.
    - Store discount details locally.
7. **Refunds:**

    - Process refunds for one-time charges or subscription payments.
    - Update local records accordingly.
8. **Subscription Quantity:**

    - Support variable quantities for subscriptions (e.g., 5 users on a plan).
    - Adjust billing via Razorpay's `quantity` parameter.
9. **Tax Handling:**

    - Apply taxes to charges and subscriptions using Razorpay's tax features.
    - Store tax details in invoices.
10. **Customer Management:**

    - Link Razorpay customers to Laravel users for recurring payments.
    - Sync customer data (e.g., email, phone) with Razorpay.
11. **Payment Receipts:**

    - Send email receipts for successful payments via Razorpay's email system or Laravel's mail.
12. **Frontend Integration Enhancements:**

    - Add prebuilt Blade components or JavaScript helpers for easier checkout integration.

Testing
-------

[](#testing)

Use Razorpay's test mode with these sample card details:

- Card: 4111 1111 1111 1111
- Expiry: Any future date
- CVV: 123
- OTP: 123456 (if prompted)

Check the Razorpay Test Cards for more options.

Requirements
------------

[](#requirements)

- PHP 8.2 or higher
- Laravel 12.0 or higher
- Razorpay PHP SDK 2.8 or higher

Troubleshooting
---------------

[](#troubleshooting-3)

- **Payment Fails**: Verify API keys and test mode settings in the Razorpay Dashboard.
- **Class Not Found**: Run `composer dump-autoload` and ensure the provider is in `bootstrap/providers.php`.

Contributing
------------

[](#contributing)

Feel free to submit issues or pull requests on GitHub.

License
-------

[](#license)

This package is open-sourced software.

Support
-------

[](#support)

For questions or issues, open a ticket on the GitHub Issues page.

###  Health Score

34

—

LowBetter than 79% of packages

Maintenance51

Moderate activity, may be stable

Popularity13

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity54

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~1 days

Total

7

Last Release

346d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/e74cbbaa7a9f04e41076efcc4a69efd1185030b55cd90c3ce8b0201499618b06?d=identicon)[squareboat1](/maintainers/squareboat1)

![](https://www.gravatar.com/avatar/bd2663e3f8f3b23c3162f1073ddccbbc2ca77437fdebc4d12afa3e44f401ed3b?d=identicon)[getankushtyagi](/maintainers/getankushtyagi)

![](https://www.gravatar.com/avatar/572d7dcc4d33652263ae13ec5594a751780e3b4e4af8db86bc616666846b79c4?d=identicon)[Anubhavjain786](/maintainers/Anubhavjain786)

---

Top Contributors

[![AnkushSquareboat](https://avatars.githubusercontent.com/u/131669661?v=4)](https://github.com/AnkushSquareboat "AnkushSquareboat (19 commits)")

### Embed Badge

![Health badge](/badges/squareboat-razorpay-cashier/health.svg)

```
[![Health](https://phpackages.com/badges/squareboat-razorpay-cashier/health.svg)](https://phpackages.com/packages/squareboat-razorpay-cashier)
```

###  Alternatives

[spatie/laravel-mix-preload

Add preload and prefetch links based your Mix manifest

169175.3k2](/packages/spatie-laravel-mix-preload)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
