A local receiver with a tunnel
By the end of this track you can receive and trust a result.
0/3 finished
Step 1
The idea
Your laptop isn't public, so a tunnel gives it a temporary public HTTPS URL that forwards to a local port.
Step 2
How it works
Why you need a tunnel
Daraja sends callbacks over the internet to a public HTTPS URL. Your laptop sits behind a router with no public address, so Daraja can't reach localhost. A tunnel service gives you a temporary public URL and forwards each request to a port on your machine.
What mpesa dev does
It starts a small receiver on a local port (8787 by default), opens a tunnel to it, prints the public URL and saves it as DARAJA_CALLBACK_BASE_URL. Payments you start from another terminal or your agent use that URL, and each callback shows up in the log as it arrives. If the URL changes, restart your agent so it picks up the new one.
Doing it yourself
Any tunnel works: run your own receiver, start the tunnel, and use the URL it prints as CallBackURL.
# terminal 1: your app on port 8000# terminal 2:cloudflared tunnel --url http://localhost:8000# use the https://….trycloudflare.com URL it prints, plus your callback pathIn production
Tunnels are for the sandbox only. Your server has its own HTTPS domain with a valid certificate, so the tunnel goes away. Keep the callback path the same, so moving from laptop to server only changes the host.
Step 3
Try it
Open two terminals. The first runs the receiver and tunnel and prints the URL; the second sends a payment.
$ mpesa dev $ mpesa pay stk 2547XXXXXXXX 10
Step 4
Read the response
The first terminal logs the callback with the same CheckoutRequestID.
Step 5
Common mistakes
- Forgetting that free tunnel URLs change on every restart, then wondering why callbacks stop. Re-register C2B URLs when they do.
- Leaving a tunnel open to a receiver that has no checks.
Go deeper
What changes when you deploy?
Answer in your own words first.
Show the answerHide the answer
The callback URL becomes your own HTTPS domain.