Why my website is not showing in google search (How to Fix It)
February 9, 2022Netflix Scholarship in Kenya 2022: Call For Applications!
April 1, 2022In our previous MPESA integration with PHP article (see here), we introduced mpesa C2B integration. We said that Customer-to-Business Integration (C2B) allows businesses to receive payments from their customers directly. Therefore, in this article, we are going to show you mpesa C2B API integration for your PHP Website.
C2B Transaction Process
Firstly, let us understand the mpesa C2B Transaction flow.
When a customer initiates a payment request to your Pay Bill or Buy Goods (Till Number) from their phone, M-PESA receives the request. Secondly, it validates the customer’s PIN, Account Balance, Pay Bill entered, etc. In addition, M-PESA also checks if you have enabled External Validation for the C2B. If External Validation is disabled, M-PESA completes the transaction. After that, it sends a Confirmation notification to the Confirmation URL registered. This only happens when the payment is successful.
If External Validation is enabled:
- M-PESA Holds the Funds tentatively from the customer’s wallet.
- M-PESA then sends a Validation request to the Validation URL registered.
- The partner validates the payment request and responds back to M-PESA.
- M-PESA receives the response, processes, and completes the transaction then a notification of the payment is sent to your registered confirmation URL.
Finally, M-PESA then sends an SMS notification to both the customer and C2B registered phone number. Learn more here
Integration
First, as usual, we will use pure PHP to integrate the C2B API. We hope you have created an account on Safaricom daraja website and have an active sandbox API.
Secondly, obtain an access token that you will be used when calling the Mpesa C2B API. For you to obtain this access_token, you use the consumer key and secret that will be obtained from your developer account.
The next step is to register validation and confirmation URLs(links). Why do we do this? The major reason for integrating Mpesa C2B API with your systems is to allow for communication and the exchange of information between the two systems.
A validation URL is a link where MPESA sends the transaction details to allow you to verify that they are what you intended after your customer initiates an Mpesa transaction using your pay bill number. For example, you might want to validate the amount being paid. Once you have verified, then you can either decline or accept the payment.
A confirmation URL is a link where MPESA sends the details of a completed transaction if you accepted the transaction in the validation stage. At this stage, you might save the data in the database, or perform any other logic for example in e-commerce where you might allow one to access premium products.
Therefore, what does this Mpesa C2B API integration look like in terms of code? Let’s start with vanilla PHP.
First of all, let’s look at the initiating stk push code. We saw this in the previous tutorial but let me just post it here again. Here is what initiateSTK.php looks like:
<?php header("Content-Type:application/json"); /*Call function with these configurations*/ $env="sandbox"; $shortcode = '600988'; $key = ""; //Put your key here $secret = ""; //Put your secret here $initiatorName = "testapi"; $initiatorPassword = "Safaricom978!"; $results_url = "https://mydomain.com/TransactionStatus/result/"; //Endpoint to receive results Body $timeout_url = "https://mydomain.com/TransactionStatus/queue/"; //Endpoint to to go to on timeout /*End configurations*/ /*Ensure transaction code is entered*/ if (!isset($_GET["transactionID"])) { echo "Technical error"; exit(); } /*End transaction code validation*/ $transactionID = $_GET["transactionID"]; //$transactionID = "OEI2AK4Q16"; $command = "TransactionStatusQuery"; $remarks = "Transaction Status Query"; $occasion = "Transaction Status Query"; $callback = null ; $access_token = ($env == "live") ? "https://api.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials" : "https://sandbox.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials"; $credentials = base64_encode($key . ':' . $secret); $ch = curl_init($access_token); curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Basic " . $credentials]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $response = curl_exec($ch); curl_close($ch); $result = json_decode($response); //echo $result->{'access_token'}; $token = isset($result->{'access_token'}) ? $result->{'access_token'} : "N/A"; $publicKey = file_get_contents(__DIR__ . "/mpesa_public_cert.cer"); $isvalid = openssl_public_encrypt($initiatorPassword, $encrypted, $publicKey, OPENSSL_PKCS1_PADDING); $password = base64_encode($encrypted); //echo $token; $curl_post_data = array( "Initiator" => $initiatorName, "SecurityCredential" => $password, "CommandID" => $command, "TransactionID" => $transactionID, "PartyA" => $shortcode, "IdentifierType" => $type, "ResultURL" => $results_url, "QueueTimeOutURL" => $timeout_url, "Remarks" => $remarks, "Occasion" => $occasion, ); $data_string = json_encode($curl_post_data); //echo $data_string; $endpoint = ($env == "live") ? "https://api.safaricom.co.ke/mpesa/transactionstatus/v1/query" : "https://sandbox.safaricom.co.ke/mpesa/transactionstatus/v1/query"; $ch2 = curl_init($endpoint); curl_setopt($ch2, CURLOPT_HTTPHEADER, [ 'Authorization: Bearer '.$token, 'Content-Type: application/json' ]); curl_setopt($ch2, CURLOPT_POST, 1); curl_setopt($ch2, CURLOPT_POSTFIELDS, $data_string); curl_setopt($ch2, CURLOPT_RETURNTRANSFER, 1); $response = curl_exec($ch2); curl_close($ch2); //echo "Authorization: ". $response; $result = json_decode($response); $verified = $result->{'ResponseCode'}; if($verified === "0"){ echo "Transaction verified as TRUE"; }else{ echo "Transaction doesnt exist"; }
The above code initiates the stk push on the user’s phone. However, note that the response on the transaction status (whether the customer PAID, CANCELED, or if there was an ERROR) is sent by Safaricom API to your callback URL. To implement this practice, the callback URL is supposed to receive this response from safaricom. Therefore, you need to set up the code in the callback URL such that it receives the response in form of JSON data and then stores it in your database. If your Callback URL is https://mydomain.com/TransactionStatus/response, response.php should be something like this:
<?php header("Content-Type:application/json"); $content = file_get_contents('php://input'); //Recieves the response from MPESA as a string $res = json_decode($content, false); //Converts the response string to an object $dataToLog = array( date("Y-m-d H:i:s"), //Date and time $res ); //Sets up the log format: Date, time and the response $data = implode(" - ", $dataToLog); $data .= PHP_EOL; //Add an end of line to the transaction log file_put_contents('transaction_log', $data, FILE_APPEND); Appends the response to the log file transaction_log $con = mysqli_connect("localhost","root","","mpesa"); //Connets to the dashboard $sql = "INSERT INTO `responses` (`Response`) VALUES ('$content')"; $rs = mysqli_query($con, $sql); //Record the response to the database if($rs) { echo "Records Inserted"; } ?>
Your database will have the following columns: MerchantRequestID, CheckoutRequestID, ResultCode (0 means successful processing and any other code means an error occurred or the transaction failed.), ResultDesc, MpesaCode, TransactionDate, and PhoneNumber.
1 Comment
Nice one,,i needed a way customers can withdraw funds from the business till or paybill