Hello and welcome to this PHP/Laravel tutorial series, my name is Henry Mbugua, I will be taking you through the various aspects, and new answers of M-PESA integration using Laravel web framework and PHP 7.3. Laravel is one of the most popular PHP frameworks and can help you build the application from ground up with expressive, elegant syntax. In lesson 3, we learned how to create mpesa migration, validation method, and confirmation method, in this lesson we are going to continue with our tutorial serious and we are going to learn how we can register our validation and confirmation method with Safaricom M-pesa API.

Creating Register Method

Safaricom M-pesa API provides C2B register URL API which registers the third party’s confirmation and validation URLs to M-pesa, which maps these URLs to the third party Shortcode. Whenever M-pesa receives transactions on the Shortcode, M-pesa triggers a validation request against the Validation URL and the party system responds M-pesa with validation response (either a success or an error code). Depending on the response, M-pesa completes transactions by calling the confirmation URL or cancels the transactions.

The next step is to open our MpesaController.php and make sure it has the following code:

<?php namespace App\Http\Controllers; use App\MpesaTransaction; use Carbon\Carbon; use Illuminate\Http\Request; use Illuminate\Http\Response; use Illuminate\Support\Facades\Storage; class MpesaController extends Controller { /** * Lipa na M-PESA password * */ public function lipaNaMpesaPassword() { $lipa_time = Carbon::rawParse('now')->format('YmdHms'); $passkey = "bfb279f9aa9bdbcf158e97dd71a467cd2e0c893059b10f78e6b72ada1ed2c919"; $BusinessShortCode = 174379; $timestamp =$lipa_time; $lipa_na_mpesa_password = base64_encode($BusinessShortCode.$passkey.$timestamp); return $lipa_na_mpesa_password; } /** * Lipa na M-PESA STK Push method * */ public function customerMpesaSTKPush() { $url = 'https://sandbox.safaricom.co.ke/mpesa/stkpush/v1/processrequest'; $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type:application/json','Authorization:Bearer '.$this->generateAccessToken())); $curl_post_data = [ //Fill in the request parameters with valid values 'BusinessShortCode' => 174379, 'Password' => $this->lipaNaMpesaPassword(), 'Timestamp' => Carbon::rawParse('now')->format('YmdHms'), 'TransactionType' => 'CustomerPayBillOnline', 'Amount' => 5, 'PartyA' => 254728851199, // replace this with your phone number 'PartyB' => 174379, 'PhoneNumber' => 254728851199, // replace this with your phone number 'CallBackURL' => 'https://blog.hlab.tech/', 'AccountReference' => "H-lab tutorial", 'TransactionDesc' => "Testing stk push on sandbox" ]; $data_string = json_encode($curl_post_data); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string); $curl_response = curl_exec($curl); return $curl_response; } public function generateAccessToken() { $consumer_key="sMpgnYW62glBlxPXbyTBEGdPib8eJLOL"; $consumer_secret="IcK2PkAFArVVVffU"; $credentials = base64_encode($consumer_key.":".$consumer_secret); $url = "https://sandbox.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials"; $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_HTTPHEADER, array("Authorization: Basic ".$credentials)); curl_setopt($curl, CURLOPT_HEADER,false); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); $curl_response = curl_exec($curl); $access_token=json_decode($curl_response); return $access_token->access_token; } /** * J-son Response to M-pesa API feedback - Success or Failure */ public function createValidationResponse($result_code, $result_description){ $result=json_encode(["ResultCode"=>$result_code, "ResultDesc"=>$result_description]); $response = new Response(); $response->headers->set("Content-Type","application/json; charset=utf-8"); $response->setContent($result); return $response; } /** * M-pesa Validation Method * Safaricom will only call your validation if you have requested by writing an official letter to them */ public function mpesaValidation(Request $request) { $result_code = "0"; $result_description = "Accepted validation request."; return $this->createValidationResponse($result_code, $result_description); } /** * M-pesa Transaction confirmation method, we save the transaction in our databases */ public function mpesaConfirmation(Request $request) { $content=json_decode($request->getContent()); $mpesa_transaction = new MpesaTransaction(); $mpesa_transaction->TransactionType = $content->TransactionType; $mpesa_transaction->TransID = $content->TransID; $mpesa_transaction->TransTime = $content->TransTime; $mpesa_transaction->TransAmount = $content->TransAmount; $mpesa_transaction->BusinessShortCode = $content->BusinessShortCode; $mpesa_transaction->BillRefNumber = $content->BillRefNumber; $mpesa_transaction->InvoiceNumber = $content->InvoiceNumber; $mpesa_transaction->OrgAccountBalance = $content->OrgAccountBalance; $mpesa_transaction->ThirdPartyTransID = $content->ThirdPartyTransID; $mpesa_transaction->MSISDN = $content->MSISDN; $mpesa_transaction->FirstName = $content->FirstName; $mpesa_transaction->MiddleName = $content->MiddleName; $mpesa_transaction->LastName = $content->LastName; $mpesa_transaction->save(); // Responding to the confirmation request $response = new Response(); $response->headers->set("Content-Type","text/xml; charset=utf-8"); $response->setContent(json_encode(["C2BPaymentConfirmationResult"=>"Success"])); return $response; } /** * M-pesa Register Validation and Confirmation method */ public function mpesaRegisterUrls() { $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, 'https://sandbox.safaricom.co.ke/mpesa/c2b/v1/registerurl'); curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type:application/json','Authorization: Bearer '. $this->generateAccessToken())); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode(array( 'ShortCode' => "600141", 'ResponseType' => 'Completed', 'ConfirmationURL' => "https://blog.hlab.tech/api/v1/hlab/transaction/confirmation", 'ValidationURL' => "https://blog.hlab.tech/api/v1/hlab/validation" ))); $curl_response = curl_exec($curl); echo $curl_response; } }

Let’s understand the code we have added in this file:

Line 152 to 168 – we have created a method called mpesaRegisterUrls () which we will trigger in order for us to call M-pesa to register API.

() which we will trigger in order for us to call M-pesa to register API. Line 154 – we create an initiate curl.

Line 155 – we pass the M-pesa Register API URL. In this case, we are using sandbox register urls.

Line 160 to 165 – we define our post data to Safaricom register API.

Line 161 – we pass our Shortcode.

Line 162 – we define the response type.

Line 163 – we define our confirmation URL.

Line 164 – we define our validation URL.

Line 166 – we define our response from Safaricom response API

Line 167 – we echo the response from Safaricom M-pesa register API

NB: By default, Safaricom does not enable validation URL, you have to write an official letter for them to enable validation on your Shortcode.

The next step is to open our api.php route file and make sure it has the following code:

<?php use Illuminate\Http\Request; /* |-------------------------------------------------------------------------- | API Routes |-------------------------------------------------------------------------- | | Here is where you can register API routes for your application. These | routes are loaded by the RouteServiceProvider within a group which | is assigned the "api" middleware group. Enjoy building your API! | */ Route::middleware('auth:api')->get('/user', function (Request $request) { return $request->user(); }); Route::post('v1/access/token', 'MpesaController@generateAccessToken'); Route::post('v1/hlab/stk/push', 'MpesaController@customerMpesaSTKPush'); Route::post('v1/hlab/validation', 'MpesaController@mpesaValidation'); Route::post('v1/hlab/transaction/confirmation', 'MpesaController@mpesaConfirmation'); Route::post('v1/hlab/register/url', 'MpesaController@mpesaRegisterUrls');

On line 24, we have defined a post URL that goes to our register method. The next step is to test whether our register method works. Ensure that Laravel development server is running by using the following command:

php artisan serve

Once your development server is running, then open postman and hit your register URL to trigger our M-pesa register method. In my case this is my URL:

http://127.0.0.1:8000/api/v1/hlab/register/url

Remember this is a post request. Here is a screenshot of my postman:

postman register urls response

From the screenshot above, we get a response from Safaricom and we are able to register our validation and confirmation URL successfully.

NB: Safaricom allows you to register the URL’s once if you need to change the validation and confirmation URL’s you have to write an official letter.

Goal Achieved in This Lesson

In this lesson, we have achieved the following:

We have learned how to create M-pesa register URL’s method in our applications

We have learned how to trigger register method in our applications

With that, we conclude our lesson, to get the code associated with this lesson visit Laravel Mpesa API Integration.