Guide, Software Engineering, E-Commerce

M-Pesa Payment Integration: STK Push, Paybill and Till Explained

Most Kenyan customers would rather pay with M-Pesa than type card details into a website. But many business sites still handle it by hand: a Paybill number at checkout, a customer who pastes a confirmation code into a form, and a staff member who checks the statement before releasing the order. Proper M-Pesa payment integration replaces that with a prompt on the customer's phone and an order that updates itself once the payment is confirmed.

This guide explains how it works in plain English, so you can make good decisions and brief a developer with confidence.

What is Daraja?

Daraja is Safaricom's developer platform for M-Pesa. It gives your website APIs that talk to M-Pesa directly, so no one has to read payments off SMS messages. A developer creates an app on the Safaricom Daraja developer portal, gets a consumer key and secret, and uses them to request short-lived access tokens for each API call. Two APIs matter most for business websites:

  • M-Pesa Express (Lipa na M-Pesa Online, or "STK Push"): your website starts the payment and the customer approves it on their phone.
  • Customer to Business (C2B): the customer pays from their own M-Pesa menu, and M-Pesa notifies your system.

Daraja also has a sandbox with test credentials, so the whole flow can be built and tested before real money moves.

How STK Push (Lipa na M-Pesa Online) works

STK Push is what most people mean when they ask for "M-Pesa on my website." The customer enters their phone number, a prompt appears on their phone with the amount and business name already filled in, and they enter their PIN to approve it. There is no paybill number to copy and no account number to mistype.

The flow, step by step

  1. The customer places an order and enters their Safaricom number.
  2. Your server (never the browser) gets an access token and sends an STK Push request with the shortcode, amount, phone number, an account reference such as the order number, and a callback URL.
  3. Daraja replies right away with a request ID. This only means the request was accepted, not that the customer has paid.
  4. The customer enters their PIN, cancels, or ignores the prompt.
  5. M-Pesa sends the result to your callback URL. A successful result includes the receipt number, amount and phone number. A failed one includes a result code, for example for a cancellation or a timeout.
  6. Your server matches the result to the order, checks it, and marks the order as paid or failed.

Meanwhile, the checkout page should show a clear "check your phone" message, poll your own server for the order status, and give the customer a "resend prompt" button.

Paybill vs Till (Buy Goods): which one do you need?

Both work with STK Push and C2B. The difference is how payments are identified.

Paybill

A Paybill takes an account number with each payment. That suits businesses that need to tell payments apart: school fees by admission number, invoices by invoice number, or orders by order ID. For websites, that account field makes reconciliation much easier.

Till (Buy Goods and Services)

A Till has no account number. This suits retail-style sales. Tills still work with STK Push, but your system has to match payments using the request IDs that STK Push gives you. Some Till setups have a separate store number and till number, so confirm with Safaricom which value goes into which field.

Rule of thumb: if you send invoices or collect fees, a Paybill is usually easier to work with. If you already use a Till in-store and sell mainly through checkout, a Till with STK Push works well. Either way, use a shortcode registered to your business, because go-live checks that you own it.

C2B validation and confirmation callbacks

Some customers will always pay through the M-Pesa menu, especially for invoices. C2B lets your system hear about those payments. You register two URLs for your shortcode:

  • Validation URL: M-Pesa asks your system whether to accept a payment before completing it, for example to reject an account number that doesn't exist. External validation is optional, usually has to be enabled on request, and falls back to a default action you set if your server doesn't answer in time.
  • Confirmation URL: after a payment completes, M-Pesa sends the details (receipt, amount, account reference, payer information) so your system can record it.

A good setup uses STK Push at checkout and C2B confirmation as a safety net for manual payments.

From sandbox to production: going live

Safaricom changes the exact steps from time to time, so check the current process on the Daraja portal. In general, it looks like this:

  1. Test thoroughly in the sandbox, including cancelled prompts, timeouts and duplicate callbacks.
  2. Get your shortcode ready: an active Paybill or Till registered to the business, plus access to the M-Pesa business administration account that manages it.
  3. Submit the go-live request on Daraja, which links your production app to the shortcode and requires verification by its administrators.
  4. Store production credentials, including the STK Push passkey, securely on the server.
  5. Switch endpoints and callback URLs to production, register C2B URLs, and run a small real transaction from start to finish.

The paperwork and approvals usually take longer than the code, so start them early.

Reconciliation: matching payments to orders and invoices

Getting money in is only half the job. You also need to know which payment belongs to which order.

  • Keep a payments table separate from orders, recording every request, callback and receipt, including failures.
  • Match on reliable IDs: the checkout request ID for STK Push, and the account reference for Paybill C2B. Don't match on amount alone.
  • Check amounts and decide in advance how to handle underpayments, overpayments and partial invoice payments.
  • Record each receipt number only once, so a repeated callback can't mark two orders as paid.
  • Reconcile against your M-Pesa statement regularly to find payments that never triggered a callback.

Security basics

  • Never trust the browser. A success message in the browser or a code the customer types in proves nothing. Mark orders as paid only after your server gets a valid callback or confirms the result with a status query.
  • Use HTTPS callback URLs on a domain you control, with a valid certificate.
  • Check every callback: the request ID exists, the amount matches, and the order is still unpaid.
  • Keep secrets on the server, in environment configuration, never in front-end code or a public repository.
  • Treat payment logs as personal data under the Kenya Data Protection Act 2019: limit who can see them and how long you keep them.

For the wider picture, see our guide on how to secure your business website.

Common M-Pesa payment integration mistakes

  • Treating "request accepted" as "paid." The first STK Push response only confirms that the prompt was sent.
  • Having no fallback for missing callbacks. Use the STK Push query API to check payments that are still pending.
  • Using the wrong phone number format. Convert 07… and +254… numbers to the 254… format Daraja expects.
  • Sending decimal amounts. M-Pesa works in whole shillings, so round consistently.
  • Ignoring duplicates from double taps or repeated callbacks.
  • Leaving sandbox settings in production, such as old endpoints or callback URLs.
  • Not giving staff an admin view of pending, failed and unmatched payments.

WooCommerce vs custom builds

On WooCommerce, an M-Pesa plugin can add STK Push quickly, which is often the right choice for a small shop. Before using one with real money, check that it confirms payments through callbacks, handles duplicates and timeouts, works with your WooCommerce version, and is actively maintained. Our guide to WooCommerce websites in Kenya covers the wider setup, and our WooCommerce development service can review or harden an existing store.

A custom build makes more sense when M-Pesa payments need to link up with invoicing, school or membership portals, subscriptions, an ERP, or several shortcodes across branches. That gives you full control over reconciliation and reporting. See our API and third-party integration services for those cases.

M-Pesa integration checklist

  1. Choose a Paybill or Till based on how you need to identify payments.
  2. Confirm you have access to the business administration account for that shortcode.
  3. Build and test STK Push in the sandbox, including failure cases.
  4. Register C2B URLs over HTTPS.
  5. Log every request, callback and receipt.
  6. Mark orders as paid only after server-side confirmation.
  7. Complete go-live and test with a real transaction.
  8. Reconcile against your M-Pesa statement regularly.

Frequently asked questions

Can I accept M-Pesa on my website without Daraja?

Yes. You can display your Paybill or Till and confirm payments by hand. That works for low volumes, but it is slow and error-prone. Daraja automates confirmation.

Will my existing Till work, or do I need a Paybill?

Both work with STK Push. A Paybill is easier when you need a reference such as an invoice number. A Till is fine when request IDs are enough to match payments to orders.

What happens if the customer ignores the prompt?

The request times out and M-Pesa sends a failed result to your callback URL. Your checkout should say so clearly and let the customer try again.

Is M-Pesa payment integration secure?

Yes, if it is built correctly: secrets on the server, HTTPS callbacks, and payments confirmed by your server, never by the browser. Most problems come from shortcuts in the implementation.

How long does going live take?

Development can be fairly quick. Approval depends on your shortcode paperwork and administrator access, so start that early.

Getting M-Pesa payments right

A good M-Pesa payment integration feels simple to customers, with one prompt and one PIN, and gives your team a receipt number for every order. The parts customers never see, like callbacks, reconciliation and security checks, are what make it reliable. Explore our M-Pesa payment integration service or book a discovery call to talk through your setup.

Smartphone showing an M-Pesa STK Push payment prompt next to a website checkout page

Table of Contents

Share with your friends
What do you think?

Subscribe to our newsletter

Subscribe to our newsletter and never miss an update. Get the latest news, articles, and exclusive offers straight to your inbox!