KRISPAY
Cashless payments for self-service laundry machines
Fullstack Engineer | 2022 to present | Laravel, PHP, IoT integration, MySQL
Cashless payments for self-service laundry machines, running in 80+ locations.
Self-service laundry branches ran on coins and prepaid cards that customers had to top up. Owners could not see how much they earned until someone drove out to collect the cash, and a lost coin was money gone with no way to trace it.
The machines sit in branches on cheap home internet. A payment that fails halfway is worse than no payment at all: the customer has been charged, the machine stays dead, and nobody is on site to fix it.
Writing our own firmware and machine control for 80+ locations would have taken more time than our small team had. So I picked a ready made smart switch platform to control the machines instead of building all the IoT parts myself. I put its API behind our own service, with a retry queue for when the platform stops answering, so a problem on their side does not show up as a broken app on ours. The trade off: I am stuck with their rate limits and their downtime, and I cannot fix either. Getting to 80+ locations fast mattered more than owning the hardware layer, so I took that trade off.
A QRIS payment can go through on the payment provider's side while the confirmation never reaches our server, because the branch connection dropped or timed out. So I gave every transaction a unique key the server can recognize on repeat. Instead of trusting one message to always land, the server asks the provider directly for the status when no confirmation arrives in time. The trade off: the server holds unfinished payments longer and runs a regular job to match them up. I took that, because charging someone while the machine stays dead is the most expensive way to fail. It costs trust, not just money.
Branch owners had no idea which machine was free, broken, or running until someone sent a manual report. So instead of only recording finished payments, I gave every machine a live status (idle, running, error) sent to one shared dashboard. The trade off: each machine checks in on a schedule, which adds a small amount of constant traffic. I took that, because seeing machine status, not just money coming in, is what turns a laundry from equipment into a business you can run from anywhere.
- -~2,000 transactions a day across 80+ locations
- -Owners see their earnings live, replacing manual cash pickups
- -A franchise model grew on top of this system, adding locations every month
- -Helped grow the self-service laundry market in Yogyakarta over the past three years
Leaning on someone else's IoT platform was the right call for speed, but it is now the limit on what this system can do. KRISPAY runs on Laravel and is old code today. I am building its replacement on NestJS with our own device firmware, so neither the server nor the machines depend on an outside company's plans.