Flexzone
End-to-end fitness center operations platform managing multi-branch memberships, automated Xendit payment billing, and an asynchronous QR scanning kiosk bridge linking mobile phone scanners to front-desk attendance hardware.
V1 Monolithic Production vs. V2 Redesign Concept
The verified, battle-tested production system deployed in commercial facilities is Flexzone V1.0: a high-efficiency PHP 8.x and MySQL monolith with custom session isolation, Xendit webhook billing, and the file-mutexed mobile scanner bridge.
*Note on Architectural Trajectory:* A proposed V2 multi-tier rewrite incorporating Laravel microservices, React frontends, and Java desktop runtimes represents a forward-looking architectural redesign concept, while V1 remains the operational production baseline.
The Front-Desk Bottleneck & Access Contention
Gyms and commercial fitness centers face intense front-desk congestion during morning and evening rush hours. Members queue to check in manually, staff spend valuable time cross-referencing paper logs or expired membership cards, and unverified visitors slip through unnoticed.
Commercial turnstiles with integrated proprietary optical hardware cost thousands of dollars per lane—an impractical capital expenditure for independent gyms and growing branch franchises.
The Asynchronous QR Kiosk Hardware Bridge
To deliver sub-second, contactless check-ins at zero incremental hardware cost, I engineered a cross-device scanner bridge. Any staff smartphone or mounted budget tablet acts as an optical scanning sensor, while the front-desk workstation acts as the authoritative verification terminal:
Cross-Device Optical Scanner & Atomic Mutex Queue
Mobile HTML5 Camera Sensor → flock(LOCK_EX) Serialized Queue → Sub-200ms Front-Desk Terminal Polling → MySQL InnoDB Verification
// Asynchronous mobile scanner bridge writer (api_submit_scan.php)
$token = trim($_POST['member_token'] ?? '');
$queueFile = __DIR__ . '/storage/pending_scans.json';
// Open file with exclusive lock to prevent read/write corruption
$fp = fopen($queueFile, 'c+');
if ($fp && flock($fp, LOCK_EX)) {
$content = stream_get_contents($fp);
$queue = !empty($content) ? json_decode($content, true) : [];
// Push new scan entry with microsecond timestamp
$queue[] = [
'token' => $token,
'timestamp' => microtime(true),
'device' => $_SERVER['REMOTE_ADDR']
];
// Truncate and rewrite atomically
ftruncate($fp, 0);
rewind($fp);
fwrite($fp, json_encode($queue));
fflush($fp);
flock($fp, LOCK_UN);
}
if ($fp) fclose($fp);
The front-desk console polls the atomic scan queue in sub-200ms cycles. Upon detecting a new token, it queries the MySQL membership state engine, flashes the member profile and photo, emits an audible chime, and records the timestamped attendance log.
Deterministic Membership State Engine
Subscriptions transition through a deterministic finite state machine to prevent revenue leakage and expired access:
PENDING_PAYMENT status.ACTIVE, and dispatches dynamic QR pass.EXPIRING), sending email payment links via PHPMailer.EXPIRED, immediately denying entry at the QR kiosk with visual on-screen alerts.