Skip to content
← Projects
silvere@ouaga:~/projects/betpay

BetPay

[ LIVE ]

My side project, live in production: a multi-tenant SaaS that automates 1xBet deposits and withdrawals over mobile money for local agents, run on a phone farm that holds their SIMs.

1
PWA, branded per agent
n:1
agent SIMs per farm phone
0
mobile money PINs stored on the server
1%
automatic referral commission
  • Node.js
  • WebSocket (ws)
  • PostgreSQL
  • Kotlin / Android
  • PWA
  • Railway
  • Phone farm
Illustration of a manual deposit over chat: the client sends their 1xBet ID, waits 15 minutes for the agent's number, sends a payment screenshot, chases the agent, and gets credited 48 minutes after asking
Before: a manual deposit over chat (illustration)
The after: the client app in the agent Betyep's colours, with Dépôt and Retrait buttons
After: the client PWA, in the agent's brand

The problem

Funding a 1xBet account from mobile money in Burkina Faso goes through a local agent, over WhatsApp. The client sends their ID, waits for the agent’s number, pays, sends a screenshot as proof, and waits again while the agent checks it by eye and types the credit by hand. The illustration above shows a typical evening deposit: 48 minutes from request to credit.

BetPay turns that agent into a SaaS tenant. The agent signs up, connects their MobCash agent account, and mails in their SIM. Their customers get a web app in the agent’s own colours, and deposits and withdrawals run without anyone typing.

Money moves last

One rule shapes the whole transaction flow: never move the leg I control until the leg I can’t reverse has confirmed.

Deposit. The client enters their 1xBet ID, and the server looks up the account holder’s name so they can check it is the right account before paying. The transaction is recorded as AWAITING_SMS and the client dials the agent’s merchant USSD code. The 1xBet credit through MobCash runs only after the operator’s payment-confirmation SMS reaches the server and matches. If the credit fails after the money arrived, the transaction is marked FAILED and raises an alert. It never fails silently.

Withdrawal. A two-stage wizard. First the server verifies the 1xBet payout code and checks that it belongs to the entered 1xBet ID. That step moves no money and creates no transaction. Only then does the client pick an operator and phone number, and the farm phone dials the payout USSD on the agent’s SIM. The server checks code ownership again at execution, in case a client skips the first step.

The phone farm

Hosted agents ship their SIM, and one farm phone holds several agents’ SIMs. The server attributes every inbound payment SMS and every USSD result to an agent by the SIM’s Android subscription_id. The ICCID would be the obvious key, but non-rooted phones can’t read it.

A farm phone that drops off silently stalls every deposit of every agent on it, so the farm is monitored like production infrastructure:

  • Each phone sends health heartbeats. The super-admin “Parc SIM” page shows devices, SIMs, PIN coverage, and an operations feed.
  • After a grace period offline, the agents and the super admin get an alert, once per outage. On reconnect, the phone resends the payment SMS it received in between and the server reconciles them.
  • Mobile money PINs live encrypted on the phone. The server pushes a PIN and records the acknowledgement, but never stores the PIN itself.

Clients dial USSD on mobile data, which drops their connection mid-transaction. A durable status store replays missed updates when they reconnect with a new connection.

The SaaS around it

  • One PWA for every agent. The agent ID in the URL sets the name, logo, colours (extracted from the agent’s logo), merchant code, and withdrawal address. Branding is data, not a build. The service worker picks up deploys on the next open.
  • Agent portal. Password sign-in with per-agent tokens, onboarding with a free trial, a subscription paid through a mobile money aggregator, a message inbox, and a referral program with an automatic 1% commission.
  • Super-admin controls. Agent approval, pricing, banners, gateway settings stored in the database rather than in env vars, and per-agent switches that pause deposits or withdrawals without suspending the account.
BetPay agent portal sign-in screen
The agent portal

Where it stands

The SaaS runs in production on Railway. The two original agents moved onto it in October 2026, and the Flutter client app it started with is retired in favour of the PWA. The protocol was written down before the code, which is the main reason the same backend has outlived three generations of front end.