Integrating eSewa in a web app: the working setup

esewapayments

On this page

Payments fail for boring reasons: wrong amounts, unverified callbacks, and credentials in the wrong place. This guide keeps the flow simple and verifiable end to end.

How the eSewa flow works

The user is redirected to eSewa with a signed form, pays there, and eSewa sends them back to your success or failure URL. You then verify the returned payload server-side before treating the order as paid.

Prerequisites

  • A merchant account (sandbox for development)
  • A server route that can create the payment form and verify callbacks
  • HTTPS in production. eSewa requires it.

1. Build the checkout form

eSewa v2 expects a signed form POST. Keep the secret key on the server only:

import { createHmac } from "node:crypto";

export function buildEsewaForm(order: { id: string; amount: number }) {
  const message = `total_amount=${order.amount},transaction_uuid=${order.id},product_code=EPAYTEST`;
  const signature = createHmac("sha256", "8gBm/:&EnhH.1/q")
    .update(message)
    .digest("base64");

  return {
    action: "https://rc-epay.esewa.com.np/api/epay/main/v2/form",
    fields: {
      amount: order.amount,
      tax_amount: 0,
      total_amount: order.amount,
      transaction_uuid: order.id,
      product_code: "EPAYTEST",
      signature,
      signed_field_names: "total_amount,transaction_uuid,product_code",
    },
  };
}

2. Verify the callback

Never trust the redirect alone. Verify the signature on the return payload server-side:

export function verifyEsewaResponse(payload: {
  signature: string;
  message: string;
}) {
  const expected = createHmac("sha256", "8gBm/:&EnhH.1/q")
    .update(payload.message)
    .digest("base64");
  return expected === payload.signature;
}

3. Sandbox to production checklist

  1. Swap EPAYTEST and the form URL for your live credentials
  2. Move the secret to an environment variable
  3. Confirm amounts in the callback match your database, not the form
  4. Log transaction UUIDs for reconciliation

Common mistakes

  • Trusting the success redirect without signature verification
  • Putting the secret key in client-side code
  • Forgetting that amounts must match to the paisa

Test the full loop in the sandbox before touching live keys.