Integrating eSewa, Khalti & Dynamic FonePay QR Gateways in .NET
My phone buzzed. It was my brother — CSIT student, second year, probably surviving on noodles and tei dai ko sasto Mo:mo.
"Dai, 3 days bhayo. Khalti integrate hunna. Project submission Monday ho."
I knew that panic. That specific brand of developer anxiety when:
The deadline is breathing down your neck The documentation makes sense… until it doesn't You've rewritten the same code 17 times You're questioning your career choices
"Video call gar," I replied.
The Screen Share of Chaos
His screen was a beautiful disaster. 23 Brave tabs open (12 of them AI). Rider with more red squiggles than actual code.
"Dai, documentation ma yo lekheko cha. Tara mildai milena."
I smiled. Not because it was funny. But because I'd been there. We've ALL been there.
Rewind: 2022. TU Convocation Season.
It was convocation form filling season. TU students everywhere were trying to pay online. Khalti team pinged me.
"Sushil, developers are struggling to integrate our API. Can you help?"
Back then, I thought: "How hard can payment integration be?"
Spoiler alert: Hard enough that people were giving up and going back to bank deposits. In 2022. In Nepal. Where the country was desperately trying to go digital.
So I built plugin.web.eSewa.and.Khalti.
Developers downloaded it. Projects shipped. Crisis averted.
I moved on. Built other stuff. Forgot about it.
My Brother's Call Was a Wake-Up Call
I pulled up my old package. The code looked like it was written by someone who just
discovered async/await and went wild with it. The package name was longer than some
of my functions. And the architecture? Let's just say "extensible" wasn't in the vocabulary.
"What happens when FonePay becomes popular?"
"What about that new gateway launching next month?"
The answer: copy-paste chaos. Refactor hell. Developer tears.
Nope. Not on my watch.
Introducing: Nepal.Payments.Gateways
I did what any reasonable developer would do at midnight: started a complete rewrite.
Two rules:
Install it in 10 seconds:
dotnet add package Nepal.Payments.Gateways
Step 1 — Initialize (Same for ALL Gateways)
// using Nepal.Payments.Gateways.Models.Khalti.PaymentRequest
var paymentManager = new PaymentManager(
paymentMethod: PaymentMethod.Khalti, // or Esewa, or FonePay
paymentVersion: PaymentVersion.V2,
paymentMode: PaymentMode.Sandbox,
secretKey: <em>khaltiSecretKey
);
Step 2 — Create the Request
var request = new PaymentRequest()
{
Amount = 1300,
PurchaseOrderId = "order</em>" + DateTime.Now.Ticks,
CustomerInfo = new CustomerInfo
{
Name = "Your Customer",
Email = "customer@email.com",
Phone = "98XXXXXXXX"
},
ProductDetails = new[]
{
new ProductDetail
{
Name = "Your Product",
TotalPrice = 1300,
Quantity = 1
}
}
};
Step 3 — Get Payment URL and Redirect
var response = await paymentManager.InitiatePaymentAsync<dynamic>(request);
return Redirect(response.Data.PaymentUrl);
That's it. Three steps. You can skip the official documentation — but don't quote me on that. 😄
"But Dai, What About Verification?"
Even simpler:
var paymentManager = new PaymentManager(
paymentMethod: PaymentMethod.Khalti,
paymentVersion: PaymentVersion.V2,
paymentMode: PaymentMode.Sandbox,
secretKey: <em>khaltiSecretKey
);
var response = await paymentManager.VerifyPaymentAsync<dynamic>(pidx);
if (response?.Data is PaymentResponse v)
{
Console.WriteLine($"Paid: Rs. {v.TotalAmount}");
Console.WriteLine($"Transaction: {v.TransactionId}");
// Party time! vanna hunthyo — raksi khadainas... ehh piudainas
}
eSewa? Copy-Paste-Change-One-Line
// using Nepal.Payments.Gateways.Models.Esewa.PaymentRequest
// Literally just change this one line:
paymentMethod: PaymentMethod.Esewa // Was: PaymentMethod.Khalti
// Everything else? EXACTLY THE SAME.
That's the magic. Same pattern. Same structure. Different gateway.
Version Support (V1 & V2)
// For newer implementations
paymentVersion: PaymentVersion.V2
// For legacy systems still on old APIs
paymentVersion: PaymentVersion.V1
Just specify the version — the package handles the rest. No need to rewrite your entire codebase when APIs evolve.
"Dai, Testing Kasari Garney?"
Bookmark this. You'll need it at 3 AM when you're testing payments.
Live demo: payments-demo.sksushil.info.np/payment
eSewa Test Credentials
Username: 9806800001 (or 2 / 3 / 4 / 5)
Password: Nepal@123
Token: 123456
Merchant ID: EPAYTEST
Secret Key: 8gBm/:&EnhH.1/q
Khalti Test Credentials
Mobile Number: 9800000001 (or 2 / 3 / 4 / 5)
Pin: 1111
OTP: 987654
Secret Key: live</em>secret<em>key</em>68791341fdd94846a146f0457ff7b455
These are sandbox credentials only. Never use them in production.
What's Cooking Next? FonePay Dynamic QR
var qrManager = new PaymentManager(
paymentMethod: PaymentMethod.FonepayQR,
paymentVersion: PaymentVersion.V1,
paymentMode: PaymentMode.Sandbox,
secretKey: _fonepaySecretKey
);
var qrCode = await qrManager.GenerateQRAsync(amount, reference);
// Boom. QR code ready.
Same pattern. New gateway. Zero headaches.
The REAL Test
I sent the package to my brother.
Me: "Try this."
Him (30 minutes later): "Dai, kaam bhayo!"
Me: "Demo pathai."
Him (sent video of successful payment)
Me: "la mojj gares."
If he can integrate it at midnight before a Monday deadline, I'd call that a win.
Real Talk
Look, I'm not building this because I'm some coding wizard.
I'm building it because my brother was panicking about a project deadline.
Because somewhere right now, a developer in Pokhara is staring at Khalti/eSewa documentation wondering why their callback isn't working.
Because in Butwal, someone just spent 6 hours debugging a signature mismatch.
Because we've ALL been that person.
If this package saves you even one debugging session — if it helps you ship your project on time — then it was worth rebuilding from scratch.
The package is open source and free. If it helps you, a ⭐ on GitHub goes a long way.
Tags
Subscribe to Newsletter
Get notified about new articles
Related Articles
The Bridge That Never Breaks — gRPC Streaming in a Hybrid Offline World
How gRPC streaming became the backbone of a hybrid system connecting cloud services with multiple of...
Integrating eSewa, Khalti & Dynamic FonePay QR in .NET
Complete guide to integrating eSewa, Khalti and FonePay Dynamic QR in .NET with code examples....