PHPackages                             ajaymahato/laravel-esewa-epay-v2 - 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. [Payment Processing](/categories/payments)
4. /
5. ajaymahato/laravel-esewa-epay-v2

ActiveLibrary[Payment Processing](/categories/payments)

ajaymahato/laravel-esewa-epay-v2
================================

Laravel eSewa ePay v2 integration (HMAC, callback verify, status check)

v1.1.1(7mo ago)010MITPHPPHP ^8.1|^8.2|^8.3

Since Oct 4Pushed 7mo agoCompare

[ Source](https://github.com/ajaymahato431/Laravel-Esewa-Epay-V2)[ Packagist](https://packagist.org/packages/ajaymahato/laravel-esewa-epay-v2)[ RSS](/packages/ajaymahato-laravel-esewa-epay-v2/feed)WikiDiscussions main Synced 1mo ago

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

Laravel eSewa ePay v2
=====================

[](#laravel-esewa-epay-v2)

Laravel eSewa ePay v2 integration for Laravel 10/11/12. Generate HMAC signatures, post to the ePay form endpoint, verify callbacks, and record every attempt in your database with a single facade call.

Features
--------

[](#features)

- Drop-in facade: `return Esewa::pay([...]);` renders an auto-submit payment form
- HMAC-SHA256 (Base64) signing helper for requests and webhook payloads
- Callback verification + event dispatch (`EsewaPaymentVerified`) with DB persistence
- Status check client for reconciliation workflows
- Ships with migration, model, enum, controllers, routes, and Blade view

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

[](#requirements)

- PHP 8.1+
- Laravel 10 or 11 (or any app with `illuminate/support` 10/11/12)
- eSewa merchant credentials for UAT or Production

Payment Status Constants/Enums
------------------------------

[](#payment-status-constantsenums)

```
    case PENDING        = 'PENDING';
    case COMPLETE       = 'COMPLETE';
    case FULL_REFUND    = 'FULL_REFUND';
    case PARTIAL_REFUND = 'PARTIAL_REFUND';
    case AMBIGUOUS      = 'AMBIGUOUS';
    case NOT_FOUND      = 'NOT_FOUND';
    case CANCELED       = 'CANCELED';
```

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

[](#installation)

1. Require the package

    ```
    composer require ajaymahato/laravel-esewa-epay-v2
    ```
2. Publish config + migration, then run migrations

    ```
    php artisan vendor:publish --tag=esewa-config
    php artisan migrate
    ```
3. Configure your `.env`

    ```
    ESEWA_MODE=uat                 # uat (testing) or production
    ESEWA_PRODUCT_CODE=EPAYTEST     # merchant code
    ESEWA_SECRET_KEY=8gBm/:&EnhH.1/q
    ESEWA_SUCCESS_URL=https://your-app.com/esewa/relay
    ESEWA_FAILURE_URL=https://your-app.com/esewa/relay

    # Optional overrides
    ESEWA_ROUTE_PREFIX=             # set if you want /prefix/esewa/...
    ```

Add this to your order/booking table
------------------------------------

[](#add-this-to-your-orderbooking-table)

```
$table->foreignId('payment_id')->nullable()
->constrained('esewa_payments')->nullOnDelete();
$table->string('transaction_uuid')->unique();
$table->string('payment_status')->default('UNPAID'); // cache
$table->string('esewa_ref')->nullable(); // external proof
$table->timestamp('paid_at')->nullable();
```

Quick Start
-----------

[](#quick-start)

Create your order/booking as usual. In your controller, generate the UUID, queue the delayed reconciliation job, then return the payment form using the same UUID.

```
use Illuminate\Support\Str;
use App\Jobs\ReconcileEsewaPaymentJob;

public function payOrder(\App\Models\Order $order)
{
    // Generate a UUID you control (so jobs/admin tools can reference it)
    $uuid = now()->format('ymd-His').'-'.Str::upper(Str::random(4));

    // Schedule a safety-net reconcile in case the browser callback never arrives
    ReconcileEsewaPaymentJob::dispatch($uuid)->delay(now()->addMinutes(8));

    // Return the auto-submitting eSewa form
    return \Esewa::pay([
        'transaction_uuid'        => $uuid,                 // use the same UUID
        'amount'                  => (int) $order->total,
        'total_amount'            => (int) $order->total,
        'tax_amount'              => 0,
        'product_service_charge'  => 0,
        'product_delivery_charge' => 0,
        'meta' => [
            'payable' => ['type' => $order::class, 'id' => $order->id],
        ],
        'success_url' => route('thank.you'),        //it should be different from .env urls
        'failure_url' => route('payment.failed'),   //put the success or failed page routes here
    ]);
}
```

Handling Verified Payments
--------------------------

[](#handling-verified-payments)

Hook one listener to flip your own record (booking/order/cart) to PAID.

1. Make the listener

```
php artisan make:listener MarkOrderPaid
```

app/Listeners/MarkOrderPaid.php

```
public function handle(\AjayMahato\Esewa\Events\EsewaPaymentVerified $event): void
{
    $payment = $event->payment;
    if (($payment->status?->value ?? $payment->status) !== 'COMPLETE') {
        return;
    }

    $meta = $payment->meta['payable'] ?? null;
    if (! $meta) {
        return;
    }

    $model = app($meta['type'])::find($meta['id']);
    if (! $model) {
        return;
    }

    $model->update([
        'payment_id' =? $payment->id,
        'payment_status' => 'PAID',
        'esewa_ref' => $payment->ref_id,
        'paid_at' => now(),
    ]);
}
```

Tip: add a tiny helper on your models:

```
public function isPaid(): bool
{
return $this->payment_status === 'PAID';
}
```

Reconciliation Safety Nets (Optional to make the project more Secure)
---------------------------------------------------------------------

[](#reconciliation-safety-nets-optional-to-make-the-project-more-secure)

Delayed jobs, scheduled sweeps, and manual tools ensure you update stale payments even if callbacks fail. Choose any one option among the three according to your convenience.

### A) Delayed job fallback

[](#a-delayed-job-fallback)

1. Create the job

    ```
    php artisan make:job ReconcileEsewaPaymentJob
    ```
2. Implement the job (`app/Jobs/ReconcileEsewaPaymentJob.php`):

    ```
