Skip to content

Integrating eSewa, Khalti, Fonepay and ConnectIPS: A Complete Guide for Nepali Businesses

Nepali customers pay with wallets, QR codes and bank transfers, not cards. This guide shows how to choose between eSewa, Khalti, Fonepay and ConnectIPS, integrate them securely, and avoid the mistakes that cost businesses money.

Anand KanishkAnand KanishkFounder & CEO21 min read4,786 words
Share

If you sell anything online in Nepal, your checkout lives or dies by local payments. Your customers don't reach for a credit card. They open eSewa or Khalti, scan a Fonepay QR, or pay straight from their bank account with ConnectIPS. International gateways such as Stripe and PayPal don't accept merchants registered in Nepal, so for most Nepali businesses these local options aren't an alternative. They're the only way to get paid.

Yet integrating them well is harder than it looks. Documentation is spread across PDFs and developer portals, each provider has its own signing scheme and amount format, and the most common integration shortcut ("the customer was redirected to the success page, so the order is paid") is also the most expensive mistake you can make.

This guide is written for business owners deciding which gateways to offer and developers and CTOs who have to build it properly. You'll learn:

  • how Nepal's digital payment ecosystem fits together;
  • which gateway suits which kind of business;
  • how each integration works, step by step, with code;
  • how to design a payment system that is secure, reconcilable and ready to scale;
  • the pitfalls we see again and again, and how to avoid them.

Key takeaways

  • Offer eSewa and Khalti for consumer checkouts, add Fonepay QR for in-store and omnichannel sales, and ConnectIPS for high-value or B2B payments.
  • Never mark an order as paid because of a browser redirect. Always confirm the payment server-to-server with the provider's status or lookup API.
  • Watch the units: Khalti and ConnectIPS use paisa; eSewa uses rupees. Mixing them up charges customers 100 times too much, or too little.
  • Build one payment layer in your system that handles every gateway the same way. Adding the next provider then becomes a small job, not a rewrite.
  • Reconcile daily against your settlement reports and bank statements, and issue the VAT invoice only after the payment is confirmed.

Nepal's digital payment landscape in brief

Digital payments in Nepal are regulated by Nepal Rastra Bank (NRB), which licenses two kinds of companies:

  • Payment Service Providers (PSPs) issue wallets and serve customers and merchants directly. eSewa and Khalti are the best known.
  • Payment System Operators (PSOs) run the networks that connect banks, wallets and merchants. Fonepay runs the country's dominant QR payment network, and Nepal Clearing House Limited (NCHL) runs ConnectIPS, the interbank payment system that moves money directly between bank accounts.

For a merchant this means there are three ways customers typically pay:

  1. Digital wallets (eSewa, Khalti): fast and familiar, ideal for everyday purchases. Customers top up from their bank or pay through linked bank accounts.
  2. QR payments (Fonepay and interoperable QR): customers scan a code with their bank or wallet app. This is the default at shops, restaurants and pharmacies across the country.
  3. Direct bank payments (ConnectIPS): money moves from the customer's bank account to yours. Higher limits make it the natural choice for fees, invoices and large orders.

Most successful Nepali checkouts offer at least two of these, because no single option covers every customer.

The four gateways at a glance

eSewaKhaltiFonepayConnectIPS
What it isDigital wallet and payment gateway (PSP)Digital wallet and payment gateway (PSP)QR payment network and gateway (PSO)Interbank payment system by NCHL (PSO)
Customer pays witheSewa wallet and linked bank accountsKhalti wallet, mobile and internet banking, ConnectIPS, cardsAny Fonepay-enabled bank or wallet appTheir bank account, directly
Best forConsumer e-commerce, tickets, subscriptions, top-upsConsumer e-commerce, apps, digital productsIn-store, restaurants, delivery, omnichannel retailFees, insurance, B2B invoices, high-value orders
Integration styleSigned form POST and redirect, then status APIREST API: initiate, redirect, then lookup APIRedirect (web) or dynamic QR with status checksCertificate-signed form POST, then validation API
SignatureHMAC-SHA256Secret key in an Authorization headerHMAC hash (data validation field)RSA-SHA256 with a digital certificate
Amount unitRupeesPaisaRupeesPaisa
SandboxYes, public test credentialsYes, self-serve test merchantThrough onboardingUAT environment through onboarding

Endpoints, fields and limits change from time to time. Treat the details in this guide as a map, and always confirm them against each provider's current documentation before going live.

Which gateway should your business use?

There's no single "best" gateway. The right mix depends on who your customers are and how much they spend.

Business typeRecommended mixWhy
E-commerce storeeSewa + Khalti, then ConnectIPSCovers most wallet users; ConnectIPS catches larger baskets and customers without wallets
Restaurant, retail or pharmacy chainFonepay dynamic QR + eSewa/Khalti onlineQR at the counter, wallets for online and delivery orders, one view of sales
School, college or training instituteConnectIPS + eSewa + KhaltiFees are large and parents bank with many institutions; wallets help with smaller payments
SaaS or subscription productKhalti + eSewa, invoices via ConnectIPSWallets for monthly plans, bank transfer for annual and business plans
Travel and trekking agencyConnectIPS + wallets locally; a bank card gateway for foreign touristsLocal gateways serve Nepali customers; foreign guests usually need card acceptance through a Nepali bank
Cooperative or microfinanceConnectIPS + Fonepay QRDeposits and repayments from bank accounts, QR collection at branches
B2B supplier or distributorConnectIPSHigh limits and a clean bank-to-bank trail for accounting

Do you need more than one? Almost certainly. Each extra method recovers customers who would otherwise abandon the checkout. The key is to add them without making the code messier with every provider. We'll cover that in the architecture section below.

Building a product where payments are central, such as a marketplace or subscription platform? Our guide to building a SaaS MVP in 12 weeks shows where payment work fits in the overall roadmap.

Before you write any code: merchant onboarding

Every gateway requires a merchant agreement before you get live credentials. Start this early, because it usually takes longer than the integration itself.

Documents you'll typically need:

  • company or firm registration certificate;
  • PAN or VAT registration certificate;
  • a business bank account (for settlement);
  • KYC documents of the owners or directors (citizenship, photos);
  • your website or app URL, with your business details visible;
  • for some providers, tax clearance or an authorised signatory letter.

Your website should already have:

  • clear product or service descriptions with prices in NPR;
  • a refund and cancellation policy, terms and conditions and a privacy policy;
  • contact details (address, phone, email);
  • HTTPS everywhere.

Reviewers check these pages, and missing ones are the most common reason for onboarding delays.

Meanwhile, build against the sandbox. eSewa and Khalti offer public test environments, so development doesn't have to wait for the paperwork. Fonepay and ConnectIPS provide test (UAT) access as part of onboarding.

How online payments work in Nepal: the common flow

Despite their differences, all four gateways follow the same basic pattern:

  1. The customer checks out. Your server creates an order and a payment record with a unique transaction ID, the exact amount and the status PENDING.
  2. Your server prepares the payment request. It signs the request (or calls the provider's API) using secret credentials that never leave the server.
  3. The customer is redirected to the provider. They log in to their wallet or bank, and confirm with their PIN or OTP.
  4. The provider redirects the customer back to your success or failure URL, with some details of the result.
  5. Your server verifies the payment, server-to-server. It calls the provider's status, lookup or validation API and checks the status, the amount and the transaction ID.
  6. Only then does your server mark the order as paid, issue the invoice and start fulfilment.

The golden rule: the redirect in step 4 is a hint, not proof. Anyone can type your success URL into a browser, edit its query parameters or replay an old one. Step 5 is what proves payment. Skipping it is the single most common, and most costly, integration mistake in Nepal.

Step 5 also covers the cases where the redirect never arrives: the customer closes the tab, loses mobile data or their phone dies after paying. A background job should recheck every payment still PENDING after a few minutes, so paid orders are never left stranded.

eSewa integration (ePay v2)

eSewa is Nepal's longest-running digital wallet, and many customers pick it by default. Its current web integration, ePay v2, works through a signed HTML form and a status check API.

How it works

  1. Your server builds the payment fields and signs them with HMAC-SHA256 using your secret key.
  2. The browser submits a form (POST) to eSewa's payment page, with the fields and the signature.
  3. The customer pays, and eSewa redirects them to your success_url with a Base64-encoded data parameter containing the result and its own signature. Cancelled or failed payments go to your failure_url.
  4. Your server checks the signature and then confirms the payment with eSewa's transaction status API.

The payment request

The main fields are:

FieldMeaning
amountPrice of the goods or service
tax_amountTax amount (0 if not applicable)
product_service_chargeService charge (0 if not applicable)
product_delivery_chargeDelivery charge (0 if not applicable)
total_amountSum of all the above. It must add up exactly.
transaction_uuidYour unique transaction ID. Never reuse one.
product_codeYour merchant code (eSewa provides a test code for the sandbox)
success_url / failure_urlWhere eSewa sends the customer afterwards
signed_field_namesWhich fields are signed, in order: total_amount,transaction_uuid,product_code
signatureBase64 HMAC-SHA256 of the signed fields

The signature is computed over the signed fields joined as name=value pairs, in the order listed in signed_field_names. The same function works for signing requests and for verifying eSewa's response:

import crypto from "node:crypto";

/** eSewa ePay v2 signature: HMAC-SHA256 over "name=value" pairs, Base64-encoded. */
export function esewaSignature(
  fields: Record<string, string | number>,
  signedFieldNames: string,
  secretKey: string,
): string {
  const message = signedFieldNames
    .split(",")
    .map((name) => `${name}=${fields[name]}`)
    .join(",");
  return crypto.createHmac("sha256", secretKey).update(message).digest("base64");
}

// Building the request on the server
const fields = {
  amount: 1000,
  tax_amount: 130,
  product_service_charge: 0,
  product_delivery_charge: 0,
  total_amount: 1130,
  transaction_uuid: payment.id, // unique per attempt
  product_code: process.env.ESEWA_PRODUCT_CODE!,
  success_url: "https://example.com/payments/esewa/success",
  failure_url: "https://example.com/payments/esewa/failure",
  signed_field_names: "total_amount,transaction_uuid,product_code",
};
const signature = esewaSignature(fields, fields.signed_field_names, process.env.ESEWA_SECRET_KEY!);
// Render an auto-submitting form that POSTs { ...fields, signature } to eSewa's payment URL.

Verifying the response

When the customer returns, decode the data parameter, recompute the signature from the fields it lists, and compare the two using a constant-time comparison:

const payload = JSON.parse(Buffer.from(String(req.query.data), "base64").toString("utf8"));
const expected = esewaSignature(payload, payload.signed_field_names, process.env.ESEWA_SECRET_KEY!);

const valid =
  expected.length === payload.signature.length &&
  crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(payload.signature));
if (!valid) throw new Error("Invalid eSewa signature");

// A valid signature is still not enough: confirm with the status API before fulfilling.

Then call eSewa's transaction status API with your product_code, the total_amount and the transaction_uuid. Treat the payment as paid only when the status is COMPLETE and the amount matches your order.

The status API can also return PENDING, FULL_REFUND, PARTIAL_REFUND, AMBIGUOUS, NOT_FOUND and CANCELED. Handle each one explicitly. PENDING and AMBIGUOUS in particular mean "check again later", not "failed".

eSewa pitfalls

  • Reusing a transaction_uuid. Each payment attempt needs a fresh ID. If a customer retries, create a new attempt linked to the same order.
  • Totals that don't add up. total_amount must equal the sum of the amount, tax, service and delivery charges, or the request is rejected.
  • Comparing amounts as text. The response may format amounts differently from your request (for example 1130.0). Compare them as numbers, in paisa, not as strings.
  • Mixing up test and live settings. The sandbox and production use different URLs, product codes and secret keys. Keep them in environment configuration, never in code.

Khalti integration (ePayment / KPG-2)

Khalti's web checkout is a clean REST API. You start a payment, redirect the customer to a hosted payment page, and confirm the result with a lookup call. Khalti's checkout also lets customers pay through mobile banking, internet banking, ConnectIPS and cards, so it can serve customers who don't use the Khalti wallet.

How it works

  1. Your server calls the initiate endpoint with your secret key in the Authorization header.
  2. Khalti returns a pidx (payment identifier) and a payment_url.
  3. You redirect the customer to payment_url.
  4. After paying, the customer returns to your return_url with query parameters such as pidx, status, transaction_id, amount and purchase_order_id.
  5. Your server calls the lookup endpoint with the pidx to confirm the final status and amount.

Starting a payment

const KHALTI_BASE = process.env.KHALTI_BASE_URL!; // sandbox or production base URL from Khalti's docs

const response = await fetch(`${KHALTI_BASE}/api/v2/epayment/initiate/`, {
  method: "POST",
  headers: {
    Authorization: `Key ${process.env.KHALTI_SECRET_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    return_url: "https://example.com/payments/khalti/return",
    website_url: "https://example.com",
    amount: 113000, // in PAISA: Rs 1,130 = 113000
    purchase_order_id: payment.id,
    purchase_order_name: `Order #${order.number}`,
    customer_info: { name: customer.name, email: customer.email, phone: customer.phone },
  }),
});
if (!response.ok) throw new Error(`Khalti initiate failed: ${response.status}`);

const { pidx, payment_url } = await response.json();
await savePidx(payment.id, pidx); // store it: you need it for the lookup
// Redirect the customer to payment_url

Confirming the payment

const lookup = await fetch(`${KHALTI_BASE}/api/v2/epayment/lookup/`, {
  method: "POST",
  headers: {
    Authorization: `Key ${process.env.KHALTI_SECRET_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ pidx }),
});
const result = await lookup.json();

if (result.status === "Completed" && result.total_amount === payment.amountPaisa) {
  await markPaid(payment.id, { providerRef: result.transaction_id });
}

The lookup can also return Pending, Initiated, Expired, User canceled, Refunded and Partially Refunded. Only Completed means paid. Payment links expire after a while, so an Expired payment needs a fresh initiate call if the customer tries again.

Khalti pitfalls

  • Paisa, not rupees. This is the classic Khalti bug. Store every amount in your system as an integer number of paisa and convert only for display.
  • Trusting the query string. The status=Completed on your return URL can be edited by anyone. Only the lookup result counts.
  • Leaking the secret key. The initiate and lookup calls must run on your server. A secret key in frontend or mobile app code is a key anyone can extract.
  • Not storing the pidx. Without it you can't confirm or reconcile the payment later.

Fonepay integration (web payments and dynamic QR)

Fonepay is the network behind the red-and-white QR codes found at counters across Nepal. Customers can pay with the apps of member banks and wallets, which makes Fonepay the widest-reaching option for in-person and omnichannel businesses.

Merchants usually join Fonepay through a member bank, which provides the merchant code, secret key and technical specification. Unlike eSewa and Khalti, much of the documentation is shared during onboarding rather than published openly.

The two integration styles

1. Web payments (redirect). This works much like eSewa:

  • Your server builds a request with fields such as the merchant code, a unique product reference number (PRN), the amount, the date, remarks and the return URL.
  • It signs the request with an HMAC hash in the data validation (DV) field, using your secret key.
  • The customer is redirected to Fonepay, pays from their bank or wallet app, and returns to your site with the payment status and a signature.
  • Your server verifies the signature and then confirms the transaction with Fonepay's verification API before marking it paid.

2. Dynamic QR. This is ideal for POS systems, restaurants, delivery and kiosks:

  • Your system requests a QR code for one specific amount and order.
  • The customer scans it with any supported app.
  • Your system learns the result through Fonepay's real-time notification channel or a status check API, so the cashier sees "Paid" on screen without checking phones or SMS.

Dynamic QR removes the most common in-store problem with static QR codes: matching an anonymous payment to the right order, and catching customers who "show" a payment screen that was never completed.

Fonepay pitfalls

  • Static QR for online orders. Static QR codes don't tell you which order was paid. Use dynamic QR or the web flow whenever you need automatic matching.
  • Reusing PRNs. Like eSewa's transaction IDs, each attempt needs a unique reference.
  • Skipping verification at the counter. Staff should rely on your system's confirmation, not the customer's phone screen.

ConnectIPS integration (direct bank payments)

ConnectIPS, run by Nepal Clearing House Limited (NCHL), debits the customer's bank account directly. Its high transaction limits and bank-grade trail make it the go-to option for school and college fees, insurance premiums, B2B invoices and large purchases.

ConnectIPS is also the most security-heavy of the four integrations. Requests are signed with a digital certificate (RSA-SHA256) issued to you during onboarding, rather than a shared secret.

How it works

  1. During onboarding, NCHL provides your merchant ID, app ID, app name, API password and a certificate file (.pfx) containing your private key.
  2. For each payment, your server builds a token by signing a string of the transaction fields with your private key.
  3. The browser posts the fields and the token to the ConnectIPS login page, and the customer logs in to their bank and approves the payment.
  4. The customer returns to your success or failure URL.
  5. Your server calls the transaction validation API (authenticated with your app ID and password, and including a freshly signed token) to confirm the result before fulfilling.

Signing the token

import crypto from "node:crypto";
import fs from "node:fs";

// Convert the .pfx once and keep the PEM in a secrets store, not in your repository:
// openssl pkcs12 -in CREDITOR.pfx -nocerts -nodes -out connectips-private.pem
const privateKey = fs.readFileSync(process.env.CONNECTIPS_KEY_PATH!, "utf8");

export function connectIpsToken(t: {
  merchantId: string; appId: string; appName: string;
  txnId: string; txnDate: string; amountPaisa: number;
  referenceId: string; remarks: string; particulars: string;
}): string {
  const message =
    `MERCHANTID=${t.merchantId},APPID=${t.appId},APPNAME=${t.appName},` +
    `TXNID=${t.txnId},TXNDATE=${t.txnDate},TXNCRNCY=NPR,TXNAMT=${t.amountPaisa},` +
    `REFERENCEID=${t.referenceId},REMARKS=${t.remarks},PARTICULARS=${t.particulars},TOKEN=TOKEN`;
  return crypto.createSign("RSA-SHA256").update(message).sign(privateKey, "base64");
}

The exact field order and date format come from NCHL's specification. A single character out of place produces an invalid token, so build this string in one well-tested function.

ConnectIPS pitfalls

  • Amounts in paisa. As with Khalti, TXNAMT is in paisa.
  • Certificate handling. The private key is the most sensitive credential in your payment stack. Keep it out of source control, restrict who can read it, and plan for renewal before the certificate expires.
  • Field order and formatting. Signature failures are almost always caused by a field in the wrong order, an unexpected space, or the wrong date format.
  • Treating a redirect as success. As with every gateway, only the validation API confirms the payment.

Designing an enterprise-grade payment system

Getting a single gateway to work is a weekend project. Running four of them reliably, with thousands of orders, refunds, audits and month-end closing, is an engineering problem. These are the design principles we apply on every payment project.

1. One payment layer, many providers

Don't spread eSewa calls through your checkout, Khalti calls through your mobile API and ConnectIPS code through your billing module. Build a single payment service with one interface:

  • createPayment(order, provider) returns what the customer needs (a form, a redirect URL or a QR code);
  • verifyPayment(paymentId) asks the provider for the truth;
  • refund(paymentId, amount) where the provider supports it.

Each gateway becomes an adapter behind that interface. The rest of your system only sees payments with a status, and adding a fifth provider later only means writing one more adapter.

2. A strict payment state machine

Every payment moves through a small set of states, and only certain transitions are allowed:

CREATED → PENDING → COMPLETED, with side exits to FAILED, EXPIRED and CANCELLED, and later REFUNDED or PARTIALLY_REFUNDED.

Enforce this in code and in the database. A payment that is COMPLETED can never go back to PENDING, and an order can only be fulfilled from a COMPLETED payment.

3. Idempotency everywhere

Customers double-click, browsers retry and redirects arrive twice. Use your unique transaction ID as an idempotency key:

  • verifying the same payment twice must not fulfil the order twice;
  • a database unique constraint on (provider, provider_reference) stops one provider transaction from being counted against two orders;
  • a retry by the customer creates a new attempt, linked to the same order.

4. A data model built for audits

For every payment attempt, store:

FieldWhy
Order ID and attempt IDLinks money to what was sold
Provider and provider reference (pidx, transaction code, PRN, TXNID)Needed for lookups, disputes and reconciliation
Amount in paisa and currencyNo floating-point rounding errors
Status and status history with timestampsShows exactly what happened, and when
Raw request and response payloads (with secrets removed)Your evidence when something is disputed
Who or what changed the status (redirect, background job, admin)Accountability

5. Background verification and recovery

Run a scheduled job that rechecks every payment still PENDING. Check after a couple of minutes, then with growing gaps, until the provider gives a final answer or the payment expires. This recovers the payments where the customer paid but never came back to your site, which is a surprisingly large share of mobile traffic.

6. Security by default

  • Keep all keys, secrets and certificates on the server, in a secrets manager or encrypted environment configuration.
  • Serve everything over HTTPS, and accept return URLs only on your own domains.
  • Compare signatures in constant time, and validate every field you receive.
  • Log payment events, but never log secret keys, full tokens or customer PINs and OTPs.
  • Keep your platform patched. Payment pages are a prime target, as we showed in our breakdown of the PHP2Shell vulnerabilities.

7. Observability

Track the conversion rate per gateway, the share of payments stuck in PENDING, verification failures and provider response times, and alert your team when one gateway starts failing. When a provider has an outage, you'll know within minutes and can temporarily hide that option at checkout instead of losing sales.

Settlement, reconciliation and accounting

Getting paid is only half the job. The money then has to arrive in your bank account, match your records and be accounted for correctly.

Settlement. Providers settle collected funds to your bank account on a schedule set in your merchant agreement, often the next working day. Each provider charges a merchant discount rate (MDR) or service fee per transaction. Rates are negotiated and vary by provider, business type and volume, so ask each one for a written fee schedule and compare them before you sign.

Daily reconciliation. Every day, match three sources:

  1. the payments your system marked COMPLETED;
  2. the provider's transaction or settlement report;
  3. the credits in your bank statement.

Any mismatch, such as a payment the provider has but you don't, or a settlement amount that doesn't match after fees, becomes an exception for your finance team. Automating this is one of the highest-value jobs you can give to workflow automation: what takes an accountant hours every week becomes a short exception report. Our list of business processes to automate first covers it in more detail.

Invoices and VAT. Issue the tax invoice only after a payment is confirmed, and record the gateway reference on it. If you're registered for VAT and use electronic billing, make sure your billing system meets the Inland Revenue Department's requirements for e-billing and real-time reporting where they apply to your business.

Refunds. Refund support differs between providers. Some offer it through the merchant dashboard, some by API, some through a request to the provider. Define your refund process up front, record every refund against the original payment, and include refunds in your reconciliation.

Mobile apps: extra considerations

If you're building a mobile app, payments need extra care:

  • Use official SDKs where they exist. eSewa and Khalti provide SDKs and plugins for Android, iOS and Flutter, which give a smoother experience than a raw web view.
  • Handle the return trip. Payment flows can switch between your app, a browser and a wallet app. Use deep links or app links so customers land back in the right place, and confirm the payment from your server, not from the app.
  • Plan for patchy connectivity. On mobile data, the confirmation step is where most payments get "lost". Background verification on the server (see above) is what makes this safe.
  • Never ship secrets in the app. Anything in an app package can be extracted. The app should ask your server to start a payment and report the result.

Choosing a framework for a payment-heavy app? Our comparison of Flutter vs React Native covers performance, SDK support and long-term maintenance. And if you need a team to build it, see our mobile app development services.

Testing checklist before you go live

Run every scenario below for each gateway, in the sandbox first and then with small real payments in production:

  • Successful payment: the order becomes paid exactly once.
  • Customer cancels on the provider's page: the order stays unpaid and can be retried.
  • Customer closes the browser after paying: the background job marks the order paid.
  • Payment link or session expires: the customer can start a new attempt.
  • Success URL opened by hand, edited or replayed: nothing is fulfilled.
  • The same callback arrives twice: the order is fulfilled once.
  • Amounts with tax, delivery and discounts: the totals match to the paisa.
  • The provider is down or slow: the checkout shows a clear message and offers other methods.
  • Refund, full and partial: recorded, reconciled and reflected on the order.
  • Reconciliation report: every test payment matches the provider's report.
  • Secrets: none in frontend code, app bundles, logs or the repository.
  • Live credentials: switched on with environment configuration, not code changes.

12 common pitfalls (and how to avoid them)

  1. Marking orders paid on redirect. Always verify server-to-server.
  2. Rupees versus paisa. Store integers in paisa and convert only at the edges.
  3. Floating-point money. 0.1 + 0.2 isn't 0.3 in JavaScript. Never use floats for amounts.
  4. Reused transaction IDs. Every attempt gets a new unique ID.
  5. Secrets in the frontend or app. All signing and API calls happen on the server.
  6. No background verification. Paid customers who never return to your site end up with "failed" orders.
  7. Ignoring PENDING and AMBIGUOUS. These mean "check again", not "failed".
  8. No unique constraint on provider references. One payment could be counted against two orders.
  9. Hard-coded sandbox settings. Test URLs and keys leak into production, or the other way round.
  10. Not reconciling. Small mismatches pile up into large month-end problems.
  11. Invoicing before confirmation. VAT invoices for payments that never completed create tax headaches.
  12. One gateway only. Every missing payment method is a share of customers who can't pay you.

How long does integration take, and what does it cost?

For an experienced team, a single gateway integrated properly (with verification, background checks and tests) is a matter of days, not weeks. A multi-gateway payment layer with reconciliation, refunds and reporting is a larger project, usually measured in weeks, depending on your existing system, mobile apps, accounting integration and how many gateways you need.

The bigger variable is often onboarding, which depends on your documents and the providers' review queues. Start it in parallel with development.

Costs depend on scope: the number of gateways, web and mobile coverage, reconciliation and accounting integration, and the state of your current platform. Our transparent breakdown of custom software development costs explains what drives the price, and we're happy to give you a fixed estimate after a short call.

Frequently asked questions

Which payment gateway is best in Nepal? There isn't one best gateway for everyone. For most online businesses, eSewa and Khalti together cover the majority of consumers. Add ConnectIPS for high-value or business payments, and Fonepay QR if you also sell in person.

Can I use Stripe or PayPal in Nepal? Not as a Nepal-registered merchant: Stripe and PayPal don't currently support merchant accounts for businesses based in Nepal. To accept international cards, you'll typically need a card acquiring service from a Nepali bank.

Do I need a registered company to accept online payments? Yes. Every provider requires a registered business, a PAN or VAT certificate and a business bank account before issuing live credentials.

Is it safe to integrate payment gateways on a WordPress or PHP website? It can be, if the plugin or code verifies every payment server-to-server, keeps secrets on the server, and the site is kept up to date. Many breaches start with an outdated plugin, not with the gateway itself. If you're choosing a platform, compare the options in our Next.js vs WordPress guide.

How do I know a payment really succeeded? Only through the provider's server-side status, lookup or validation API, never from the redirect URL or a screenshot. Check the status, the amount and the transaction ID before fulfilling the order.

Can customers pay with cards through these gateways? Khalti's checkout supports several methods beyond its wallet, including bank transfers and cards. For broad international card acceptance, add a bank card gateway alongside the local options.

Do these gateways support recurring subscription payments? Automatic recurring charges are limited with wallet-based payments in Nepal. Most SaaS businesses send renewal reminders with a pay-now link, or invoice business customers for annual plans payable by ConnectIPS. Ask each provider what is available to your business at the time you apply.

How long does settlement take? It depends on your merchant agreement. Next-working-day settlement is common, but confirm the schedule and fees with each provider in writing.

Conclusion

Nepal's payment ecosystem has matured quickly. Between eSewa, Khalti, Fonepay and ConnectIPS, you can reach almost every customer in the country, online and at the counter. Businesses that get the most out of it follow a few simple rules:

  • offer the right mix of gateways for their customers;
  • verify every payment on the server;
  • treat amounts and transaction IDs with discipline;
  • run all providers through one well-designed payment layer;
  • reconcile every day.

Get those right, and payments become something your business can rely on rather than a weekly fire to put out.

Need a hand? At Zwicky Technology we design and build payment-ready platforms for Nepali businesses, from e-commerce stores and school fee portals to SaaS products and POS systems, with eSewa, Khalti, Fonepay and ConnectIPS integrated properly from day one. Explore our custom software development and SaaS product development services, or book a free consultation to talk through your project. Not sure who to trust with something as critical as payments? Here are 10 questions to ask any software development company before you sign.

Found this useful?

Share it with your network.

Share

FAQ

Frequently asked questions

Can't find what you're looking for?

Ask us directly

About the author

Anand Kanishk

Anand Kanishk

Founder & CEO

Software engineer by profession, social engineer by passion: building technology that creates meaningful change.

Continue learning

All articles