Last month, a business owner in Nairobi sent me an email. Their team was using Perfex CRM to manage clients, but their local customers wanted to pay with mobile money. Specifically, Safaricom's M-Pesa.
They tried setting up a custom webhook, but payments kept failing. The invoices in the CRM stayed unpaid. As a web developer who has built dozens of these integrations, I knew exactly what was wrong: callback timeouts.
Let me share how we fixed this setup so it works smoothly.
When a customer pays via M-Pesa, the Safaricom system sends a message (a callback) back to your website. If your website takes too long to reply, Safaricom assumes the message was lost. It tries again and again, which can lock up your server.
Most cheap hosting plans have a low timeout limit. If your PHP setup takes more than 5 seconds to process the payment data and update the database, the connection breaks.
Before you install any plugin, you need to make sure your server is ready. If you use Nginx, you should adjust your configuration. I usually add this line to the Nginx server block to give the webhook enough time to process:
fastcgi_read_timeout 60;
This simple tweak keeps the connection open long enough for the payment verification to complete.
Writing a billing API integration from scratch takes a lot of time. You have to handle security keys, transaction IDs, and refund logic. To save time, I didn't write this from scratch. I used the Mpesa Gateway - Perfex CRM module for my client.
I got the module from GPLPAL, and it saved me days of testing API hooks. If you run other systems besides Perfex, you can find similar tools on websites that offer PHP Scripts download packages.
Next, you need to get your keys from the Safaricom Developer Portal. Here is what you need to put into the CRM settings:
Make sure you test this in the "sandbox" mode first. Never use live credentials until you see a successful $1 test transaction go through.
Once everything is saved, run a test. Open your browser's developer console (press F12) and watch the network tab when you trigger a payment. You want to see a clean 200 OK response from the M-Pesa URL.
If you get a 500 Error, check your PHP error logs. Usually, it means your database credentials in Perfex are slightly off, or your firewall is blocking Safaricom's IP addresses.
Using a dedicated module makes the process much simpler. It handles the security handshakes so you do not have to worry about the math behind the digital signatures. If you are setting this up for your own business, just take your time with the server settings and you will have it running in no time.