Integrating eSewa, Khalti, and connectIPS without the pain
Practical notes from four payment integrations: idempotency, reconciliation, and why the callback is never enough on its own.
Aayush Shrestha
CT Tech Nepal
Every Nepali payment gateway documents a callback. Every production system eventually discovers that callbacks do not always arrive. Sometimes the network drops, sometimes the user closes the app, sometimes the gateway retries into an endpoint that already moved on.
The pattern we now use on every integration: the callback is a fast path, never the source of truth. The source of truth is a reconciliation job that polls the gateway for any transaction still in a pending state after a defined window. That job is the thing that keeps your ledger honest.
Idempotency is the second requirement. Every payment initiation carries a client-generated reference. If the same reference arrives twice, you return the original result rather than creating a second charge. This sounds obvious until you are debugging a customer charged twice because the user double-tapped.
Finally, treat the sandbox as a rough approximation. Response shapes differ subtly between sandbox and production, error codes are sometimes undocumented, and settlement timing varies. Build enough logging around the integration that when a merchant asks about a specific transaction, you can answer within five minutes.
Key takeaways
- Callbacks are a fast path, reconciliation is the truth
- Idempotency keys on every initiation
- Log enough to answer merchant questions quickly
- Budget for sandbox–production differences