1. Go to this page and download the library: Download kemboielvis/mpesa-sdk-php library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
kemboielvis / mpesa-sdk-php example snippets
Kemboielvis\MpesaSdkPhp\Mpesa;
// Option A: via constructor
$mpesa = new Mpesa('YOUR_CONSUMER_KEY', 'YOUR_CONSUMER_SECRET', 'sandbox'); // or 'live'
// Option B: via setCredentials (also allows specifying a custom token store file)
$mpesa = (new Mpesa())
->setCredentials('YOUR_CONSUMER_KEY', 'YOUR_CONSUMER_SECRET', 'sandbox', /* optional */ 'mpesa_api_cache.json');
// Optional: choose where to store the token cache file
// If only a filename is provided, it's stored under the system temp directory.
$mpesa->setStoreFile('mpesa_api_cache.json');
// Optional: enable debug logging (prints to PHP error_log)
$mpesa->setDebug(true);
// Example: STK Push
$response = $mpesa->setBusinessCode('YOUR_TILL_OR_SHORTCODE')
->setPassKey('YOUR_LNM_PASSKEY')
->stk()
->setTransactionType('CustomerPayBillOnline') // or 'CustomerBuyGoodsOnline'
->setAmount(100)
->setPhoneNumber('0712345678') // 07..., 7..., +254... and 254... are all accepted
->setCallbackUrl('https://yourdomain.com/callback')
->setAccountReference('INV-12345')
->setTransactionDesc('Payment for invoice INV-12345')
->push()
->getResponse();
print_r($response);
try {
$check = $mpesa->b2cHakikisha()
->setPhoneNumber('0722000000')
->setShortCode('123456') // defaults to setBusinessCode()
->lookup();
if ($check->isFound()) {
echo $check->getCustomerName(); // "john M****** M******"
$check->getCustomer(); // ['firstName' => 'john', 'middleName' => 'M******', 'lastName' => 'M******']
} else {
echo $check->getErrorMessage();
}
} catch (RuntimeException $e) {
// HTTP errors, e.g. "API error (400): The customer does not exist."
}
use Kemboielvis\MpesaSdkPhp\Services\MobileNumberValidationService as Kyc;
$kyc = $mpesa->mobileNumberValidation()
->setShortCode('776700') // defaults to setBusinessCode()
->setPhoneNumber('0710860780')
->setIdType(Kyc::ID_NATIONAL) // ID_NATIONAL (01), ID_MILITARY (02), ID_PASSPORT (05)
->setIdNumber('45435345')
->validate();
$kyc->isMatch(); // true when responseCode is 4000 ("Details match successfully")
$kyc->getResponse(); // responseRefID, responseCode, responseMessage, status
use Kemboielvis\MpesaSdkPhp\Services\MobileDataBundlesService as Bundles;
// 1. Fetch the offers for a customer
$bundles = $mpesa->mobileDataBundles()->fetchOffers('0708374149');
foreach ($bundles->getOffers() as $offer) {
echo $offer->offerName, ' - Ksh ', $offer->offerPrice, PHP_EOL; // "Weekly 2GB - Ksh 99"
}
// 2. Buy one (setOffer() copies offeringId, account, price, data amount and validity)
$purchase = $mpesa->mobileDataBundles()
->setPhoneNumber('0708374149')
->setOffer($bundles->getOffers()[0])
->setPaymentMode(Bundles::PAYMENT_MODE_AIRTIME) // or PAYMENT_MODE_MPESA
// ->setTransactionId('...') // optional; generated if omitted
->purchase();
$purchase->isPurchaseSuccessful();
$transactionId = $purchase->getTransactionId();
// 3. Check the status later (M-Pesa purchases complete asynchronously)
$status = $mpesa->mobileDataBundles()->checkStatus($transactionId)->getResponse();
// responseId, responseDesc, responseStatus ("1000" = success), responseCreated
$pochi = $mpesa->businessToPochi()
->setInitiatorName('testapi') // needs "ORG B2C API initiator" role
->setSecurityCredential('ENCRYPTED_CREDENTIAL') // from the Daraja portal
->setPartyA('600992') // B2C shortcode; defaults to setBusinessCode()
->setPhoneNumber('0705912645') // Pochi wallet number
->setAmount(10) // Ksh 10 - 250,000
->setRemarks('Supplier payment') // 2 - 100 characters
->setOccasion('ChristmasPay') // optional
->setQueueTimeoutUrl('https://yourdomain.com/pochi/timeout')
->setResultUrl('https://yourdomain.com/pochi/result')
// ->setOriginatorConversationId('...') // optional; a UUID is generated if omitted
->pay();
$pochi->getResponse();
$id = $pochi->getOriginatorConversationId(); // store it to match the callback and avoid double payment
$bill = $mpesa->businessPayBill()
->setInitiator('API_Username') // needs "Org Business Pay Bill API initiator" role
->setSecurityCredential('ENCRYPTED_CREDENTIAL') // from the Daraja portal
->setPartyA('123456') // your shortcode; defaults to setBusinessCode()
->setPartyB('000000') // paybill to pay
->setAmount(239)
->setAccountReference('353353') // account number at the paybill, max 13 chars
->setRequester('254700000000') // optional: customer you are paying for
->setRemarks('OK')
->setOccasion('Rent') // optional
->setQueueTimeoutUrl('https://yourdomain.com/b2b/timeout')
->setResultUrl('https://yourdomain.com/b2b/result')
->pay();
$bill->getResponse(); // OriginatorConversationID, ConversationID, ResponseCode, ResponseDescription
$goods = $mpesa->businessBuyGoods()
->setInitiator('API_Username')
->setSecurityCredential('ENCRYPTED_CREDENTIAL')
->setPartyB('000000') // till, store number or merchant HO
->setAmount(239)
->setAccountReference('353353') // max 13 chars
->setRequester('254700000000') // optional
->setQueueTimeoutUrl('https://yourdomain.com/b2b/businessbuygoods/queue')
->setResultUrl('https://yourdomain.com/b2b/businessbuygoods/result')
->pay();
$topUp = $mpesa->b2cAccountTopUp()
->setInitiator('testapi') // needs "Org Business Pay to Bulk API initiator" role
->setSecurityCredential('ENCRYPTED_CREDENTIAL') // from the Daraja portal
->setPartyA('600979') // your shortcode; defaults to setBusinessCode()
->setPartyB('600000') // B2C shortcode to load
->setAmount(239)
->setAccountReference('353353')
->setRequester('254708374149') // optional
->setRemarks('Top up')
->setQueueTimeoutUrl('https://yourdomain.com/topup/timeout')
->setResultUrl('https://yourdomain.com/topup/result')
->topUp();
$topUp->getResponse(); // OriginatorConversationID, ConversationID, ResponseCode, ResponseDescription
// One-time registration (1000 = registered, 1001 = already registered)
$mpesa->pullTransactions()
->setShortCode('600000') // defaults to setBusinessCode()
->setNominatedNumber('0722000000') // number in the shortcode KYC details
->setCallbackUrl('https://yourdomain.com/pull/callback')
->register()
->getResponse();
// Query (1000 = transactions found, 1001 = none in the period)
$pull = $mpesa->pullTransactions()
->setShortCode('600000')
->setStartDate(new DateTime('-2 hours')) // or '2020-08-04 08:36:00'
->setEndDate(new DateTime())
->setOffset(0) // row to start from, for paging
->query();
foreach ($pull->getTransactions() as $trx) {
echo $trx->transactionId, ' ', $trx->amount, ' ', $trx->billreference, PHP_EOL;
}
$tax = $mpesa->taxRemittance()
->setInitiator('TaxPayer')
->setSecurityCredential('ENCRYPTED_CREDENTIAL') // from the Daraja portal
->setPartyA('888880') // your shortcode; defaults to setBusinessCode()
->setAmount(239)
->setAccountReference('PRN1234XN') // payment registration number from KRA
->setRemarks('VAT for March')
->setQueueTimeoutUrl('https://yourdomain.com/b2b/remittax/queue')
->setResultUrl('https://yourdomain.com/b2b/remittax/result')
->remit();
$tax->getResponse(); // OriginatorConversationID, ConversationID, ResponseCode, ResponseDescription
$b2b = $mpesa->b2bExpressCheckout()
->setPrimaryShortCode('000001') // merchant till paying (debit party)
->setReceiverShortCode('000002') // your paybill (defaults to setBusinessCode())
->setAmount(100)
->setPaymentRef('INV-123') // shown to the merchant in the prompt
->setCallbackUrl('https://yourdomain.com/b2b/result')
->setPartnerName('Your Business') // your name as the merchant knows it
// ->setRequestRefId('...') // optional; a UUID is generated if omitted
->push();
$ack = $b2b->getResponse(); // e.g. { "code": "0", "status": "USSD Initiated Successfully" }
$requestId = $b2b->getRequestRefId(); // matches `requestId` in the callback
// Optional: see what points are worth (1 point = Ksh 0.2)
$ksh = $mpesa->lipaNaBonga()->calculatePoints(40)->getCalculatedAmount(); // 8.0
$bonga = $mpesa->lipaNaBonga()
->setPhoneNumber('0720776155')
->setAmount(50) // points are worked out (250) unless you call setPoints()
->setShortCode('888880') // defaults to setBusinessCode()
->setAccountNumber('INV-123')
// ->setConversionRate(0.2) // default
->redeem(); // customer confirms with their M-Pesa PIN
$bonga->isSuccessful();
$bonga->getCustomerMessage();
$age = $mpesa->ageOnNetwork()->check('0722000000');
if ($age->isSuccessful()) {
$age->getRegistrationDate(); // raw value, e.g. "2019-01-12" or a message
$age->getRegistrationDateTime(); // DateTimeImmutable, or null if it is not a date
}
$iot = $mpesa->iotSim()
->setVpnGroup('1-555162310488_VPN') // your IoT account number
->setUsername('[email protected]'); // user registered on the account
// SIM operations
$sims = $iot->getAllSims(0, 20)->getSims(); // start index, page size
$iot->queryLifeCycleStatus('0110100606')->getBody(); // desc, status, statusCode
$info = $iot->queryCustomerInfo('0110100606')->getBody(); // offeringName, offeringId, ...
$iot->activateSim('0110100606');
$iot->renameAsset('0110100606', 'Tracker001');
$iot->suspendSim('0110100606', $info->offeringId);
$iot->resumeSim('0110100606', $info->offeringId);
$iot->getActivationTrends(new DateTime('-30 days'), new DateTime()); // or '20240221', '20240421'
// Messaging
$iot->sendMessage('0110100606', 'Test');
$messages = $iot->searchMessages('0110100606')->getMessages(); // "254" is added for you
$iot->filterMessages('02-05-2024 08:39:11', new DateTime(), '1', 1, 10)->getMessages();
$iot->getAllMessages(1, 10)->getMessages();
$iot->deleteMessage($messages[0]->id);
$iot->deleteMessageThread('0110100606');
$iot->isSuccessful(); // header.responseCode === 200 for the last call
// Option A: an encrypted credential you already have (e.g. from the Daraja portal).
// No certificate needed.
$mpesa->setSecurityCredential('ENCRYPTED_CREDENTIAL'); // for every service
$mpesa->accountBalance()->setSecurityCredential('...'); // or for one service only
// Option B: let the SDK encrypt the plain password with the certificate
// (download the sandbox or production certificate from the Daraja portal).
$mpesa->setCertificate('/path/to/ProductionCertificate.cer'); // path or PEM contents
$mpesa->accountBalance()->accountBalance('initiator', 'INITIATOR_PASSWORD', /* ... */);
$mpesa->setVerifySsl(true); // verify certificates on token and API requests
$mpesa->setVerifySsl(false); // default
bash
cd src/Tests
MPESA_CONSUMER_KEY=... MPESA_CONSUMER_SECRET=... MPESA_PHONE=2547XXXXXXXX \
MPESA_CALLBACK_URL=https://yourdomain.com/callback php tests.php
bash
php src/Tests/token_cache_smoke.php
bash
# Start fake token server in a background shell
php -S 127.0.0.1:8091 src/Tests/fake_mpesa_server.php
# In another shell
php src/Tests/concurrency_test.php
bash
# Start fake token server on a different port
php -S 127.0.0.1:8092 src/Tests/fake_mpesa_server.php
# In another shell
php src/Tests/tamper_concurrency_test.php
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.