WooPesa
The checkout should never be the bottleneck.
A payment infrastructure layer connecting commerce with M-Pesa — so that paying, confirming and fulfilling are one continuous process instead of three disconnected ones.
- Payment infrastructure
- Integration architecture · Engineering
- PHP · WooCommerce · Daraja API · Webhooks
- In production use
The sale was made. The system just didn’t know it.
In a market where mobile money is the default, an online store can take an order and still be unable to answer the only question that matters: has this been paid?
The gap gets filled manually. Someone reads an SMS, finds the transaction code, matches it to an order by eye, and marks it paid. It works at ten orders a day. At a hundred it becomes the business — slow, error-prone, and impossible to do at night.
Meanwhile the customer is waiting on a confirmation that a human has to produce. That pause is where orders are abandoned.
One uninterrupted path from cart to fulfilment.
The payment is initiated from the checkout itself, and the store is told the outcome by the payment network rather than by a person reading a message. Every stage is a state the order can be queried for.
Enters the phone number that will pay. No codes to copy, nothing to remember.
The order is created and held in a pending state, with the amount locked.
A payment request is raised against the merchant short code through the Daraja API.
The prompt arrives on the customer’s handset. They authorise with their PIN.
The network posts the result back to the store — success, cancellation or timeout.
Amount and reference checked against the pending order before anything is trusted.
State advances automatically, with the transaction reference recorded against it.
Downstream processes start immediately, because the trigger is now a system event.
The interesting part is the failure cases.
The happy path is short. Almost all of the engineering is in what happens when the path is not happy, because a payment integration that only works when everything works is not an integration.
The customer dismisses the prompt. The callback arrives twice. The callback never arrives at all but the money moved. The customer pays a different amount. The connection drops between authorisation and confirmation.
Each of those is a defined state rather than an exception — handled with verification against the pending order, idempotent callback processing so a repeated notification cannot double-fulfil, and reconciliation for the case where the store and the network disagree.
The best version is the one nobody notices.
For the customer, success means the checkout looks like any other checkout and then simply completes. The only new element is the prompt on their own phone, which they already know how to answer.
For the merchant, the surface is the order list — with payment state and transaction reference where they were previously keeping a parallel record in their head.
Replace with real captures
What the system changes.
Payment confirmation stops being a job. The manual verification step is removed rather than made faster, which also removes the class of errors that came with it — mismatched amounts, orders marked paid twice, orders paid but never marked.
Operationally it means the store can take money outside working hours, and the order state is trustworthy enough for other systems to build on top of.
Merchant volumes & conversion data — to be published with permission