Skip to content

Use the adapters directly

Each language has the same shape: build the configured providers from environment variables, call initiate() to start a payment, then call verify() from your return handler with the values you stored. All amounts are integer paisa (1 NPR = 100 paisa).

Language Copy Notes
TypeScript scripts/ts/src/ Keep core.ts, index.ts and the providers you need. Files import each other with .ts extensions; rewrite to .js for NodeNext or extensionless for bundlers if your tsconfig lacks allowImportingTsExtensions.
Python scripts/python/nepal_payments/ Stdlib only. Add cryptography for connectIPS.
Java scripts/java/src/main/java/np/payments/ JDK 17+, no dependencies, blocking and thread-safe.
Kotlin scripts/kotlin/src/main/kotlin/np/payments/ kotlin-stdlib only, suspend API. Server side only, never inside an Android app.
PHP scripts/php/src/ Namespace NepalPayments. Register it in your PSR-4 autoload.
Go scripts/go/payments/ Stdlib only. Copy into your module, for example internal/payments/, and fix the import path.

Set the environment variables for each provider you want. A provider is enabled when its required variables are present. The full list is in Environment variables.

Terminal window
ESEWA_ENV=sandbox
ESEWA_PRODUCT_CODE=EPAYTEST
ESEWA_SECRET_KEY='8gBm/:&EnhH.1/q'
KHALTI_SECRET_KEY=... # from test-admin.khalti.com
KHALTI_WEBSITE_URL=https://shop.example.com
import { createPayments, paymentsConfigFromEnv, newOrderId } from "./payments/index.ts";
const payments = createPayments(paymentsConfigFromEnv());
const init = await payments.get("khalti").initiate({
orderId: newOrderId(), amountPaisa: 150000, description: "Order #42",
returnUrl: "https://shop.example.com/payments/khalti/return",
});
// later, in the return handler: verify with values from YOUR database
const result = await payments.get("khalti").verify({
orderId: attempt.id, amountPaisa: attempt.amountPaisa, providerRef: attempt.providerRef,
});

initiate() returns either a redirect (send the browser to url) or a form (render an auto-submitting POST; every port has a renderAutoSubmitForm helper). Store the providerRef it returns on the attempt: Khalti’s pidx, NPS’s ProcessId and IME Pay’s token are needed by verify().

Every framework needs the same five routes. Web frameworks has complete handlers for Express, Hono, Next.js, FastAPI, Django, Laravel, Spring Boot and Ktor, plus notes for Go net/http, chi and Gin. Mobile apps reuse those routes; see Mobile apps.