- ✓Working knowledge of backend APIs (Node.js/Express, Laravel, or Python)
- ✓Understanding of cryptographic hashing (HMAC-SHA256 and RSA)
- ✓A test merchant account on eSewa Developer Portal or Khalti Merchant Portal
- ✓Basic understanding of HTTP request-response lifecycles and webhooks
🚀 What You Will Learn & Build
- ▸Direct feature-by-feature comparison of eSewa, Khalti, ConnectIPS, and Fonepay
- ▸KYC documentation and merchant registration requirements for personal vs. registered business entities
- ▸Security best practices: preventing client-side spoofing, replay attacks, and duplicate order fulfillment
- ▸A structured decision tree: which gateway to pick for your startup, e-commerce store, or college project
- ▸Direct links and learning pathways for step-by-step code implementations
The Digital Payment Ecosystem in Nepal: 2026 Overview
| Gateway | Primary Mechanism | Integration Complexity | Fee Structure (Approx.) | Best Used For |
|---|---|---|---|---|
| eSewa (ePay v2) | Wallet redirect + HMAC-SHA256 | Beginner / Intermediate | 2.0% – 3.0% | General retail e-commerce, consumer subscriptions |
| Khalti (ePayment v2) | REST JSON API (`pidx`) + redirect | Beginner Friendly | 2.0% – 2.5% | Modern web apps, MERN stack, developer-first startups |
| ConnectIPS | Direct bank debit + RSA SHA256 | Advanced (Cryptographic keys) | Flat NPR 2 – 8 per txn | High-value B2B transactions, tuition, official fees |
| Fonepay QR | Dynamic Interoperable EMV QR | Intermediate (Next.js/APIs) | 1.5% – 2.0% | Mobile banking users across 50+ commercial banks |
Which Payment Gateway Should You Integrate First?
Never tightly couple your checkout controller to one provider. Create an abstract PaymentGatewayInterface in your application with initiate(), verify(), and refund() methods. This enables you to toggle eSewa, Khalti, or ConnectIPS without rewriting order fulfillment logic.
Non-Negotiable Payment Security Rules
// Example of safe, idempotent order fulfillment logic
export async function fulfillOrderSafely(transactionUuid: string, paidAmount: number) {
const order = await db.orders.findOne({ transactionUuid });
if (!order) {
throw new Error("Order not found");
}
// Check state machine: Prevent duplicate fulfillment
if (order.status === "PAID") {
console.warn(`Duplicate callback ignored for order: ${transactionUuid}`);
return { success: true, message: "Already fulfilled" };
}
// Strict verification: Verify amount match
if (order.totalAmount !== paidAmount) {
await db.orders.updateOne({ transactionUuid }, { status: "SUSPICIOUS_AMOUNT_MISMATCH" });
throw new Error("Fraud alert: Paid amount does not match recorded order amount");
}
// Update status atomically
await db.orders.updateOne(
{ transactionUuid },
{
status: "PAID",
paidAt: new Date(),
paymentVerifiedVia: "SERVER_API"
}
);
return { success: true, message: "Order fulfilled securely" };
}Comprehensive Cluster Tutorials & Code Guides
✨ Expected Output & Verification
A robust conceptual and architectural roadmap that allows any developer in Nepal to select, design, and securely integrate payment systems without common amateur vulnerabilities.
🧪 How to Test the Implementation
- 1Review the gateway comparison matrix against your company's or project's entity status
- 2Register a developer account on developer.esewa.com.np and admin.khalti.com
- 3Bookmark the cluster tutorials matching your chosen tech stack (Laravel, Node.js, Next.js)
- 4Set up test environment variables in your local .env file before writing code
⚠️ Common Errors & How to Fix Them
Root Cause: Placing merchant credentials in React, Vue, or frontend HTML where any visitor can inspect source code.
Fix: Move all secret keys to server-side .env files. Only public merchant codes belong in frontend forms.
Root Cause: Sending 100.5 to gateway while database has 100.50, causing signature validation or verification failure.
Fix: Normalize all amounts using number_format($amt, 2, '.', '') or Number(amt).toFixed(2).
🛡️ Security Considerations & Best Practices
- !Never trust client redirects without server-to-server transaction status queries.
- !Store payment callback logs with raw payloads in a separate audit table for financial reconciliation.
- !Use HTTPS on all environments except local development to prevent man-in-the-middle payload tampering.
❓ Frequently Asked Questions (FAQ)
For production live credentials, eSewa and ConnectIPS legally require a registered business (PAN/VAT certificate, company registration, and bank account). However, Khalti allows personal developer sandboxes for testing, and recently introduced personal merchant onboarding for registered individual taxpayers.
📌 Summary of Key Takeaways
Nepal's digital payment ecosystem offers world-class wallet and banking infrastructure. Success comes down to selecting the right provider for your audience, adhering strictly to server-side cryptographic verification, and enforcing idempotency.
Official References & Further Reading
Written by Manoj Neupane
AuthorSoftware developer and programming instructor, Nepal
Building software systems and SaaS platforms with Laravel, Next.js, and Node.js. Passionate about helping students and developers in Nepal master practical, real-world development skills.