Accept M-Pesa on your WordPress membership site using Safaricom's Daraja API. Customers receive a PIN prompt directly on their phone — no manual payment steps required.
Built to the latest Paid Memberships Pro gateway standard and the Daraja v1 API specification.
Customers enter their phone number and approve the payment from an M-Pesa PIN prompt — no app switching or manual "pay to till" instructions.
mpesa_stk_query() checks the Daraja Query API when the async callback hasn't arrived yet, so checkout completes reliably on the second form submit.
Every Safaricom server-to-server call is validated against a site-specific secret UID using hash_equals(), preventing replay attacks.
All database operations use wpdb->prepare(), wpdb->insert(), and wpdb->update(). No raw string interpolation.
Uses wp_remote_get/post() instead of raw cURL — respects WordPress proxy settings and integrates with existing HTTP filter hooks.
Ships with a complete test suite (no extra packages required). Covers phone normalisation, access token, STK push/query, callbacks, and the IPN listener.
Two-click M-Pesa payment — no redirect, no manual steps.
Download the latest release zip from GitHub, upload via WordPress Plugins → Add New → Upload.
Log in to developer.safaricom.co.ke and grab your Consumer Key, Consumer Secret, and Passkey.
Go to Memberships → Payment Settings, select M-Pesa (Daraja), and fill in your credentials.
Copy the Callback URL shown in the settings page and add it to your Daraja app configuration.
| Setting | Where to find it | Required? |
|---|---|---|
| mpesa_short_code | Your Safaricom paybill or till number | Yes |
| mpesa_consumer_key | Daraja developer portal → your app | Yes |
| mpesa_consumer_secret | Daraja developer portal → your app | Yes |
| mpesa_passkey | Daraja → Lipa Na M-Pesa Online passkey | Yes |
| gateway_environment | Set to sandbox for testing, live for production | Yes |
All public functions are available globally after the plugin is loaded.
// Get a Daraja OAuth 2.0 access token
$token = mpesa_get_access_token(); // string|false
// Initiate an STK Push
$result = mpesa_stk_push(
'254712345678', // phone (international format)
1500, // amount (KES)
'ORD-20240101', // account reference (≤12 chars)
'My Site' // description (≤13 chars, optional)
);
// $result->CheckoutRequestID — save this!
// $result->ResponseCode === '0' means push was accepted
// Query status of a pending push
$status = mpesa_stk_query( $result->CheckoutRequestID );
// $status->ResultCode === '0' means payment confirmed
// $status->ResultCode === '1032' means user cancelled