AstraPay

Turning QRIS Into a Top Up Channel

I designed a shareable, closed-amount QRIS Top Up experience with clear fees, one-use QR instructions, and post-payment confirmation. In AstraPay's 2026 YTD channel results through October 21, QRIS ranked #3 by transactions (623,275; 10.61% of all cash-in transactions) and #8 by GTV (Rp147.28 billion; 2.80%). These figures show channel usage, not attributable UI-driven growth.

Role: Product DesignerPaymentsQRISCash-inTransaction StatesInteraction Design
THE SHIPPED PRODUCT

A top-up experience built around one scannable bill.

The interface makes the payable amount explicit, gives the payer a QR they can scan or receive, and confirms success only after the payment resolves.

#32026 YTD transaction rank
10.61%2026 YTD transaction share
01 / DEFINE

Show the total before creating a QR

The user selects Rp50,000 while the interface shows an additional Rp1,000 admin fee, making the payable total Rp51,000.

02 / HAND OFF

Make the payment artifact unambiguous

The QR displays the exact payable amount, recipient, one-use instruction, and payment deadline.

03 / CONFIRM

Separate a completed payment from a displayed QR

The success screen confirms Rp50,000 credited and offers navigation back to Home or transaction details.

TRY THE REAL SCREENS

Follow the interaction from entry to confirmation

Tap the highlighted action on the phone, or choose a screen. The final confirmation is an example of the successful outcome, not a simulated live payment.

Set amount03 / 06
QRIS top up amount and fee selection

Continue after choosing the displayed amount.

Original AstraPay product screens supplied by the designer. The share sheet is native OS UI; payment confirmation is shown as a documented outcome rather than an emulated transaction.

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
From benchmark to delivery

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

The interaction is familiar, but reliability behind a one-use QR isn't automatic. These artifacts explain the early concept and alignment with engineering.

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

The diagram communicates transaction-state rules, not a gallery of implemented exception screens. Only verified original product screens appear in the walkthrough above.

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.
ACTUAL RESULTS · 2026 YTD THROUGH OCT 21

High-frequency top-ups, smaller payment values.

QRIS Top Up ranks third for transaction count across 14 cash-in channels, but eighth for gross transaction value (GTV). The distinction matters: adoption is strong even though the typical payment is smaller than bank-channel top-ups.

#3Transaction rank
10.61%Transaction share
#8GTV rank
2.80%GTV share

Where QRIS stands among cash-in channels

Switch the comparison to see all channels ranked by their share of transactions or payment value. QRIS is highlighted, with actual amounts shown alongside each bar.

01BCA
44.14%2,592,944
02PERMATA
13.02%764,695
03QRIS Top Up
10.61%623,275
04BRI
9.16%538,133
05MANDIRI
6.65%390,607
06SAQU
5.06%296,981
07BNI
4.96%291,097
08CIMB
4.89%287,528

QRIS channel footprint

623,275Transactions
160,487Unique QRIS users
Rp147.28BGTV
Rp236,299Average top-up

All listed channels, 2026 YTD · 5,874,298 transactions · Rp5,265.5B GTV

Source: AstraPay cash-in channel summary supplied by the designer, January 1–October 21, 2026. Unique-user counts are channel-specific and must not be summed across channels. Shares use all 14 listed channels. These are observed adoption figures, not a measured causal impact of this UI.

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.