├── Tutorial 10 ├── B2CResultURL.php └── b2c.php ├── Tutorial 11 ├── B2BResultURL.php └── b2b.php ├── Tutorial 12 - Balance Query ├── bal_callback_url.php └── bal.php ├── Tutorial 9 ├── callback_url.php └── stk_initiate.php ├── Reversal API ├── reverse_ResultURL.php └── reverse_transaction.php ├── Transaction Status ├── ResultURL.php └── transaction_status_query.php ├── sample_response.txt ├── Turorial 1 └── confirmation_url.php ├── access_token.php ├── Tutorial 2 ├── mobile_payments.sql ├── confirmation_url.php └── config.php ├── validation_url.php ├── LICENSE ├── simulate.php ├── register_url.php └── README.md /Tutorial 10/B2CResultURL.php: -------------------------------------------------------------------------------- 1 | 23 | -------------------------------------------------------------------------------- /access_token.php: -------------------------------------------------------------------------------- 1 | access_token; 20 | 21 | echo $access_token; 22 | 23 | curl_close($curl); 24 | ?> 25 | -------------------------------------------------------------------------------- /Tutorial 2/mobile_payments.sql: -------------------------------------------------------------------------------- 1 | 2 | -- Copy this code to your SQL query box and run. Ensure you have selected the database on config.php 3 | -- Database not optimised for now. 4 | -- Custom fields can also be added 5 | 6 | CREATE table mobile_payments( 7 | transLoID int AUTO_INCREMENT not null, 8 | TransactionType varchar(10) not null, 9 | TransID varchar(10) not null, 10 | TransTime varchar(14) not null, 11 | TransAmount varchar(6) not null, 12 | BusinessShortCode varchar(6) not null, 13 | BillRefNumber varchar(6) not null, 14 | InvoiceNumber varchar(6) not null, 15 | OrgAccountBalance varchar(10) not null, 16 | ThirdPartyTransID varchar(10) not null, 17 | MSISDN varchar(14) not null, 18 | FirstName varchar(10), 19 | MiddleName varchar(10), 20 | LastName varchar(10), 21 | PRIMARY KEY (transLoID), 22 | UNIQUE(TransID) 23 | ) Engine=innoDB; 24 | -------------------------------------------------------------------------------- /validation_url.php: -------------------------------------------------------------------------------- 1 | 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Ben Njunge 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /simulate.php: -------------------------------------------------------------------------------- 1 | $ShortCode, 17 | 'CommandID' => 'CustomerPayBillOnline', 18 | 'Amount' => $amount, 19 | 'Msisdn' => $msisdn, 20 | 'BillRefNumber' => $billRef 21 | ); 22 | 23 | $data_string = json_encode($curl_post_data); 24 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 25 | curl_setopt($curl, CURLOPT_POST, true); 26 | curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string); 27 | $curl_response = curl_exec($curl); 28 | print_r($curl_response); 29 | 30 | echo $curl_response; 31 | ?> 32 | -------------------------------------------------------------------------------- /register_url.php: -------------------------------------------------------------------------------- 1 | $shortCode, 21 | 'ResponseType' => 'Completed', 22 | 'ConfirmationURL' => $confirmationUrl, 23 | 'ValidationURL' => $validationUrl 24 | ); 25 | 26 | $data_string = json_encode($curl_post_data); 27 | 28 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 29 | curl_setopt($curl, CURLOPT_POST, true); 30 | curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string); 31 | 32 | $curl_response = curl_exec($curl); 33 | print_r($curl_response); 34 | 35 | echo $curl_response; 36 | ?> 37 | -------------------------------------------------------------------------------- /Reversal API/reverse_transaction.php: -------------------------------------------------------------------------------- 1 | access_token; 16 | curl_close($curl); 17 | 18 | /* Reversal Request */ 19 | $reversal_url = 'https://sandbox.safaricom.co.ke/mpesa/reversal/v1/request'; 20 | 21 | $curl = curl_init(); 22 | curl_setopt($curl, CURLOPT_URL, $reversal_url); 23 | curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type:application/json','Authorization:Bearer '.$access_token)); //setting custom header 24 | 25 | $curl_post_data = array( 26 | //Fill in the request parameters with valid values 27 | 'Initiator' => '', 28 | 'SecurityCredential' => '', 29 | 'CommandID' => 'TransactionReversal', 30 | 'TransactionID' => '', 31 | 'Amount' => '', 32 | 'ReceiverParty' => '', 33 | 'RecieverIdentifierType' => '', 34 | 'ResultURL' => '', 35 | 'QueueTimeOutURL' => '', 36 | 'Remarks' => 'OUT OF STOCK', 37 | 'Occasion' => '' 38 | ); 39 | 40 | $data_string = json_encode($curl_post_data); 41 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 42 | curl_setopt($curl, CURLOPT_POST, true); 43 | curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string); 44 | $curl_response = curl_exec($curl); 45 | print_r($curl_response); 46 | echo $curl_response; 47 | 48 | ?> 49 | -------------------------------------------------------------------------------- /Tutorial 2/confirmation_url.php: -------------------------------------------------------------------------------- 1 | $jsonMpesaResponse['TransactionType'], 22 | ':TransID' => $jsonMpesaResponse['TransID'], 23 | ':TransTime' => $jsonMpesaResponse['TransTime'], 24 | ':TransAmount' => $jsonMpesaResponse['TransAmount'], 25 | ':BusinessShortCode' => $jsonMpesaResponse['BusinessShortCode'], 26 | ':BillRefNumber' => $jsonMpesaResponse['BillRefNumber'], 27 | ':InvoiceNumber' => $jsonMpesaResponse['InvoiceNumber'], 28 | ':OrgAccountBalance' => $jsonMpesaResponse['OrgAccountBalance'], 29 | ':ThirdPartyTransID' => $jsonMpesaResponse['ThirdPartyTransID'], 30 | ':MSISDN' => $jsonMpesaResponse['MSISDN'], 31 | ':FirstName' => $jsonMpesaResponse['FirstName'], 32 | ':MiddleName' => $jsonMpesaResponse['MiddleName'], 33 | ':LastName' => $jsonMpesaResponse['LastName'] 34 | ); 35 | 36 | // write to file 37 | $log = fopen($logFile, "a"); 38 | fwrite($log, $mpesaResponse); 39 | fclose($log); 40 | 41 | echo $response; 42 | 43 | // this will insert to database. 44 | insert_response($transaction); 45 | ?> 46 | -------------------------------------------------------------------------------- /Transaction Status/transaction_status_query.php: -------------------------------------------------------------------------------- 1 | access_token; 16 | curl_close($curl); 17 | 18 | 19 | /* making the request */ 20 | $tstatus_url = 'https://sandbox.safaricom.co.ke/mpesa/transactionstatus/v1/query'; 21 | 22 | $curl = curl_init(); 23 | curl_setopt($curl, CURLOPT_URL, $tstatus_url); 24 | curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type:application/json','Authorization:Bearer '.$access_token)); //setting custom header 25 | 26 | $curl_post_data = array( 27 | //Fill in the request parameters with valid values 28 | 'Initiator' => '', 29 | 'SecurityCredential' => '', 30 | 'CommandID' => 'TransactionStatusQuery', 31 | 'TransactionID' => '', 32 | 'PartyA' => '', // shortcode 1 33 | 'IdentifierType' => '4', 34 | 'ResultURL' => '', 35 | 'QueueTimeOutURL' => '', 36 | 'Remarks' => '', 37 | 'Occasion' => '' 38 | ); 39 | 40 | $data_string = json_encode($curl_post_data); 41 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 42 | curl_setopt($curl, CURLOPT_POST, true); 43 | curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string); 44 | $curl_response = curl_exec($curl); 45 | print_r($curl_response); 46 | echo $curl_response; 47 | ?> 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MPESA-API-Tutorial 2 | This is a Daraja API MPESA tutorial repo. 3 | Find Video Tutorials https://www.youtube.com/playlist?list=PLcKuwRUZRXZL36Lb3e5eryz8K4mmrqgqs 4 | 5 | 6 | ## NOTE 7 | This is a tutorial version, issues to do with security have not been addresed and may or may not be addressed on this repo, 8 | however, we have the premium version that is bundled and constantly updated and maintained to meet the daily needs that you may 9 | have. Contact us for more details. 10 | 11 | # Ready Made 12 | ## Go Premium? 13 | Daraja Premium Code(DPC) is a library we have developed inhouse, that consumes Daraja API, and more of plug n' play. The code is available for purchase at KES 10,000 and if you need to monitor your transactions live on an android device/iOS Mobile, we have the apps ready integrated with our DPC at an addition of KES 5,000 14 | - This code is suitable for: 15 | - non-coders 16 | - Those who don't want to re-invent the wheel 17 | 18 | ## SurvPay Woocommerce 19 | We also have WordPress Plugin for KopoKopo and Daraja API that works on your WooCommerce Website. The code is priced at a one time fee of KE 5,000. 20 | 21 | ## Support 22 | - We no longer support the FREE Versions of Daraja codes we provide. If you need any support with a non premium code, we recommend checking our YouTube channel under the comments sections as most of the questions have been addressed. 23 | - For premium Code, our team is ready to assist any moment. 24 | 25 | ## Outsource API Services using our MpaaS(Mpesa as a service platform) 26 | - Gives you all the flexibility 27 | - Expert Support 28 | - 100% Uptime and Secure 29 | - 3 minutes. Time it takes to integrate and start using your live shortcode, yeah, we timed it. 30 | - Free 100 Transactions every month 31 | - No contracts. 32 | - Use your own branding and URL 33 | - Access to other services(Africas' Talking SMS platform, WhatsApp API, Airtime & KPLC APIs) 34 | 35 | Checkout more here https://dpc.survtechnologies.co.ke 36 | 37 | ## Why buy DPC? 38 | - No Coding Skills Required 39 | - Security inbuilt 40 | - Clean industry standard code 41 | - FREE Upgrades/Updates & Support 42 | - Monitor on Android/iOS 43 | 44 | Requests/Questions? 45 | Email: billing@survtechnologies.co.ke 46 | Messanger/Facebook Page fb.me/survtechKE/ 47 | -------------------------------------------------------------------------------- /Tutorial 12 - Balance Query/bal.php: -------------------------------------------------------------------------------- 1 | access_token; 17 | curl_close($curl); 18 | 19 | /* main request */ 20 | $bal_url = 'https://sandbox.safaricom.co.ke/mpesa/accountbalance/v1/query'; 21 | 22 | $curl = curl_init(); 23 | curl_setopt($curl, CURLOPT_URL, $bal_url); 24 | curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type:application/json','Authorization:Bearer '.$access_token)); //setting custom header 25 | 26 | $curl_post_data = array( 27 | //Fill in the request parameters with valid values 28 | 'Initiator' => '', # initiator name -> For test, use Initiator name(Shortcode 1) 29 | 'SecurityCredential' => '', #Base64 encoded string of the Security Credential, which is encrypted using M-Pesa public key 30 | 'CommandID' => 'AccountBalance', # Command ID, Possible value AccountBalance 31 | 'PartyA' => '', # ShortCode 1, or your Paybill(During Production) 32 | 'IdentifierType' => '4', 33 | 'Remarks' => '', # Comments- Anything can go here 34 | 'QueueTimeOutURL' => '', # URL where Timeout Response will be sent to 35 | 'ResultURL' => '' # URL where Result Response will be sent to 36 | ); 37 | 38 | $data_string = json_encode($curl_post_data); 39 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 40 | curl_setopt($curl, CURLOPT_POST, true); 41 | curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string); 42 | $curl_response = curl_exec($curl); 43 | print_r($curl_response); 44 | echo $curl_response; 45 | ?> 46 | -------------------------------------------------------------------------------- /Tutorial 10/b2c.php: -------------------------------------------------------------------------------- 1 | access_token; 35 | curl_close($curl); 36 | 37 | /* Main B2C Request to the API */ 38 | $b2cHeader = ['Content-Type:application/json','Authorization:Bearer '.$access_token]; 39 | $curl = curl_init(); 40 | curl_setopt($curl, CURLOPT_URL, $b2c_url); 41 | curl_setopt($curl, CURLOPT_HTTPHEADER, $b2cHeader); //setting custom header 42 | 43 | $curl_post_data = array( 44 | //Fill in the request parameters with valid values 45 | 'InitiatorName' => $InitiatorName, 46 | 'SecurityCredential' => $SecurityCredential, 47 | 'CommandID' => $CommandID, 48 | 'Amount' => $Amount, 49 | 'PartyA' => $PartyA, 50 | 'PartyB' => $PartyB, 51 | 'Remarks' => $Remarks, 52 | 'QueueTimeOutURL' => $QueueTimeOutURL, 53 | 'ResultURL' => $ResultURL, 54 | 'Occasion' => $Occasion 55 | ); 56 | 57 | $data_string = json_encode($curl_post_data); 58 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 59 | curl_setopt($curl, CURLOPT_POST, true); 60 | curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string); 61 | $curl_response = curl_exec($curl); 62 | print_r($curl_response); 63 | echo $curl_response; 64 | ?> 65 | -------------------------------------------------------------------------------- /Tutorial 2/config.php: -------------------------------------------------------------------------------- 1 | getMessage()); 37 | } 38 | 39 | # 1.1.2 Insert Response to Database 40 | try{ 41 | $insert = $con->prepare("INSERT INTO `mobile_payments`(`TransactionType`, `TransID`, `TransTime`, `TransAmount`, `BusinessShortCode`, `BillRefNumber`, `InvoiceNumber`, `OrgAccountBalance`, `ThirdPartyTransID`, `MSISDN`, `FirstName`, `MiddleName`, `LastName`) VALUES (:TransactionType, :TransID, :TransTime, :TransAmount, :BusinessShortCode, :BillRefNumber, :InvoiceNumber, :OrgAccountBalance, :ThirdPartyTransID, :MSISDN, :FirstName, :MiddleName, :LastName)"); 42 | $insert->execute((array)($jsonMpesaResponse)); 43 | 44 | # 1.1.2o Optional - Log the transaction to a .txt or .log file(May Expose your transactions if anyone gets the links, be careful with this. If you don't need it, comment it out or secure it) 45 | $Transaction = fopen('Transaction.txt', 'a'); 46 | fwrite($Transaction, json_encode($jsonMpesaResponse)); 47 | fclose($Transaction); 48 | } 49 | catch(PDOException $e){ 50 | 51 | # 1.1.2b Log the error to a file. Optionally, you can set it to send a text message or an email notification during production. 52 | $errLog = fopen('error.txt', 'a'); 53 | fwrite($errLog, $e->getMessage()); 54 | fclose($errLog); 55 | 56 | # 1.1.2o Optional. Log the failed transaction. Remember, it has only failed to save to your database but M-PESA Transaction itself was successful. 57 | $logFailedTransaction = fopen('failedTransaction.txt', 'a'); 58 | fwrite($logFailedTransaction, json_encode($jsonMpesaResponse)); 59 | fclose($logFailedTransaction); 60 | } 61 | } 62 | ?> 63 | -------------------------------------------------------------------------------- /Tutorial 11/b2b.php: -------------------------------------------------------------------------------- 1 | access_token; 17 | curl_close($curl); 18 | 19 | /* variables from Test Credentials on your developer account */ 20 | $Initiator = ''; # Initiator Name (Shortcode 1) 21 | $SecurityCredential = ''; # SBase64 encoded string of the Security Credential, which is encrypted using M-Pesa public key 22 | $CommandID = ''; # possible values are: BusinessPayBill, MerchantToMerchantTransfer, MerchantTransferFromMerchantToWorking, MerchantServicesMMFAccountTransfer, AgencyFloatAdvance 23 | $SenderIdentifierType = '4'; # Type of organization sending the transaction. 24 | $Amount = ''; 25 | $PartyA = ''; # Shortcode 1 26 | $PartyB = ''; # Shortcode 2 27 | $AccountReference = ''; # Account Reference mandatory for “BusinessPaybill” CommandID. 28 | $Remarks = ''; # Anything Goes here/string/int/varchar 29 | $QueueTimeOutURL = ''; # QueueTimeOutURL 30 | $ResultURL = ''; # ResultURL 31 | $b2bHeader = ['Content-Type:application/json','Authorization:Bearer '.$access_token]; 32 | 33 | /* Main B2B API Call Section */ 34 | $b2b_url = 'https://sandbox.safaricom.co.ke/mpesa/b2b/v1/paymentrequest'; 35 | $curl = curl_init(); 36 | curl_setopt($curl, CURLOPT_URL, $b2b_url); 37 | curl_setopt($curl, CURLOPT_HTTPHEADER, $b2bHeader); //setting custom header 38 | 39 | $curl_post_data = array( 40 | //Fill in the request parameters with valid values 41 | 'Initiator' => $Initiator, 42 | 'SecurityCredential' => $SecurityCredential, 43 | 'CommandID' => $CommandID, 44 | 'SenderIdentifierType' => $SenderIdentifierType, 45 | 'RecieverIdentifierType' => $SenderIdentifierType, 46 | 'Amount' => $Amount, 47 | 'PartyA' => $PartyA, 48 | 'PartyB' => $PartyB, 49 | 'AccountReference' => $AccountReference, 50 | 'Remarks' => $Remarks, 51 | 'QueueTimeOutURL' => $QueueTimeOutURL, 52 | 'ResultURL' => $ResultURL 53 | ); 54 | 55 | $data_string = json_encode($curl_post_data); 56 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 57 | curl_setopt($curl, CURLOPT_POST, true); 58 | curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string); 59 | $curl_response = curl_exec($curl); 60 | print_r($curl_response); 61 | echo $curl_response; 62 | ?> 63 | -------------------------------------------------------------------------------- /Tutorial 9/stk_initiate.php: -------------------------------------------------------------------------------- 1 | 20181004151020 29 | $Timestamp = date('YmdHis'); 30 | 31 | # Get the base64 encoded string -> $password. The passkey is the M-PESA Public Key 32 | $Password = base64_encode($BusinessShortCode.$Passkey.$Timestamp); 33 | 34 | # header for access token 35 | $headers = ['Content-Type:application/json; charset=utf8']; 36 | 37 | # M-PESA endpoint urls 38 | $access_token_url = 'https://sandbox.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials'; 39 | $initiate_url = 'https://sandbox.safaricom.co.ke/mpesa/stkpush/v1/processrequest'; 40 | 41 | # callback url 42 | $CallBackURL = 'http://kidonda.us/projects/MPESA_API/callback_url.php'; 43 | 44 | $curl = curl_init($access_token_url); 45 | curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); 46 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE); 47 | curl_setopt($curl, CURLOPT_HEADER, FALSE); 48 | curl_setopt($curl, CURLOPT_USERPWD, $consumerKey.':'.$consumerSecret); 49 | $result = curl_exec($curl); 50 | $status = curl_getinfo($curl, CURLINFO_HTTP_CODE); 51 | $result = json_decode($result); 52 | $access_token = $result->access_token; 53 | curl_close($curl); 54 | 55 | # header for stk push 56 | $stkheader = ['Content-Type:application/json','Authorization:Bearer '.$access_token]; 57 | 58 | # initiating the transaction 59 | $curl = curl_init(); 60 | curl_setopt($curl, CURLOPT_URL, $initiate_url); 61 | curl_setopt($curl, CURLOPT_HTTPHEADER, $stkheader); //setting custom header 62 | 63 | $curl_post_data = array( 64 | //Fill in the request parameters with valid values 65 | 'BusinessShortCode' => $BusinessShortCode, 66 | 'Password' => $Password, 67 | 'Timestamp' => $Timestamp, 68 | 'TransactionType' => 'CustomerPayBillOnline', 69 | 'Amount' => $Amount, 70 | 'PartyA' => $PartyA, 71 | 'PartyB' => $BusinessShortCode, 72 | 'PhoneNumber' => $PartyA, 73 | 'CallBackURL' => $CallBackURL, 74 | 'AccountReference' => $AccountReference, 75 | 'TransactionDesc' => $TransactionDesc 76 | ); 77 | 78 | $data_string = json_encode($curl_post_data); 79 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 80 | curl_setopt($curl, CURLOPT_POST, true); 81 | curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string); 82 | $curl_response = curl_exec($curl); 83 | print_r($curl_response); 84 | 85 | echo $curl_response; 86 | ?> 87 | --------------------------------------------------------------------------------