AstraPay

Turning QRIS Into a Top Up Channel

QRIS Top Up started from a business request to make top up feel more immediate without always opening a banking app or exchanging account details. After benchmarking competitors and more interoperable QRIS patterns, I used the QR behavior already familiar across Indonesia as a practical bridge for several use cases, from friends funding each other to event admins distributing balance. With engineering, I designed the real-time post-payment states and kept each closed-amount payment tied to one bill so status and reconciliation stayed coherent. By 2026, QRIS Top Up represented 9.3% of AstraPay cash-in and ranked among the top two channels.

Role: Product DesignerPaymentsQRISCash-inTransaction StatesInteraction Design
Context

The brief was simple. Top up should feel more immediate than opening a banking app

The project came from a business request. The CEO repeatedly raised a simple friction point. Funding AstraPay still meant opening a banking app, finding the right route, then following payment details.

I saw a broader opportunity than self top up. The same flow could help when a friend funded your balance, when the payer's bank did not have a convenient AstraPay route, or when an event admin needed to distribute promotional balance.

Competitor benchmarks and more interoperable QRIS patterns pointed to a behavior already familiar across Indonesia. Show a QR, scan, pay. I used that behavior as a practical bridge while a broader QR capability was progressing in parallel.

The problem I was solving was not simply adding another channel. It was making third-party top up possible without exchanging account details.
Design decision

QRIS gave AstraPay and almost any payer a common payment language

I did not invent a new way to pay. QRIS was already widely understood across Indonesia and could bridge different banking and payment apps without tying the experience to one bank partner.

Existing top up

The payer follows a specific channel or account detail

VA, bank transfer, and existing routes still work, but the payer needs to know which route is available and follow that channel's payment details.

Effective for planned cash-in, but it creates more coordination when someone else is paying.
QRIS Top Up

The user generates a QR and the payer scans it

The user sets the amount and displays or shares the QR. The payer only needs an app that supports QRIS to complete the payment.

One familiar interaction pattern can serve several situations without a new navigation model.Try the flow
Interactive prototype

Try the QRIS Top Up flow

Follow the main top-up path, then inspect the expiry and recovery states that sit outside the happy path.

TRY THE FLOW01 / 07
AstraPay QRIS Top Up entry screen
Choose QRISTop Up entryStart from the existing Top Up area and select QRIS as the cash-in method.
From benchmark to delivery

The interaction was recognizable. The payment behavior still had to be designed with engineering

The early concept came from benchmarking QR patterns for interoperable funding. Once the interaction was clear, the next job was making sure the post-payment UI followed the real transaction state.

Start with a QR the payer can use immediately

The user sets the amount and presents the QR. The same QR can work when the payer is nearby or be shared for another situation such as event distribution.

QRIS Top Up concept showing a displayed QR used for cash-in
QRIS familiarity reduced the need to teach a new interaction.
Transaction state model

One closed-amount payment needed to keep one transaction identity

The implementation reused existing top-up infrastructure with dynamic VA and a closed amount. Because reconciliation depends on a clear transaction identity, status checks and recovery needed to return to the same bill before the user was asked to make another payment.

transaction
Create one bill

The amount and QR belong to one transaction identity.

UI
Display or share the QR

The payer scans the QR created for that bill.

pending
Wait for payment state

The interface stays pending while the transaction is unresolved.

resolve
Is the transaction state clear?

Bill status or a callback updates the same transaction.

paid
Success and balance updated

Success appears only after the payment actually resolves.

recovery
Recheck the same bill

A delayed or unclear state is checked again before another payment is attempted.

expired
Close the old bill

An expired QR is not reused. A new bill starts after the previous transaction is fully closed.

Flow connections

  • bill to qr
  • qr to waiting
  • waiting to state
  • state to paid, Paid
  • state to recheck, Not resolved
  • recheck to state
  • state to expired, Expired

This stays at product-state level. Implementation detail that is not needed to explain the design decision is intentionally left out.

Pilot and alignment

We whitelisted the flow for two weeks before wider rollout

Before wider rollout, we whitelisted the flow for roughly two weeks. The focus was not a formal usability study. It was making sure end-to-end payment state, callbacks, settlement, and reconciliation were stable enough for real use.

The pilot led to minor backend adjustments while the frontend interaction did not need meaningful changes. That gave us confidence that the simple user-facing pattern was sufficient and the bigger risk sat in transaction handling underneath.

I aligned the solution with the Head of Payment and Head of Design, then demoed it in an AstraPay session attended by the CEO, CTO, and other leadership before rollout continued.

The two-week pilot validated the payment behavior. The simple frontend was not the part that needed repeated correction.
Outcome

A channel built as a practical bridge became a meaningful part of cash-in

The post-launch evidence I have shows channel adoption. I do not use it as a causal claim about total cash-in growth.

9.3%share of 2026 cash-inQRIS Top Up contribution to AstraPay cash-in in the 2026 readout
Top 2cash-in channelranked among AstraPay's two largest cash-in channels in the same readout
What I took forward

QR made entry easier. Transaction truth determined whether the experience could be trusted.

Benchmarking helped me avoid unnecessary novelty. QRIS was already understood by payers, so the design value came from placing that familiar behavior inside a cash-in use case that previously depended more on channels and account details.

The harder part started after the payer pressed pay. Because the amount was closed and reconciliation depended on one transaction identity, waiting, delayed status, expiry, and retry had to stay consistent with the same bill.

For the next iteration, I would add conversion from amount entry to successful top up, time to resolution, expiry rate, duplicate attempts, and recovery success. Channel share shows adoption, but it does not explain journey quality.

A flow that feels instant on the surface is only safe when post-payment state and reconciliation logic stay disciplined underneath.