azyware
Technology

Wallets, UPI and payments in super apps

EZ
Eazyware
· 7 min read
Quick answer

What should you know about UPI integration in a super app with a wallet?

Payments need a wallet ledger, UPI and card rails, reconciliation and refunds designed as a subsystem, not an afterthought. In a super app the payment layer serves every module, so build it once as a shared service: a double-entry ledger, a gateway abstraction, webhook handling and daily reconciliation.

A UPI integration app is not a checkout button wired to a gateway SDK. In a super app, where rides, food, bills, tickets and a stored-value wallet all share one balance and one payment screen, payments are a subsystem with their own data model, failure modes and daily operations. Get the subsystem right and every new module inherits working payments. Get it wrong and each module grows its own refund logic and its own reconciliation spreadsheet. This article sets out how we design the payments layer for super apps in India: the ledger, the rails, the gateway abstraction, webhooks, refunds and reconciliation.

Why payments are a subsystem, not a feature

Three things make in-app payments different from any other feature. Money must balance to the paisa, every day, against statements you do not control. Failures are asynchronous: a UPI payment can succeed at the bank after your app has shown a timeout. And regulators care: stored value, KYC limits and settlement rules are set by the RBI and NPCI, not by your product team. A feature can be iterated; a subsystem must be correct first and iterated carefully. The RBI publishes the directions on prepaid instruments and payment aggregators that shape the wallet and gateway decisions below.

The rails available to an Indian super app

RailHow it works in-appStrengthsWatch-outs
UPI intentApp opens the user's UPI app with a prefilled request; user approves; result returns via callback and webhookFast, low friction on Android, no card entryCallback can be lost; always confirm via webhook or status poll
UPI collectUser enters a UPI ID; a request is pushed to their app; they approveWorks when intent is unavailable, useful for recurring or webExpiry and pending states must be handled explicitly
UPI AutopayMandate registered once; debits recur within limitsSubscriptions and repeat services without re-authenticationMandate setup, modification and revocation flows are their own screens
CardsTokenised card via gateway; two-factor authentication redirect or native OTPFamiliar for larger amounts; needed for international usersCard-on-file rules require network tokenisation
Net bankingRedirect to bank; return with statusCoverage for users without UPI or cardsSlowest and most drop-prone
Stored-value walletYour own ledger balance, loaded via any rail aboveInstant, offline-tolerant, enables split payments and cashbackRegulatory limits, KYC tiers, and you now hold customer money

The wallet ledger is the centre of the design

Whether or not you offer a customer-facing wallet, build a double-entry ledger. Every event, a top-up, a payment, a commission, a refund, a cashback, a payout, is a journal entry with balanced debits and credits across accounts: the customer's wallet, the gateway receivable, the merchant payable, the platform revenue, the tax liability. The user's balance is the sum of entries, never a column you update. This gives you an audit trail for free, makes reconciliation a comparison of two journals, and means a refund of a partially wallet-funded order is a ledger operation rather than a special case in the order code.

Idempotency and ordering

Every write into the ledger carries an idempotency key derived from the source event (gateway payment ID, order ID plus action). Webhooks arrive twice, retries happen, and users tap the button again; the ledger must treat repeats as no-ops. Entries are also ordered per account so that a refund cannot be applied before the payment it refunds. These two properties are what let the system survive the messy reality of mobile networks.

Gateway abstraction: one interface, several providers

Build a thin payment-provider interface inside your backend and put the gateway SDKs behind it. The interface needs a small set of operations: create payment, fetch status, refund, create mandate, cancel mandate, and a webhook verifier. Razorpay UPI flows, another aggregator's card rails and a bank's direct integration then become adapters. This is what lets you move volume between providers during an outage or a pricing change, and it keeps provider-specific quirks out of the order and wallet code. The Razorpay documentation is a good reference for what a modern aggregator's webhooks and status APIs look like.

Webhooks, callbacks and the truth about status

The mobile app should never decide whether a payment succeeded. It shows what the gateway callback says, then waits for the backend, which trusts only a verified webhook or a status API call. The order moves to paid when the backend says so, and the app subscribes to that change. Design for the three awkward cases: callback says failed but the webhook later says success (show a pending state and reconcile); webhook never arrives (a scheduled status poll for payments pending beyond a few minutes); and the user closes the app mid-flow (the pending payment is visible next time they open it, with the outcome).

Refunds, partial refunds and reversals

Refund logic in a super app is complicated because an order can be funded from several sources: wallet, promotional credit, UPI. The rule we implement is refund in reverse order of funding, so promotional credit returns as credit, wallet returns to wallet, and only the gateway portion goes back through the gateway. Partial refunds, common in food and grocery, apply the same waterfall on the refunded amount. Every refund is a ledger entry with a link to the original payment, and the customer sees the split in their transaction history so support does not have to explain it.

Reconciliation is a daily job from day one

Each morning a job pulls the previous day's settlement and transaction reports from each provider and compares them line by line with the ledger. Three lists come out: matched, present in the gateway but not in the ledger (a missed webhook), and present in the ledger but not at the gateway (a payment recorded on a lost callback). Each unmatched item is a ticket for the finance team with the evidence attached. Fees and taxes are checked against the contracted rates. Finance owns this report; engineering's job is to keep the unmatched list short. Leaving it until month end is how small daily drift becomes an unexplained sum.

Wallet-specific concerns

Offering a stored-value wallet changes your regulatory position, because you are holding customer money. Limits and KYC tiers apply, balances must be viewable and exportable, and expiry rules for promotional credit must differ from real money. Many super apps start with a closed-loop wallet used only inside the app and consider broader use once volumes justify the compliance work. Whatever the model, keep real money and promotional credit in separate ledger accounts.

A worked example

A regional super app with rides, food delivery and utility bill payments had built payments three times, once per module, on the same gateway. Refunds worked differently in each, the finance team reconciled from three exports, and a gateway outage took all three modules down at once. We extracted a shared payments service: one ledger, one provider interface with two aggregators behind it, one webhook handler and one nightly reconciliation report. Each module then called the service and stopped owning payment state. Refunds then behaved the same everywhere, finance got a single exceptions list, and a later provider outage was handled by shifting volume rather than by apologising. The super app development page describes this shared-services approach, and our WhatsApp agent and personalisation case study for a D2C brand shows payment links and order status feeding a conversational channel from the same backend.

Team and timeline

A payments subsystem for a super app is usually a senior backend engineer who owns the ledger and provider interface, a second backend engineer for webhooks, refunds and reconciliation, a mobile engineer for the intent and collect flows, and a QA engineer who spends most of the time on failure cases, over six to ten weeks. It is scoped inside super app development from $63,000 / ₹41.6L, or as a standalone piece of API development and integrations from $7,000 / ₹4.4L when the rest of the platform exists. After launch a Standard Care Plan at $2,500 / ₹1,60,000 a month covers gateway changes and reconciliation exceptions. Programme and service pricing is on the pricing page.

Before you start: a checklist

  • Decide whether you need a stored-value wallet now, or only a ledger behind the scenes
  • List the rails per module: UPI intent, collect, Autopay, cards, net banking
  • Choose a primary and a backup gateway, and check webhook and refund API maturity
  • Design the ledger accounts and write the journal entry for each event type
  • Write the refund waterfall for mixed-funding orders
  • Specify pending, lost-callback and late-success behaviour in the app
  • Agree who in finance owns the daily reconciliation report
  • Separate real money from promotional credit in the data model

Questions clients ask

  • Can we start with one gateway? Yes, but build the provider interface from the start so the second one is an adapter, not a rewrite.
  • Do we need a wallet to do cashback? No; promotional credit can live in the ledger without a customer-facing wallet, which avoids stored-value obligations early on.
  • How do we handle a UPI payment that succeeds after we showed a failure? Keep the order in a pending state, let the webhook or status poll resolve it, and notify the user of the outcome.
  • Who should see the reconciliation report? Finance, daily, with engineering on call for the unmatched list.
  • Does this work for a marketplace with seller payouts? Yes; payouts are ledger entries against merchant payable accounts and are covered in our marketplace development guide.

Read super app architecture: shell, modules and shared services for where the payments service sits, payments in mobile apps in India for the client-side integration in React Native, and peak-load engineering for consumer apps for keeping payments up on a festival evening. The NPCI site is the primary source for UPI product specifications.

Build the ledger first, treat the gateway as replaceable, and reconcile every day; everything else in payments is a screen.

Frequently asked questions

Should we build our own wallet or use a gateway's?

▾

Build your own ledger regardless; offer a customer-facing stored-value wallet only when volumes justify the compliance obligations. A closed-loop ledger with promotional credit covers most early needs.

How do we integrate UPI in a React Native app?

▾

Use UPI intent on Android and collect flows as fallback, through a gateway SDK, and let the backend confirm status via webhook. Details in our mobile payments guide.

What does a payments subsystem cost?

▾

Six to ten weeks of a small team; scoped inside super app development from $63,000 / ₹41.6L, or as an integration project from $7,000 / ₹4.4L on an existing platform.