Short answer
RaftLabs built a mobile point-of-sale and merchant-acquiring platform for a UAE FinTech operator. Merchants take manual card, Tap & Pay on Android, QR code, and payment-link payments from a Flutter app, backed by a merchant dashboard and an admin console. Stripe and, from July 2024, PayBy run behind one transaction ledger. The first App Store release went live in March 2023, about 13 weeks after the first commit, and the platform reached version 1.17 in June 2026.
Engagement
The engagement
- Client
- A UAE FinTech operator (name under NDA)
- Sector
- Payments and merchant acquiring in the United Arab Emirates
- Timeline
- First commit December 2022; first App Store release March 2023; releases continued to v1.17 in June 2026
- Team
- A lead engineer with backend, web, and mobile developers and a project manager; the team shape changed over three and a half years
- Scope
- Flutter POS app, merchant dashboard, admin console, serverless acquiring backend, KYC and e-signature, and two payment processor integrations
- Status
- Handover documentation delivered in March 2026; releases continued after it
The situation
For a small merchant in the UAE, taking a card payment usually meant a hardware terminal and a merchant account. Field sellers, market vendors, and small shops often couldn't justify either, so they stayed on cash.
A UAE FinTech operator wanted merchants to take payments from the phone they already carry. RaftLabs built the app and everything behind it. Merchants take manual card, Tap & Pay, QR code, and payment-link payments from one screen. The first App Store release went live in March 2023, about 13 weeks after the first commit.
The app is the visible part. Underneath sits a merchant-acquiring platform: onboarding, KYC, per-merchant fee rates, verification tiers, refunds, disputes, and two payment processors. That platform kept growing for three more years, to version 1.17 in June 2026.

Before and after
From terminal-or-cash to four ways to pay on one phone
- A card payment meant a hardware terminal and a merchant account many small sellers couldn't justify
- Cash-only sellers kept no digital record of what they sold
- The operator needed onboarding, KYC, fee rates, refunds, and disputes built to payment-industry rules
- Cards, QR codes, and payment links each implied a separate integration
- Merchants take manual card, Tap & Pay on Android, QR code, and payment-link payments from one app
- Every payment, refund, and dispute lands in one ledger, whichever processor handled it
- KYC captures directors and shareholders, collects documents, and closes with an e-signed agreement
- New merchants join through invite codes that carry their per-transaction fee rate
- Merchants add taxes, tips, and notes to a sale and see their full transaction history
The decisions behind the platform
The real product was an acquiring platform with a POS on top
Two things had to be true at once. The merchant experience had to stay simple: open the app, take a payment. The platform underneath had to behave like a regulated acquirer, with onboarding, KYC, fee rates, settlement data, refunds, and disputes.
So the data model came first. Forty-one tables sit around a single payment-intents ledger, and each merchant moves from invite, to KYC, to soft-verified, to fully verified. Soft-verified merchants can trade before full checks clear, but a cumulative cap on received volume blocks any payment that would push them over the limit. Settlement timing for soft-verified accounts is a platform setting.
That lets a new merchant start earning early while the operator limits its exposure. For comparable POS software development, agree these tiers and limits before the first payment screen exists.
Two payment processors, one set of books
The platform launched on Stripe, using Connect for merchant onboarding and payouts, plus payment intents, hosted checkout, and refunds. In July 2024 we added PayBy, a UAE processor, for card and link payments.
Both processors write into the same ledger. Each payment records which processor handled it, and the ledger holds a unique key for each processor's own payment ID. The merchant dashboard, the admin console, refunds, and reporting all read one table, so neither the operator nor the merchant needs to know which rail a payment took.
Card details cross the backend, so the backend carries the PCI weight
Manual card entry inside the app keeps the checkout native. The cost is scope: card details pass through the backend instead of staying inside a processor's hosted fields. We accepted that trade-off and built controls around it.
The backend encrypts card details with the processor's RSA public key before forwarding them. The stored card record keeps only metadata such as brand, last four digits, issuing country, expiry, network, and the 3-D Secure result. There's no column for a full card number. Each merchant has a 3-D Secure threshold, and payments above it step up to verification.
The project team reports that the platform passed a PCI DSS audit in 2025. This page doesn't reproduce the assessment.
Webhooks run through queues so a retry can't double-count
Payment processors resend webhooks, and a burst of callbacks can arrive together. Writing each one straight to the database invites duplicates and lost updates.
Stripe webhooks are signature-verified, then fanned out to one SQS queue per event type. A dedicated consumer function drains each queue and upserts the ledger by the processor's payment ID, so a repeated callback updates the same record. After five failed receives, a message moves to a shared dead-letter queue instead of disappearing. PayBy callbacks run through their own webhook function.
Permissions come from the sign-in token
The platform serves four kinds of user: the operator's super admins, merchant admins, team members who take payments, and anonymous customers paying through a link. Each needs a different slice of the same data.
When someone signs in, an AWS Cognito trigger adds role claims to their token, and Hasura turns those claims into row-level permissions. A cashier sees their merchant's payments. An admin sees the whole base. The rules live in one place instead of being repeated in every API handler.
System flow
How a payment moves through the platform
A simplified view based on the project repositories and handover documentation. It shows the payment path, not every service.
Merchant app
Flutter POS
Takes manual card, Tap & Pay on Android, QR code, and payment-link payments, and offers a retry path when a payment can't complete.
Identity
AWS Cognito
Signs users in and adds role claims to each token, so every later request carries its permissions.
Acquiring backend
AWS Lambda and SQS
Runs merchant onboarding, KYC, e-signature, and processor calls, encrypts card details, and processes webhooks through per-event queues.
Ledger and portals
Hasura, PostgreSQL, and two web apps
Holds the single payment ledger and serves the merchant dashboard and admin console with row-level permissions.
the build
What merchants and the operator work with
The platform has three surfaces: the POS app merchants carry, a merchant web dashboard, and the operator's admin console. All three read from the same ledger.
Four ways to take a payment from one screen
Merchants enter card details, tap a contactless card on an NFC-enabled Android phone, show a QR code, or share a payment link. Each sale can carry taxes, tips, and a note. Tap & Pay runs on Android only; iPhone users take payments by card entry, QR code, or link.

A payment at a stall or a doorstep has a fallback
The same app works at a counter, a market stall, or a delivery handoff. It watches connectivity, and when a payment can't complete, the merchant can retry, re-run 3-D Secure, switch to manual card entry, or send a payment link. The sale doesn't depend on one method working first time.

Onboarding and KYC built for a regulated operator
Merchants join with an invite code that sets their per-transaction fee rate. Onboarding captures directors and shareholders, collects supporting documents, and closes with a Zoho Sign agreement. Merchants trade as soft-verified under a volume cap until full verification clears.

A merchant dashboard and an admin console on one ledger
Merchants manage transactions, refunds, team members, and settings from the web dashboard. The operator's console approves merchants, issues invite codes, reviews platform-wide payments and disputes, and sets global limits such as soft-verified caps. Both portals read the same records, so a merchant's view and the operator's view agree.

Proof
What the platform delivered, and what this page can't claim
Every figure below has a source. Transaction volumes and merchant sales impact haven't been verified for publication, so they aren't shown.
| Result | What changed | Period or context | Evidence and limitation |
|---|---|---|---|
| Speed to market | First App Store release about 13 weeks after the first commit | December 2022 to 7 March 2023 | External: App Store release date. Project-recorded: first commit date |
| Distribution | 10,000+ installs on Google Play | Cumulative, checked September 2026 | External: public store listing; installs aren't active merchants |
| Durability | 67 tagged releases, from v0.0.1 to v1.17 | December 2022 to June 2026 | Project-recorded: release tags in the project repository |
| Payment rails | PayBy added alongside Stripe on one ledger | July 2024 | Project-recorded: integration commits and ledger schema |
| Compliance | PCI DSS audit passed | 2025 | Project team reported; the assessment report isn't reproduced here |
Timeline
How the platform grew
Dec 2022
The build started
The platform repository, first release tag, and core data model came together in the first weeks.
Mar 2023
The POS app reached the App Store
The first public App Store release went live on 7 March 2023, about 13 weeks after the first commit.
Jul-Aug 2024
PayBy and Tap & Pay arrived
PayBy card and link payments joined Stripe on the same ledger, and Android merchants gained contactless Tap & Pay.
2025
The platform went through a PCI DSS audit
The project team reports a passed 2025 PCI DSS audit, with RaftLabs engineers supporting evidence collection.
Mar-Jun 2026
Handover, then more releases
Handover documentation covered infrastructure, deployment, data, security, and APIs in March 2026. Releases continued to v1.17 in June.
The lesson
Put the risk rules in the data model before the first payment screen
The simple-looking parts of this app depend on decisions made in the schema: verification tiers, volume caps, 3-D Secure thresholds, fee rates on invite codes, and a unique key for every processor's payment ID. Each one decides who can take how much money, and whether a retried callback can create a second record.
If you're planning a mobile POS or any product that moves merchant money, agree those rules with your compliance and operations owners first. Adding them after launch means migrating live payment records.
How it runs
- Flutter
- One codebase served Android and iOS merchants. Platform channels exposed NFC for Tap & Pay on Android, while card entry, QR codes, and payment links worked on both.
- Next.js
- The merchant dashboard and the admin console share components and generated GraphQL clients in one Nx monorepo, so a change to the ledger model reaches both portals together.
- Node.js on AWS Lambda
- Merchant, team, processor, and webhook services run as functions behind SQS queues, so bursts of payment callbacks queue up instead of overwhelming the database. AWS CDK defines the infrastructure as code.
- Hasura and PostgreSQL
- PostgreSQL holds the payment ledger with unique keys for each processor's IDs. Hasura turns Cognito role claims into row-level permissions for super admins, merchant admins, team members, and anonymous payers.
- Stripe and PayBy
- Stripe covered onboarding, payouts, checkout, and refunds from launch. PayBy added UAE card and link payments in 2024 through an integration that RSA-encrypts card details, writing into the same ledger.
Common questions
Yes. In this platform, merchants take payments four ways from one app: manual card entry, Tap & Pay on NFC-enabled Android phones, a QR code the customer scans, or a payment link. Tap & Pay runs on Android only, so iPhone users rely on card entry, QR codes, or links. No card reader or terminal is required.
Put one ledger in front of both. Here, Stripe and PayBy payments land in the same payment-intents table, which records which processor handled each payment and keeps a unique key for each processor's own ID. Dashboards, refunds, and reporting read that one table, so merchants and the operator never reconcile two separate sets of records.
It depends on where card details travel. This app keeps card entry native, so details pass through the backend, which encrypts them with the processor's RSA public key before forwarding. Stored records keep only metadata such as brand and last four digits. Payments above a per-merchant threshold step up to 3-D Secure. The project team reports a passed 2025 PCI DSS audit.
Queue them and make every write idempotent. Stripe webhooks are signature-verified and sent to one SQS queue per event type. A consumer function for each queue upserts the ledger by the processor's payment ID, so a repeated callback updates the same row. After five failed attempts, a message moves to a dead-letter queue for review.
Yes, within limits. Merchants start as soft-verified and can trade while full checks continue. The platform adds up each soft-verified merchant's received volume and blocks any payment that would take them past a cap set by the operator, and settlement timing for these accounts is a separate platform setting. Full verification removes the cap.
This platform reached its first App Store release about 13 weeks after the first commit, then kept growing through 67 releases over three and a half years. Scope drives the timeline: payment methods, processors, KYC depth, and compliance work. See our POS software development service, payment integration service, and pricing guide.
Related work


