# SNAPAY
RFID-based cashless payment system
by Akshit Chaudhary
Snapay is a self-contained RFID cashless payment system built on ESP32. All balance logic runs on the ESP32 using NVS (non-volatile storage). The dashboard is a plain HTML/JS frontend that communicates via MQTT over WebSocket through a HiveMQ cloud broker.
RC522 Reader
│
▼
ESP32 (brain — NVS balance storage, all logic)
│
▼ MQTT over TLS (port 8883)
HiveMQ Cloud Broker
▲
│ MQTT over WSS (port 8884)
Dashboard (browser — display + input only)
| RC522 Pin | ESP32 GPIO |
|---|---|
| SDA | 5 |
| SCK | 18 |
| MOSI | 23 |
| MISO | 19 |
| RST | 22 |
| GND | GND |
| 3.3V | 3.3V |
| LED | ESP32 GPIO |
|---|---|
| Red | 12 |
| Green | 14 |
Always use a 220Ω–330Ω resistor in series with each LED.
| Token | UID | Name | Account |
|---|---|---|---|
| Card | C0:F5:A1:5F | Akshit Chaudhary | VPAY-0001 |
| Tag | 32:73:2E:06 | Aviral Chaudhary | VPAY-0002 |
- Open
firmware/in VS Code with PlatformIO installed - Edit
firmware/src/config.h— fill in your WiFi SSID and password - Flash to ESP32:
pio run --target upload- Open Serial Monitor at 115200 baud to verify connection
No build step needed. Just open dashboard/index.html in any browser.
The dashboard connects to HiveMQ cloud automatically on load.
| Topic | Direction | Payload |
|---|---|---|
rfid/scan |
ESP32 → Dashboard | {name, account, balance} |
payment/success |
ESP32 → Dashboard | {action, name, account, amount, balance} |
payment/failure |
ESP32 → Dashboard | {action, name, account, reason, balance} |
wallet/update |
ESP32 → Dashboard | {name, account, balance} or {from, to} |
system/status |
ESP32 → Dashboard | {status, ip} |
wallet/deposit |
Dashboard → ESP32 | {uid, amount} |
wallet/withdraw |
Dashboard → ESP32 | {uid, amount} |
wallet/transfer |
Dashboard → ESP32 | {amount} |
Tap any card/tag in idle mode → dashboard shows name, account, balance
- Tap card → card activates on dashboard
- Click Deposit → enter amount → Confirm
- Tap card again → balance updates
- Tap card → card activates
- Click Withdraw → enter amount → Confirm
- Tap card → balance deducted (or declined if insufficient)
- Tap any card → card activates
- Click Transfer → enter amount → Confirm
- Tap sender card
- Tap receiver card → transfer executes
| Event | Green LED | Red LED |
|---|---|---|
| Boot | Both blink once | Both blink once |
| Card identified (idle) | 1x blink | — |
| Deposit success | 2x blink | — |
| Withdraw success | 2x blink | — |
| Transfer waiting | Slow pulse | — |
| Transfer success | 3x blink | — |
| Insufficient funds | — | 3x blink |
| Unknown card | — | 5x rapid blink |
HiveMQ Cloud (free tier)
MQTT port: 8883 · WebSocket port: 8884