A practical look at integrating Nepal's two dominant payment gateways: how the flows differ, what the sandbox will not tell you, and where teams usually lose a week.
Key Takeaways
- A practical look at integrating Nepal's two dominant payment gateways: how the flows differ, what the sandbox will not tell you, and where teams usually lose a week.
Integrating eSewa or Khalti takes an afternoon if you only count the API calls. It takes one to two weeks if you count everything that happens when a payment goes wrong, which is the part that decides whether your finance team trusts the system.
Both gateways follow the same shape: you send the customer away with a signed request, they approve the payment, and the gateway sends them back. What separates a working integration from a fragile one is what your server does in between.
Why you cannot trust the redirect back
The most common bug we see in Nepali checkouts is an order marked paid because the customer's browser reached the success URL. That URL is just a URL. Anyone can visit it. A customer can also close the tab after paying and never reach it at all, which leaves you with money received and an order stuck as pending.
The fix is to treat the redirect as a hint, not a fact. When the browser comes back, call the gateway's verification endpoint from your server with the transaction reference and the amount you expect. Only that response should move an order to paid.
Verify the amount too, not just the status. If your code accepts any successful transaction for an order id, a customer who can edit the request can pay NPR 10 for an NPR 10,000 item.
How the two gateways differ in practice
eSewa's flow is form-based and older in feel: you post a set of fields, including a signature, and read the result back. Khalti's is more API-first, with a payment identifier you exchange for a verified status. Neither is harder than the other, but they fail differently.
eSewa tends to surface problems at the point of redirect, so a bad signature or a mismatched amount shows up immediately in testing. Khalti's failures tend to arrive during verification, which means a checkout can look fine in a demo and break on a real transaction.
If you support both, resist the urge to write one abstraction that covers them. A thin adapter per gateway with a shared interface for "start payment" and "verify payment" is easier to debug than a single class with branches for each provider.
What the sandbox will not tell you
Sandbox environments for both gateways are useful for the happy path and quiet about everything else. Three things you will not learn from them:
- How your code behaves when the gateway is slow. Set a timeout on verification calls and decide what a timeout means. Usually it means "check again shortly", not "fail the order".
- What a real refund looks like. Refunds in Nepal often involve a support process rather than a clean API call, so build your order model to hold a refund-pending state.
- How reconciliation goes at the end of the month. Store the gateway's own transaction reference on every order from day one. Adding it later means matching payments by amount and timestamp, which is miserable.
The failure cases worth handling first
If you have limited time, handle these before anything else. A customer pays but the callback never arrives. A customer pays twice because they refreshed. A payment succeeds at the gateway but your database write fails. All three happen in production, and all three are cheaper to design for than to clean up.
The pattern that handles the first two is an idempotency key: a value unique to the order attempt that your server checks before creating a payment record. The third is handled by verifying on read. If an order is pending and older than a few minutes, ask the gateway what it thinks before showing the customer anything.
Where this fits in a build
For an online store, payments are usually the last major piece and the one most likely to slip. We budget them separately for that reason. An online store starts from NPR 60,000 at AntByte Labs, and a single gateway with verification, refunds, and reconciliation is a meaningful part of that scope rather than a checkbox at the end.
If you are scoping this yourself, the useful question is not "which gateway is better". It is "who on our side reconciles payments each month, and what do they need from the system to do it in an hour instead of a day".
Enjoyed this article? Share it with others!
Written by
AntByte Labs
Engineering · AntByte Labs
AntByte Labs is a Engineering at AntByte Labs, sharing expert insights on technology, software development, and digital innovation to help businesses grow.