How I Built a Real-Time Multiplayer Game with Socket.IO, Firebase & Pakistani Payment Gateways

Published: (June 10, 2026 at 04:03 PM EDT)
5 min read
Source: Dev.to

Source: Dev.to

How I Built a Real-Time Multiplayer Game with Socket.IO, Firebase & Pakistani Payment Gateways

By Faiz Ullah — Full-Stack Developer & Founder of DG Technology When people think of multiplayer games, they imagine big studios and huge teams. But a real-time, money-handling, cheat-proof multiplayer platform can be built by one engineer who understands the architecture deeply. This is the story of Ludo Battle — a real-time multiplayer Ludo tournament platform I built end-to-end, from the WebSocket game engine to the Android APK to the payment integration. I’ll walk through the hard parts, the decisions that mattered, and the lessons that apply to any real-time application — not just games. Build a platform where: 2 to 4 players play live Ludo matches with sub-second synchronization Players deposit and withdraw real money through local payment gateways Nobody can cheat — not the dice, not the moves, not the outcomes It runs on the web and as a native Android app It works on Pakistani mobile networks, where strict NATs and unstable connections are the norm That last constraint shaped a lot of decisions. Building for ideal conditions is easy. Building for real-world 4G in Pakistan is the actual engineering. The single most important principle in any real-money game: the client is a renderer, never a decision-maker. If the browser decides what the dice rolled, a cheater opens DevTools and rolls a six every time. So in Ludo Battle, the server is the source of truth for every piece of game state. The client sends intentions (“I want to roll”, “I want to move this token”), and the server decides what actually happens. Here’s the dice roll — it lives on the server and uses Node’s cryptographically secure random generator, not Math.random(): import { randomInt } from ‘crypto’;

function rollDice() { return randomInt(1, 7); // 1–6, cryptographically secure }

Math.random() is predictable and can be exploited. crypto.randomInt cannot. For real money, this difference matters. Every move is validated the same way: when a player sends game:move, the server computes the legal moves from the current board state and rejects anything illegal before applying it. The client literally cannot make an illegal or impossible move stick. The entire live experience runs over Socket.IO. I designed the events around clear namespaces so the codebase stays readable as it grows: room:create room:join room:leave room:spectate game:roll game:move chat:send chat:msg voice:join voice:signal voice:leave

Rooms map directly to Socket.IO rooms, so broadcasting game state or chat to exactly the right players is a one-liner: io.to(room:${roomId}).emit(‘chat:msg’, message);

This structure means game logic, chat, and voice are cleanly separated but share the same connection — no extra sockets, no wasted overhead. I wanted players to talk during games. The naive approach — routing audio through the server — is expensive and laggy. Instead I used peer-to-peer WebRTC, where the audio flows directly between players and the server only helps them find each other (signaling). The catch: most Pakistani mobile users are behind strict NATs that block direct P2P connections. The fix is a TURN server that relays audio when a direct connection isn’t possible. The app fetches TURN credentials per session and falls back gracefully: Try direct connection (STUN) If blocked → relay through TURN Either way → players can talk This is the difference between voice chat that “works on my machine” and voice chat that works for a farmer on a 4G connection in South Punjab. Handling money means handling risk. I deliberately chose a hosted-redirect payment flow for JazzCash and EasyPaisa so that no card or wallet credentials ever touch my server. The flow: User taps “Deposit” My backend builds a signed payload and returns it The user is redirected to JazzCash/EasyPaisa’s own secure page to approve The gateway sends a callback to my server My server verifies the HMAC signature before crediting a single rupee That HMAC verification step is critical — it’s how the server knows a callback genuinely came from the gateway and wasn’t forged by someone trying to fake a deposit. Skipping it is how platforms get drained. I also built a test mode: when no gateway credentials are configured, deposits credit instantly. This let me build and test the entire economy locally without touching real money or waiting on merchant approval. The frontend is React + TypeScript + Vite. To ship it as a native Android app without rewriting everything, I used Capacitor, which wraps the web build into a real APK that I can distribute directly — no Play Store gatekeeping required. One important real-world gotcha: Android blocks insecure WebSocket connections. The app must talk to an HTTPS backend or the sockets silently fail in the APK. Discovering and solving that kind of platform-specific issue is where real shipping experience comes from. Trust nothing from the client. This one principle prevents an entire category of exploits. Design for the worst network, not the best. Building for Pakistani 4G made the app rock-solid everywhere. Security isn’t a feature you add later — crypto.randomInt, HMAC verification, and server-authoritative logic had to be in the foundation. Separation of concerns scales. Clean event namespaces and layered logic kept a complex real-time system maintainable.

Layer Technology

Frontend React, TypeScript, Vite, Tailwind, Zustand

Backend Node.js, Express, Socket.IO

Auth Firebase Phone OTP + JWT

Payments JazzCash, EasyPaisa (HMAC-verified)

Voice WebRTC + TURN

Mobile Capacitor → Android APK

Ludo Battle taught me that the gap between a “demo” and a “product” is almost entirely in the parts users never see: the anti-cheat, the payment verification, the network resilience. Anyone can render a game board. Making it fair, secure, and reliable on real-world networks is the actual work. If you’re building something real-time, money-handling, or mobile — or you just want to talk architecture — I’d love to connect. Faiz Ullah DG Technology faizullah.pk · 📧 work@faizullah.pk · 💻 github.com/faizullahpk If you found this useful, follow me here and on GitHub — I write about real-world full-stack engineering, building for emerging markets, and shipping products solo.

0 views
Back to Blog

Related posts

Read more »