TapPay — Offline Digital Payments
Inspiration
Digital payments have become a normal part of everyday life, but most payment systems assume that a stable internet connection is always available.
That creates a problem in situations such as crowded events, college campuses, temporary network outages, low-connectivity areas, or simply when mobile data is unavailable. A person may be physically standing in front of another person with enough money in their wallet, but still be unable to complete a digital payment because the payment server cannot be reached.
We wanted to explore a different approach:
What if a digital payment could be initiated even when there is no internet, and securely settled when connectivity returns?
That idea led us to build TapPay, an offline-first digital payment system.
What is TapPay?
TapPay allows a sender to initiate a payment without requiring an immediate internet connection.
The sender can identify the receiver using NFC, with QR code as a fallback when NFC is unavailable. The transaction is then securely created and stored locally on the device.
Instead of requiring an instant connection to the backend, TapPay marks the transaction as pending synchronization.
When connectivity becomes available again, the application synchronizes the pending transaction with the backend. The backend verifies the transaction before settling it.
The basic flow is:
No Internet → NFC/QR → Local Transaction → Pending Sync → Internet Returns → Verification → Settlement
The Problem
Traditional online payment flows generally depend on communication with a remote server during the payment process.
This becomes difficult when:
- Internet connectivity is unavailable
- Mobile data is temporarily interrupted
- Network coverage is weak
- Large crowds cause connectivity problems
- Users are in low-connectivity environments
- A temporary network outage occurs during a payment
For students, small vendors, event organizers, and users in low-connectivity environments, this can make digital payments unreliable at exactly the moment they are needed.
TapPay addresses this problem by separating payment initiation from online settlement.
How TapPay Solves It
TapPay uses an offline-first architecture.
1. Identify the receiver
The sender can use:
- NFC when available
- QR scanning as a fallback
The receiver's identity is transferred to the sender without requiring an internet request.
2. Create the transaction locally
The sender enters the amount and TapPay creates a local transaction containing information such as:
- Transaction ID
- Sender ID
- Receiver ID
- Device identity
- Amount
- Currency
- Nonce
- Timestamp
- Digital signature
The transaction is stored locally using the Android application's local database.
3. Apply offline controls
TapPay does not treat offline transactions as unlimited payments.
The backend maintains an offline spending limit and tracks offline usage so that the application can restrict how much can be transacted while disconnected.
4. Synchronize later
When connectivity becomes available, the Android application synchronizes pending transactions with the Spring Boot backend.
The backend validates:
- Device identity
- Sender/receiver relationship
- Transaction ID
- Nonce
- Timestamp
- Digital signature
- Offline transaction constraints
- Transaction state
5. Settle the payment
After successful validation, the backend settles the transaction and updates the sender and receiver wallets.
The transaction then becomes available in payment history.
Security and Reliability
Offline payments introduce an important challenge: a transaction cannot simply be trusted because it was created on a phone.
TapPay therefore uses multiple checks during synchronization.
Transaction signatures
Transactions are cryptographically signed before synchronization so the backend can verify that the transaction data has not been modified.
Nonces
Nonces help prevent the same transaction data from being reused improperly.
Device identity
Transactions are associated with registered devices so the backend can verify that the device submitting a transaction belongs to the expected user.
Offline spending limits
Offline payments are constrained by an offline limit rather than allowing unlimited disconnected spending.
Idempotent synchronization
A transaction that is synchronized more than once should not result in multiple wallet deductions.
TapPay checks transaction identity and state before processing it again.
Local persistence
Pending transactions are stored locally instead of being lost when the network is unavailable.
Technology Stack
Android
- Kotlin
- Jetpack Compose
- Room Database
- WorkManager
- Retrofit
- CameraX
- QR code processing
- NFC / Host Card Emulation
Backend
- Java 21
- Spring Boot
- Spring Data JPA / Hibernate
- Spring Security
- JWT authentication
- MySQL
- HikariCP
- REST APIs
Security and transaction layer
- Cryptographic transaction signatures
- Nonce validation
- Device authentication
- Offline spending limits
- Transaction idempotency
- Database transactions and locking
Architecture
TAP PAY
|
+------------+------------+
| |
Android Spring Boot
| |
+------+-------+ +------+-------+
| | | |
NFC QR Authentication Sync API
| | | |
+------+-------+ +------+-------+
| |
Local DB Validation
| |
WorkManager Signature Check
| |
+-----------> Sync ------+
|
Settlement
|
+-----+-----+
| |
Sender Receiver
Wallet Wallet
What We Built
The project consists of two major components.
Android Application
The Android application handles:
Authentication
Device registration
Wallet display
NFC payment
QR fallback
Local transaction storage
Transaction signing
Pending transaction management
Background synchronization
Payment history
Spring Boot Backend
The backend handles:
Authentication
Device management
Wallet management
Offline reservation
Transaction validation
Signature verification
Nonce validation
Synchronization
Settlement
Transaction history
Audit information
Challenges We Faced
The most challenging part was not creating the payment screen itself. It was maintaining consistency between an offline device and the backend.
An online payment can usually be validated immediately. An offline payment cannot.
We therefore had to think about questions such as:
What happens if the same transaction is synchronized twice?
What happens if synchronization fails halfway through?
How should offline spending limits be maintained?
How can the backend verify that a transaction came from the correct device?
How can a transaction be securely verified after being created offline?
What happens when NFC is unavailable?
How can QR act as a practical fallback?
How can wallet updates remain consistent during settlement?
We also encountered transaction-boundary and database connection issues while integrating synchronization with the backend. Solving these problems required understanding how Spring transactions, JPA, wallet locking, and connection pooling interact rather than simply handling errors on the Android side.
What We Learned
Building TapPay taught us that an offline-first payment system is fundamentally different from a normal CRUD application.
The hardest part is maintaining trust and consistency when the server is temporarily unavailable.
We learned about:
Offline-first application architecture
Local persistence with Room
Background synchronization with WorkManager
NFC and QR communication
Cryptographic transaction verification
Idempotent APIs
Database transactions
Pessimistic locking
Wallet consistency
Spring Boot transaction boundaries
Android/backend API integration
Failure handling and synchronization
What Makes TapPay Different?
TapPay is not simply a payment UI with an offline screen.
The core idea is to make offline transaction creation a first-class part of the architecture.
Instead of:
Internet → Payment → Server → Success
TapPay uses:
NFC/QR → Secure Local Transaction → Offline Validation Controls → Synchronization → Server Verification → Settlement
This allows the application to continue functioning when immediate connectivity is unavailable while still requiring the backend to verify and settle the transaction later.
The combination of NFC + QR fallback + local persistence + cryptographic verification + offline limits + automatic synchronization + server-side settlement is the core of the project.
Future Improvements
For a larger production deployment, TapPay could be extended with:
Hardware-backed key storage
Stronger device attestation
More sophisticated fraud detection
Merchant accounts
Multi-currency support
Improved conflict resolution
More extensive security auditing
Secure key rotation
Large-scale distributed settlement infrastructure
Conclusion
TapPay explores how digital payments can remain useful when connectivity cannot be guaranteed.
The goal is not to remove the backend from the payment system, but to move the payment experience into an offline-first model where transactions can be created locally and securely verified and settled when connectivity returns.
TapPay: Pay now. Sync securely when you're back online.
---
`
Built With
- android
- android-studio
- java
- jdbc
- kotlin
- maven
- mysql
- security
- springboot
Log in or sign up for Devpost to join the conversation.