Payments & M-Pesa
Which tenders settle instantly, how the M-Pesa STK push flow works end to end, configuring credentials, split payments and custom tenders.
The payment methods
| Method | When it settles |
|---|---|
| Cash | Immediately at the till |
| Card | Immediately at the till |
| Visa | Immediately at the till |
| Debit Card | Immediately at the till |
| Credit Note | Immediately at the till |
| M-Pesa | When the customer approves the prompt on their phone |
| Custom tenders | Immediately, into the bucket you mapped them to |
Everything except M-Pesa settles the moment you place the order. Custom tenders settle immediately too, into whichever bucket you mapped them to.
Read this diagram as text
- How is the customer paying? → Cash
- How is the customer paying? → Card, Visa, Debit
- How is the customer paying? → M-Pesa
- Cash → More than one method?
- Card, Visa, Debit → More than one method?
- M-Pesa → More than one method?
- More than one method? → Use split payment lines (yes)
- Use split payment lines → Counts toward its reconciliation bucket at close
- More than one method? → Counts toward its reconciliation bucket at close (no)
- How is the customer paying? → Voucher, wallet, house account? (something else)
- Voucher, wallet, house account? → Counts toward its reconciliation bucket at close
Card tenders are recorded, not processed — Wezo books the sale against the tender you chose while the card terminal handles the money. M-Pesa is different: Wezo actually initiates the request and waits for confirmation.
The M-Pesa flow, step by step
Only Safaricom's authenticated confirmation can settle the order. Nothing the cashier does at the till can mark an M-Pesa sale paid.
Read this diagram as text
- Place the order as M-Pesa → Branch has M-Pesa configured and enabled?
- Branch has M-Pesa configured and enabled? → Order saved, push not started (no)
- Branch has M-Pesa configured and enabled? → STK push sent to the customer's phone (yes)
- STK push sent to the customer's phone → Order sits as pending
- Order sits as pending → Customer approves on the handset?
- Customer approves on the handset? → Declined or timed out (no)
- Declined or timed out → Order sits as pending (retry)
- Customer approves on the handset? → Safaricom confirms to Wezo (yes)
- Safaricom confirms to Wezo → Order marked paid
- Order marked paid → Loyalty points awarded
At the till
Make sure the customer's phone number is captured on the order.
The prompt goes to that number, so a typo means nobody gets a prompt.
Select M-Pesa as the payment method and place the order.
Ask the customer to check their phone and approve.
The order shows as pending until confirmation arrives. Do not hand over goods on the assumption it worked.
Confirm the order shows as paid.
Open the order to see its transactions table with receipt number, amount and status.
Only a verified callback can mark an order paid
Nothing at the till can mark an M-Pesa order paid by itself. The order settles only when Safaricom's authenticated confirmation reaches Wezo — which is what stops an unpaid order from being closed out as paid.
When it does not go through
- The push could not be started: the order is still saved and you are told why on screen. Take another tender or retry.
- The customer cancels or lets it time out: the order stays unpaid. Ask them to try again or pay another way.
- Payment failed: the order's payment status is marked failed and the balance stands. Do not release goods.
Configure M-Pesa for a branch
Organization → Branch → Settings → Payments
Open the branch's settings page and find the Payments section.
Add the M-Pesa provider and enter the credentials from your Safaricom Daraja account.
Save. The provider shows as configured.
Credentials are encrypted before they are stored and are never returned to the browser or written to logs.
Run a test payment against your own phone number.
This proves the credentials, the callback URL and the whole round trip before a customer is standing in front of you.
Credentials are per branch
Each branch holds its own M-Pesa configuration, so a location with its own till number is not forced to share another's. A branch with no configured provider cannot send a push — the till tells the cashier immediately rather than failing quietly.
Split payments
In the cart summary, click Add under Split Payment.
The new line is pre-filled with whatever is still outstanding.
Choose the method and adjust the amount.
Add more lines until Remaining to pay reaches zero.
While a shortfall remains it shows in red and Place Order stays disabled.
Place the order.
Checked in the browser and again on the server: too little is a shortfall, too much is rejected rather than recorded as change.
Read this diagram as text
- Add tender lines → Do the lines cover the total?
- Do the lines cover the total? → Remaining to pay shown in red (no)
- Remaining to pay shown in red → Add tender lines
- Do the lines cover the total? → Do they exceed the total? (yes)
- Do they exceed the total? → Reduce a line (yes)
- Reduce a line → Add tender lines
- Do they exceed the total? → Place Order (no)
The tenders must equal the total
Split payments are checked twice — in the browser and again on the server. Too little is rejected as not covering the total; too much is rejected outright rather than being recorded as an overpayment.
Custom tenders
Dashboard → Settings → Custom payment tenders
A custom tender is any manual way you accept money that is not in the built-in list — a gift voucher, a staff account, another mobile wallet. Each one is mapped to a reconciliation bucket so end-of-day counting still balances.
Open Dashboard → Settings and find Custom payment tenders.
Enter a tender name such as Voucher or Airtel Money.
Map it to a reconciliation bucket: cash, card, M-Pesa or other.
That is the column its takings land in at reconciliation time.
Enable it.
Only enabled tenders appear in the POS payment list. Disable one to retire it without losing history.
Payment safety rules
- Totals are recomputed on the server from the catalog; a terminal cannot dictate what is charged.
- Provider credentials are encrypted at rest and never sent to the browser.
- Only an authenticated provider callback can settle an M-Pesa order.
- Refunds require a paid order, the right permission, and are recorded in the audit log.
- Payment references and receipt numbers are stored per transaction, so any figure can be traced back to a specific payment.