Conversational commerce on WhatsApp, with live payments, settlement and a hardware fleet. I am the sole engineer, on Kotlin and Spring Boot, and it went from first commit to daily production traffic in under five months.
- Contribution
- Founder-engineer
- Organisation
- Independent build
- Period
- Apr 2026 - Present
- Business verticals in production
- 3
- Payment providers integrated
- 2
- First commit to production traffic
- <5 mo
- Engineer, end to end
- 1
The problem
Several businesses on one engine: food ordering and table booking, event ticketing, prepaid electricity and vehicle paper renewal, all sold and paid for inside WhatsApp, with real money moving every day. The hard part of a system like that is not taking a payment. It is knowing, at every moment, what state the money is in.
What I built
A commerce platform on the Meta Cloud API and WhatsApp Flows, which I build and run as the sole engineer. Food and retail ordering with catalogues synced to Meta, in-chat checkout, loyalty tiers and a tax engine. Event ticketing with pass images and QR check-in at the door on hardware scanners, using signed, audited codes. Prepaid electricity vending and vehicle paper renewal with NIN and BVN identity verification.
Payments run through Rubies and Squad behind one provider interface, with dedicated virtual accounts and instant bank-transfer reconciliation. Settlement is calculated from ledger entries, grouped by day cycle, with audit trails and a capped processing fee, and a payout status checker never marks an unknown payout as failed.
Receipt printers and QR scanners run over MQTT with HTTP fallback, station-based routing and stale-job resweeps. Merchants work in a Next.js dashboard with a 12-step guided onboarding, role-based access that fails closed on both front end and back end, and TOTP challenges for admins.
The stack
- Kotlin
- Spring Boot
- Next.js
- Meta Cloud API
- WhatsApp Flows
- MQTT
- Rubies
- Squad
The hard bug
One word in a webhook
A payment Rubies had confirmed did not register as successful. The cause was a single word: one side of the integration said “SUCCESS” and the other said “Successful”.
I fixed the match, then added HMAC signature verification, so a webhook only changes an order when its signature shows it came from Rubies.
The result
Three verticals in production, built by one engineer from first commit to daily production traffic in under five months. Real money moves through Rubies and Squad every day, every payout can be traced to the ledger entries behind it, and database migrations ship without downtime.
See it

One shared core runs several businesses on WhatsApp, with payments, settlement and hardware as part of the same system.
Customer on WhatsApp
Orders, tickets, electricity and vehicle paper renewals, through the Meta Cloud API and WhatsApp Flows.
Shared core
A Kotlin and Spring Boot backend routes each request to its business workflow, with catalogues synced to Meta, loyalty tiers and a tax engine.
Payments
Rubies and Squad behind one provider interface, with dedicated virtual accounts, instant bank transfer reconciliation and signed webhooks.
Ledger and settlement
Settlement calculated from ledger entries, grouped by day cycle, with audit trails and a capped processing fee.
Fulfilment
Receipt printers and QR door scanners over MQTT with HTTP fallback, station-based routing and stale-job resweeps.
Underneath. A Next.js merchant dashboard with a 12-step guided onboarding, role-based access shared by front end and back end that fails closed, TOTP challenges for admins, and branches that deploy develop to staging and main to production.
Decisions that shaped it
One payment path for every business
Providers plug in behind clean interfaces, so food orders, tickets and vending all share one payment layer.
Settle from the ledger
Payouts are calculated from ledger entries and kept with audit trails, so each one can be traced to the transactions behind it.
Never guess the state of money
An order stays pending until its payment is reconciled, and the payout status checker never marks an unknown payout as failed. An unknown payout stays open until the provider confirms what happened, because one marked failed by mistake could be paid twice.
Fail closed
Access control is shared by the dashboard and the API and denies by default. Queries are scoped to the tenant, every webhook carries an HMAC signature that is verified, vending has amount gates, and secrets never appear in API responses.
Explore a simplified platform model.
Illustrative states · no payment is sent
Food order
Choose a meal and confirm the delivery details.
Verify. Route.
Verify the payment, maintain the transaction state and route the confirmed request to its business workflow.
Ready to fulfil.
Order confirmed. A receipt is routed to the operator.
The merchant needs a usable order, not just a successful payment screen.
Provider integrations, settlement and recovery sit beneath several customer experiences. This diagram illustrates that architecture; it does not contact a payment provider.
Keep exploring
Onboarding Engine