Drupal is a registered trademark of Dries Buytaert
drupal 10.6.12 Update released for Drupal core (10.6.12)! drupal 11.3.13 Update released for Drupal core (11.3.13)! drupal 10.6.11 Update released for Drupal core (10.6.11)! drupal 11.3.12 Update released for Drupal core (11.3.12)! drupal 11.2.14 Update released for Drupal core (11.2.14)! drupal 10.5.12 Update released for Drupal core (10.5.12)! cms 2.1.3 Update released for Drupal core (2.1.3)! drupal 10.5.11 Update released for Drupal core (10.5.11)! drupal 11.3.11 Update released for Drupal core (11.3.11)! drupal 11.2.13 Update released for Drupal core (11.2.13)! drupal 10.6.10 Update released for Drupal core (10.6.10)! cms 2.1.2 Update released for Drupal core (2.1.2)! drupal 11.1.10 Update released for Drupal core (11.1.10)! drupal 10.5.10 Update released for Drupal core (10.5.10)! drupal 10.4.10 Update released for Drupal core (10.4.10)! drupal 11.2.12 Update released for Drupal core (11.2.12)! drupal 11.3.10 Update released for Drupal core (11.3.10)! drupal 10.6.9 Update released for Drupal core (10.6.9)! drupal 10.6.8 Update released for Drupal core (10.6.8)! drupal 11.3.9 Update released for Drupal core (11.3.9)!

esewa

No security coverage
View on drupal.org

eSewa is Nepal's leading digital wallet, enabling instant online payments for mobile recharges, utility bills (electricity, internet, water, TV), insurance premiums, bus, airline, and movie tickets, and many more services.

The eSewa Payment Gateway module integrates eSewa into Drupal Commerce using the official eSewa ePay v2 API with HMAC-SHA256 cryptographic signature verification. When a customer selects eSewa at checkout they are securely redirected to the eSewa payment page. After completing payment, eSewa redirects back to your site with a base64-encoded, cryptographically signed response. The module verifies the signature before recording the payment, preventing fraudulent or tampered responses from ever fulfilling an order.

Key features:

  • Full eSewa ePay v2 API integration (HMAC-SHA256 signed POST form)
  • Cryptographic response verification via remotemerge/esewa-php-sdk
  • Replay-attack prevention (transaction UUID cross-check)
  • Amount tamper detection (±0.01 NPR tolerance check)
  • Automatic sandbox credentials in test mode — no configuration required
  • Drupal Commerce event dispatch on payment success / failure
  • Hook support for custom success / failure messages
  • Form validation: live credentials required when mode is set to Live
  • Supports Drupal 10 and Drupal 11

Supported currencies: NPR (Nepalese Rupee) only.

To submit bug reports and feature suggestions, or to track changes:
https://www.drupal.org/project/issues/esewa

REQUIREMENTS

This module requires the following:

Drupal modules

  • Drupal Commerce
    ^3.0 (includes commerce_order, commerce_payment, commerce_cart)

PHP

  • PHP 8.1 or higher
  • PHP extensions: ext-curl, ext-json (required by the SDK)

Composer library (installed automatically)

INSTALLATION

Step 1 — Install via Composer

Always install this module and its PHP dependency via Composer so that autoloading of the SDK is handled automatically. From your Drupal project root, run:

	composer require drupal/esewa

This single command will:

  1. Download the drupal/esewa module into modules/contrib/esewa
  2. Automatically install remotemerge/esewa-php-sdk ^4.0 into vendor/
  3. Regenerate the Composer autoloader

Custom module note: If you are managing this as a custom module in modules/custom/esewa, add only the SDK dependency:
composer require remotemerge/esewa-php-sdk ^4.0

Step 2 — Enable the module

Via Drush (recommended):

	
drush en esewa -y
drush cr

Via the Drupal UI:

  1. Navigate to Administration » Extend ( /admin/modules)
  2. Find eSewa Payment Gateway under the Commerce package
  3. Tick the checkbox and click Install
  4. Clear caches via drush cr or Administration » Configuration » Performance

Step 3 — Verify the SDK library

	php -r "require 'vendor/autoload.php'; echo class_exists('RemoteMerge\Esewa\EsewaFactory') ? 'SDK OK' : 'SDK MISSING';"

Expected output: SDK OK. If you see SDK MISSING, run composer install and then drush cr.

CONFIGURATION

Set your store currency to NPR

eSewa only processes NPR (Nepalese Rupee) payments. Before adding the gateway:

  1. Navigate to Administration » Commerce » Configuration » Currencies and confirm NPR is present. If not, click + Add currency and add Nepalese Rupee (NPR).
  2. Navigate to Administration » Commerce » Configuration » Stores, edit your store, and set NPR as the default currency.

The module will display an error at checkout and refuse to build the payment form if the order currency is not NPR.

Add the payment gateway

  1. Navigate to Administration » Commerce » Configuration » Payment gateways ( /admin/commerce/config/payment-gateways)
  2. Click + Add payment gateway
  3. In the Plugin dropdown select eSewa
  4. Fill in the fields described below
  5. Click Save

Gateway configuration fields

Field Required Description Name Yes Internal admin label, e.g. eSewa Display name Yes Customer-facing label shown at checkout, e.g. Pay with eSewa Mode Yes Test (development / staging) or Live (production) Test Product Code No Leave blank to use the eSewa sandbox default EPAYTEST automatically Test Secret Key No Leave blank to use the eSewa sandbox default automatically Live Product Code Live only Merchant code from your eSewa Merchant Dashboard, e.g. NP-ES-YOURCODE Live Secret Key Live only HMAC-SHA256 key from your eSewa Merchant Dashboard. Stored securely. Status Yes Set to Enabled

Test mode: When Mode is set to Test, the official eSewa sandbox credentials ( EPAYTEST / 8gBm/:&EnhH.1/q) are applied automatically. You do not need to enter a Product Code or Secret Key for testing.

TEST CREDENTIALS

Official eSewa sandbox credentials from the eSewa Developer Portal. No real money is involved in test mode.

eSewa test user accounts

Field Value eSewa ID 9711111111 / 9711111112 / 9711111113 / 9711111114 Password Nepal@123 MPIN 1122
(mobile app only) OTP / Token 123456

Merchant / SDK sandbox credentials (applied automatically)

Field Value Product Code EPAYTEST Secret Key 8gBm/:&EnhH.1/q

eSewa environment URLs (for reference)

Environment Purpose URL Test Payment form POST https://rc-epay.esewa.com.np/api/epay/main/v2/form Test Transaction status check https://rc.esewa.com.np/api/epay/transaction/status/ Production Payment form POST https://epay.esewa.com.np/api/epay/main/v2/form Production Transaction status check https://esewa.com.np/api/epay/transaction/status/

These URLs are managed automatically by the SDK based on the configured environment.

PRODUCTION SETUP

Step 1 — Register as an eSewa Merchant

  1. Visit https://merchant.esewa.com.np
  2. Create or log in to your eSewa Merchant account
  3. Complete the KYC / merchant verification process
  4. eSewa will issue your live Product Code and Secret Key

Step 2 — Switch the gateway to Live mode

  1. Navigate to Administration » Commerce » Configuration » Payment gateways
  2. Edit your eSewa gateway
  3. Change Mode to Live
  4. Enter your Live Product Code
  5. Enter your Live Secret Key
  6. Click Save

Security tip: Store the Secret Key in an environment variable or a secrets manager — never commit it to version control. You can inject it via settings.php:
$config['commerce_payment.commerce_payment_gateway.esewa']['configuration']['live_secret_key'] = getenv('ESEWA_SECRET_KEY');

Step 3 — Confirm HTTPS

Both callback URLs ( /esewa/success and /esewa/cancel) must be served over HTTPS in production to prevent response interception.

PAYMENT FLOW

The module implements the three-step eSewa ePay v2 flow:

1. INITIATE — The module builds a signed POST form via the SDK. The SDK generates an HMAC-SHA256 signature over total_amount, transaction_uuid, and product_code. The customer's browser auto-submits this form to the eSewa checkout page.

2. VERIFY — After the customer completes payment, eSewa redirects to /esewa/success?data=<base64>. The module decodes the response, verifies the HMAC-SHA256 signature via the SDK, cross-checks the transaction_uuid (replay-attack prevention), confirms the status is COMPLETE, and validates total_amount matches the stored order total (±0.01 NPR tamper detection).

3. COMPLETE — All checks passed: a commerce_payment entity is saved in completed state, the order is advanced to the complete checkout step, the esewa.payment_success event is dispatched, and the customer is redirected to the order confirmation page.

On cancel/failure — eSewa redirects to /esewa/cancel. The module rolls the order back to the previous checkout step (so the customer can retry), dispatches the esewa.payment_failure event, and shows a cancellation warning.

eSewa ePay v2 request fields

Field Required Description amount Yes Base product/service price tax_amount Yes Tax amount (use 0 if none) product_service_charge Yes Service charge (use 0 if none) product_delivery_charge Yes Delivery charge (use 0 if none) total_amount Yes Sum of all above fields transaction_uuid Yes Unique order identifier — alphanumeric and hyphens only product_code Yes Merchant product code assigned by eSewa success_url Yes Your absolute /esewa/success callback URL failure_url Yes Your absolute /esewa/cancel callback URL signed_field_names Yes total_amount,transaction_uuid,product_code signature Yes HMAC-SHA256 base64-encoded signature

eSewa success response (decoded from ?data=)

	
{
  "transaction_code": "0007G36",
  "status": "COMPLETE",
  "total_amount": "1000.0",
  "transaction_uuid": "your-uuid-here",
  "product_code": "EPAYTEST",
  "signed_field_names": "transaction_code,status,total_amount,transaction_uuid,product_code,signed_field_names",
  "signature": "62GcfZTmVkzhtUeh+QJ1AqiJrjoWWGof3U+eTPTZ7fA="
}

Transaction status values

Status Meaning COMPLETE Payment completed successfully PENDING Payment initiated but not yet completed FULL_REFUND Full payment refunded to customer PARTIAL_REFUND Partial payment refunded AMBIGUOUS Payment is in an uncertain / halted state NOT_FOUND Session expired or transaction does not exist CANCELED Payment cancelled or reversed by eSewa

TROUBLESHOOTING

Module does not appear in the Payment gateways plugin list

	drush en esewa -y && drush cr

Verify the @CommercePaymentGateway annotation block is intact in src/Plugin/Commerce/PaymentGateway/EsewaCheckoutCheckout.php.

"Class not found" / SDK autoload errors

	
composer require remotemerge/esewa-php-sdk ^4.0
composer dump-autoload
drush cr

"eSewa supports NPR only" message at checkout

Your Commerce store currency is not NPR. Navigate to Administration » Commerce » Configuration » Stores and set the default currency to NPR (Nepalese Rupee).

Payment verified but order does not advance to "complete"

Ensure your Commerce checkout flow includes a complete step. Navigate to Administration » Commerce » Configuration » Checkout flows and verify the step exists and is correctly positioned.

Signature verification failure / "Invalid signature" in logs

  • In live mode: confirm the Secret Key in gateway settings exactly matches the key in your eSewa Merchant Dashboard, including all special characters.
  • In test mode: the key 8gBm/:&EnhH.1/q is applied automatically. If you see this error in test mode, clear all caches and retry.
  • Verify your server's system clock is accurate (NTP sync recommended).

"Amount mismatch" in Drupal logs

eSewa returned a total_amount that differs from the stored order total by more than ±0.01 NPR. Check whether order prices are being modified after the payment form is built, or investigate currency rounding configuration.

"Transaction UUID mismatch" in Drupal logs

The transaction_uuid in eSewa's response does not match the UUID stored in the PHP session. This protects against replay attacks. Possible causes: session expiry, the user opening multiple browser tabs, or an actual tampered response. The payment is safely rejected in all cases.

Viewing eSewa-specific log messages

	drush watchdog:show --type=esewa --count=50

Or via UI: Administration » Reports » Recent log messages ( /admin/reports/dblog) — filter by Type: esewa.

DEVELOPER REFERENCE

Hooks


hook_esewa_success_message(string &$message)

Customise the status message displayed to the customer after a successful payment.

	
/**
 * Implements hook_esewa_success_message().
 */
function mymodule_esewa_success_message(string &$message): void {
  $message = t('<strong>Thank you!</strong> Your eSewa payment has been received.');
}


hook_esewa_failure_message(string &$message)

Customise the warning message displayed when a payment is cancelled or fails.

	
/**
 * Implements hook_esewa_failure_message().
 */
function mymodule_esewa_failure_message(string &$message): void {
  $message = t('Your eSewa payment was not completed. You have not been charged.');
}

Events

The module dispatches Symfony events that any module can subscribe to.

Constant Event string Fired when EsewaCheckoutEvents::PAYMENT_SUCCESS esewa.payment_success HMAC signature verified, payment entity created EsewaCheckoutEvents::PAYMENT_FAILURE esewa.payment_failure User cancels or gateway onCancel() is called

Example event subscriber:

	
// mymodule/src/EventSubscriber/EsewaEventSubscriber.php
namespace Drupal\mymodule\EventSubscriber;

use Drupal\esewa\Event\EsewaCheckoutEvents;
use Drupal\esewa\Event\EsewaCheckoutPaymentEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class EsewaEventSubscriber implements EventSubscriberInterface {

  public static function getSubscribedEvents(): array {
    return [
      EsewaCheckoutEvents::PAYMENT_SUCCESS => 'onPaymentSuccess',
      EsewaCheckoutEvents::PAYMENT_FAILURE => 'onPaymentFailure',
    ];
  }

  public function onPaymentSuccess(EsewaCheckoutPaymentEvent $event): void {
    $order = $event->getOrder();
    // e.g. trigger a receipt email, update inventory, etc.
  }

  public function onPaymentFailure(EsewaCheckoutPaymentEvent $event): void {
    $order = $event->getOrder();
    // e.g. restore reserved stock, send a cancellation notification, etc.
  }
}

Register the subscriber in mymodule.services.yml:

	
services:
  mymodule.esewa_event_subscriber:
    class: Drupal\mymodule\EventSubscriber\EsewaEventSubscriber
    tags:
      - { name: event_subscriber }

Session keys

The module stores these scalar values in the PHP session during the payment redirect. They are cleared immediately after the callback is processed.

Key Type Description esewa_order_id int Commerce order ID esewa_gateway_id string Payment gateway entity machine name esewa_transaction_uuid string UUID sent to eSewa — used for replay-attack detection esewa_total_amount float Order total in NPR — used for amount tamper detection esewa_is_test bool Whether the gateway was in test mode when the form was built

Gateway plugin API

Public methods available on EsewaCheckoutCheckout:

Method Signature Description createEsewaClient() (string $success_url, string $failure_url): EpayInterface Returns a fully configured SDK client for the current mode. In test mode, sandbox credentials are applied automatically. completePayment() (OrderInterface $order, string $remote_id, string $remote_state): PaymentInterface Creates and saves a commerce_payment entity in completed state and dispatches the success event.

RUNNING TESTS

The module ships with PHPUnit unit tests covering the plugin's core business logic. No database or browser is required.

	
# From the module directory:
cd modules/custom/esewa

php ../../../vendor/bin/phpunit \
  --configuration phpunit.xml.dist \
  tests/src/Unit/ \
  --testdox
File What it covers EsewaCheckoutEventsTest Event name constants EsewaCheckoutPaymentEventTest Payment event object construction and order accessor EsewaCheckoutCheckoutTest defaultConfiguration(), createEsewaClient() (test/live modes, sandbox fallbacks, missing-credential exceptions), completePayment() (entity creation, event dispatch, test/live flags), onCancel()

Activity

Total releases
2
First release
Jun 2026
Latest release
9 hours ago
Release cadence
0 days
Stability
50% stable

Releases

Version Type Release date
2.0.0 Stable Jun 25, 2026
2.0.x-dev Dev Jun 25, 2026