QR payments for e-commerce: how to build the checkout flow
An online store should show a dynamic QR code per order, carrying the amount and a unique reference, in the EMVCo merchant-presented format that most national systems follow. On desktop the shopper scans it with their phone; on mobile, show a copy code or an app link instead. Give the code a clear expiry with a way to get a new one, confirm the order on the provider's webhook, and follow the underlying rail's rules for refunds.
In 30 seconds
- Use a dynamic code per order with the amount and a reference; a static code makes the shopper type the amount and turns matching into manual work.
- On a phone, a QR code is the wrong control: show a copy-and-paste code or an app link, as Pix Copia e Cola and the Kaspi app redirect do.
- Set an expiry that fits the goods, offer a new code when it lapses, and confirm orders on the provider's webhook rather than on the page.
- 9 sources cited
On this page9 sections
A QR code looks like the simplest payment method to add: show an image, wait for the money. In practice, most of the orders lost on QR methods are lost on details around the image. The shopper is on a phone and cannot scan their own screen. The code expired while they looked for their banking app. The amount was missing and they typed the wrong one. The page said “waiting” long after the bank had paid.
This article explains the mechanics an online store has to get right: static and dynamic codes, the EMVCo format behind most national systems, the desktop and mobile flows, expiry and confirmation, amounts and refunds. The national systems themselves are covered in our article on account-to-account and instant payments, and two of them in depth in our guides to Pix and Kaspi.
What is a QR payment at an online checkout?
It is a payment the shopper starts by scanning a code the merchant shows. EMVCo, which manages the EMV specifications, publishes a QR specification with two modes. In merchant-presented mode, the merchant displays the code and the customer scans it with their phone. In consumer-presented mode, the customer shows a code and the merchant scans it. Online checkouts use the first.
EMVCo describes its specification as a standardised template for generating payment QR codes, one that can carry account-based as well as card-based payments, and several payment options in a single code. Its merchant-presented specification is at version 1.1, published on 27 November 2020. Many national systems build on it. The Central Bank of Brazil’s Pix manual, for example, says the BR Code adopts the EMV standard and covers only the merchant-presented flow.
The money then moves over whatever rail sits behind the code: an instant payment system, a wallet, or a card. EMVCo notes that a specific mobile app is generally needed to process the code, which is why the shopper scans with their banking or wallet app rather than the phone camera alone.
Static or dynamic: which QR code should an online store use?
Dynamic, one per order. Mastercard’s developer documentation for EMVCo merchant-presented codes says the Point of Initiation Method field holds 11 for a static code and 12 for a dynamic one. The difference shows up in matching and amounts.
| Property | Static code | Dynamic code |
|---|---|---|
| Point of Initiation Method | 11 | 12 |
| Reuse | Shown for many payments | Made for one transaction |
| Amount | Optional; if absent, the customer types it | Set for the order |
| Matching to an order | By amount, time or a note the customer adds | By a reference carried in the code |
| Typical use | A printed code at a counter | An online checkout |
The Pix manual shows how far a dynamic code can go. A static Pix code contains all its data in the image, with only five settings: a mandatory key and optional transaction identifier, free text, amount and a field for cash-withdrawal services. A dynamic Pix code contains only basic data about the receiver plus a URL. When the shopper scans it, the payer’s bank calls that URL and fetches the rest from the receiver’s provider: amount, reference and expiry. The manual lists reconciliation by transaction identifier among the dynamic code’s features.
Three fields matter most when you check what your provider generates. Mastercard’s documentation describes them:
- Amount (tag 54). If it is missing, the customer is prompted to type the amount, which invites typos and partial payments.
- Currency (tag 53). A three-digit ISO 4217 code.
- Merchant name (tag 59). The “doing business as” name the wallet shows, so the shopper can recognise who they are paying.
The last field, a checksum (tag 63), is calculated over all the other data and must come at the end. You will rarely build codes by hand, but if a shopper’s app reports an invalid code, a damaged checksum is a common reason to ask your provider about.
How should the flow differ on desktop and mobile?
On desktop, show the code; on mobile, hide it behind a better option. The Pix manual describes the problem plainly: when the shopper browses an online store in a mobile browser or buys inside an app, the phone is the device that reads the code, so it cannot read a code on its own screen. The Central Bank designed Pix Copia e Cola for this case. The checkout offers a way to copy the full string the code represents, exactly what a scanner would read, and the shopper pastes it into the banking app. It works for static, dynamic and composite Pix codes.
Wallet methods often use an app link instead. Antom’s documentation for Kaspi in Kazakhstan describes both flows. On the web, the shopper sees a QR code and scans it in the Kaspi.kz app. In a mobile browser or app, the shopper is sent straight to the Kaspi.kz app to confirm, and is prompted to install it if it is missing.
A practical layout by device:
- Desktop. The QR code first, large, with the amount and merchant name next to it, and the copy code below for shoppers who prefer it.
- Mobile browser. A copy button or an “open app” button first; the QR code collapsed or removed.
- In-app. An app link where the method supports one, otherwise the copy code.
Our article on checkout localisation covers method order by market around this step.
How long should a QR code live, and how do you know it was paid?
As long as the goods allow, with a way to start again. The Pix manual sets a default lifetime of 86,400 seconds, 24 hours, from creation, and gives 3,600 seconds as an example of a shorter value. After that, the receiver’s provider may answer a scan with an HTTP 410 or 404 for an expired or completed charge. Antom’s Kaspi flow times out after 10 minutes. A 24-hour code suits an invoice; a checkout for limited stock or a digital product delivered at once usually wants minutes, a visible countdown and a “new code” button that keeps the basket.
Confirmation is the other half. Stripe’s Pix documentation says the checkout stays open while the customer uses the banking app, and the banking app does not redirect the customer back. The page has to learn the result from the server. Two mechanisms work together:
| Mechanism | What it does | Use it for |
|---|---|---|
| Webhook from the provider | Pushes the final status to your backend | Fulfilment, ledger and stock |
| Polling from the page | Asks your backend for the order status every few seconds | Moving the shopper’s screen to “paid” |
| Status query to the provider | Asks the provider directly | Orders with no webhook after expiry |
Fulfil only on the webhook, and make the handler safe to receive twice; our guide to webhooks and idempotency explains how. Let the page poll your own backend, not the provider, so the shopper’s screen and your ledger read the same record.
How do national QR systems differ?
The format is shared; the rules around it are local. A few short examples:
- Brazil. Pix QR codes follow the BR Code, built on EMVCo merchant-presented mode, with dynamic codes fetched from a URL and Pix Copia e Cola for phones.
- Kazakhstan. Kaspi QR runs inside the Kaspi.kz app. Antom processes it in KZT, from KZT 0.01 to KZT 1,000,000 per payment.
- United Arab Emirates. The Central Bank of the UAE announced Aani on 16 October 2023 as an instant payment platform run by its subsidiary Al Etihad Payments, available 24 hours a day and supporting QR payments at merchants. In October 2025, noon payments announced a pilot with NEOPAY that lets merchants collect Aani payments by mobile number, email or QR code, with customers approving in their banking app or the Aani app.
- Argentina. The central bank’s Transferencias 3.0 programme makes QR payments interoperable: whatever the brand of the code, any wallet can pay it. Payments are irrevocable, the buyer pays no fee, and merchants pay between 6 and 8 per thousand plus VAT.
- Peru. The central reserve bank’s interoperability rules extended to QR payments in their second phase. Perú Retail reported in July 2023 that the deadline for banks, municipal savings banks, finance companies and QR payment providers had moved from 30 June to 13 September 2023, with weekly fines of PEN 24,750 for refusing connections.
How do refunds work after a QR payment?
Through the rail behind the code, so they vary. Stripe accepts Pix refunds within 90 days, full or partial, returned to the bank account that paid. Antom lists full and partial refunds for Kaspi with a 365-day period. Where payments are irrevocable, as the Argentine central bank describes Transferencias 3.0, there is nothing to reverse: the refund is a new transfer to the customer, which needs their account details or a payout route. Our refunds reference compares windows across methods.
Worked example: what does a “new code” button recover?
Example figures, for illustration only.
An online store in Kazakhstan with an average order of KZT 20,000 shows a 10-minute QR code. Each month, 8,000 shoppers open the QR step. 6,000 pay on the first code and 800 let it expire; the rest leave for other reasons. Without a way to start again, the expired 800 must rebuild the basket, and none do. With a “new code” button that keeps the basket, 500 of them request a new code and 450 pay.
| Setup | Paid on first code | Codes expired | Paid on a new code | Orders | Revenue |
|---|---|---|---|---|---|
| No new code | 6,000 | 800 | 0 | 6,000 | KZT 120,000,000 |
| New code, basket kept | 6,000 | 800 | 450 | 6,450 | KZT 129,000,000 |
The button recovers 450 orders and KZT 9,000,000 a month in this example. The split of expired codes is invented; your own logs of codes created, expired and paid will show the real figure.
What are the common mistakes?
- One static code for every order. Matching falls back to amount and time, and two shoppers paying the same price on the same minute become a support case.
- A QR code as the only option on mobile. A shopper cannot scan the screen they are holding. Lead with a copy code or an app link.
- No amount in the code. If the amount field is missing, the shopper types it, and an underpayment or overpayment becomes a manual refund.
- Expiry with no way back. A lapsed code that forces the shopper to rebuild the basket loses the order; offer a new code in place.
- Fulfilling on the page. The banking app does not return the shopper, and the page may close. Ship on the provider’s webhook and poll your own backend for display.
- Late payments after expiry. Some shoppers approve just as a code lapses. Decide in advance whether you fulfil, refund or ask, and make sure the payment still reaches the right order.
How does Omno support QR payments?
Omno can show QR-based methods such as Pix through the providers that offer them in the hosted checkout, with eligibility rules that show each method only to customers in the right country and currency. Routing rules choose the provider, and if a provider is unavailable or rejects the request, the payment moves to the next provider in the rule until one accepts. Merchants with their own checkout can use a Direct Link behind their own button, which splits payments between providers by share or priority. The final status of each payment arrives by webhook, and sessions with no final webhook can be checked through a status query. The hosted checkout page describes the flow.
Key facts
- EMVCo's QR specification defines two modes: merchant-presented, where the customer scans the merchant's code, and consumer-presented, where the merchant scans the customer's (EMVCo).
- In EMVCo merchant-presented codes, the Point of Initiation Method is 11 for a static code and 12 for a dynamic one; without an amount field, the customer types the amount (Mastercard developer docs).
- A dynamic Pix QR code carries a URL that the payer's bank reads at scan time, and a Pix charge expires after 86,400 seconds (24 hours) unless set otherwise (Banco Central do Brasil).
- Pix Copia e Cola exists because a phone cannot scan a QR code on its own screen; the shopper copies the same string a scanner would read (Banco Central do Brasil).
- Antom's Kaspi integration shows a QR code on desktop, opens the Kaspi.kz app on mobile and times out after 10 minutes by default (Antom docs, 2026).
- Transferencias 3.0 QR payments in Argentina work with any wallet, are irrevocable, and cost merchants 6 to 8 per thousand plus VAT (Banco Central de la República Argentina).
Changelog
- First published.
- Updated product details.
Sources
9 references
- EMV QR Codes, EMVCo
- Generate QR Code for Merchants, Mastercard
- Manual de Padrões para Iniciação do Pix, versão 2.10.0, Banco Central do Brasil
- Pix payments, Stripe
- Kaspi, Antom
- Al Etihad Payments launches Aani: an instant payments platform for digital transactions in the UAE, Central Bank of the UAE
- noon payments partners with NEOPAY to introduce AANI Instant Payment for merchants in UAE, noon payments
- Transfers 3.0, Banco Central de la República Argentina
- BCR posterga interoperabilidad entre bancos y microfinancieras hasta septiembre, Perú Retail