Brian Omariba
Start a project →
← All systems
Dossier /02 Payment infrastructure Shipped

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.

Category
Payment infrastructure
Role
Integration architecture · Engineering
Stack
PHP · WooCommerce · Daraja API · Webhooks
Status
In production use
01 — Problem

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.

02 — System

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.

01Customer

Enters the phone number that will pay. No codes to copy, nothing to remember.

02Checkout

The order is created and held in a pending state, with the amount locked.

03M-Pesa

A payment request is raised against the merchant short code through the Daraja API.

04STK push

The prompt arrives on the customer’s handset. They authorise with their PIN.

05Callback

The network posts the result back to the store — success, cancellation or timeout.

06Verification

Amount and reference checked against the pending order before anything is trusted.

07Order

State advances automatically, with the transaction reference recorded against it.

08Fulfilment

Downstream processes start immediately, because the trigger is now a system event.

03 — Architecture

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.

04 — Interface

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.

Checkout & order-state screens — to add

Replace with real captures

05 — Outcome

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