• Home
  • About
    • Overview
    • Our Experience
    • Join our team
  • What we do
    • Communications & PR
    • Marketing & Advertising
    • Design, branding & printing
    • Events Management
    • Digital Solutions
    • Film & Video Production
    • Professional Photography
  • Our Work
  • Our Blog
  • Contacts
  • Request a Quote
  • Privacy Policy
  • Terms of use
✕
MediaForce is a web development Game-Changer on Clutch
July 8, 2022
How to build an effective branded marketing caravan campaign
August 23, 2022

Integrate MPESA Payment API to your Laravel Website

August 1, 2022
Categories
  • Integrations
Tags

If you are wondering how to accept payments to your Laravel website, you are in the right place. We have shown you how to integrate MPESA into your PHP website. If you are not using any PHP framework, see this article.

In this article, we are going to look at how to integrate MPESA STK Push payment to your Laravel Website. Laravel is an open-source PHP framework, which is robust and easy to understand (read more).  The difference is not that much except that Laravel helps organize our request functions and classes into Models and Controllers.

This article will help laravel PHP developers to implement the MPESA daraja API for Lipa na MPESA STK Push without much hustle.  Therefore, you will need to have prior knowledge about Laravel.

 

Requirements & Installation

Before we get started, ensure you have the following:

  • Safaricom Daraja Account
  • PHP version 7.4 and above
  • Laravel version 7.4 and above
  • cURL extension for PHP installed on your server

 

If your environment meets these requirements, let’s get started!

Firstly,  let us create an MPESA STK Push Model in your Laravel Project named MpesaStkPush.php. Therefore, on your terminal type $ php artisan make:model MpesaStkPush

<?php

namespace App\Repositories;

use Carbon\Carbon;
use function Psy\sh;

class MpesaStkpush
{
    protected $consumer_key;
    protected $consumer_secret;
    protected $passkey;
    protected $amount;
    protected $accountReference;
    protected $phone;
    protected $env;
    protected $short_code;
    protected $parent_short_code;
    protected $initiatorName;
    protected $initiatorPassword ;

    public function __construct(){

        $this->short_code = '7854001';
        $this->parent_short_code='5868111';
        $this->consumer_key=" "; //Your Consumer key
        $this->consumer_secret=" "; //Your Secret key
        $this->passkey = " "; //Your Passkey
        $this->CallBackURL = " "; //Your callback URL
        $this->env = "sandbox"; //Your Environment sandbox or Live
        $this->initiatorName = "testapi"; //Username of your choice
        $this->initiatorPassword = "Safaricom978!"; //Password of your choice

    }

    /** Lipa na M-PESA password **/
    public function getPassword()
    {
        $timestamp = Carbon::now()->format('YmdHms');
        $password  = base64_encode($this->short_code. "" . $this->passkey ."". $timestamp);

        return $password;
    }

    public function lipaNaMpesa($amount,$phone,$accountReference){
        $this->phone = $phone;
        $this->amount=$amount;
        $this->accountReference=$accountReference;

        $Password = getPassword()

        $headers = ['Content-Type:application/json; charset=utf8'];

        $access_token_url = ($this->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"; 
        $initiate_url = ($this->env == "live") ? "https://api.safaricom.co.ke/mpesa/stkpush/v1/processrequest" : "https://sandbox.safaricom.co.ke/mpesa/stkpush/v1/processrequest"; 


        $curl = curl_init($access_token_url);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
        curl_setopt($curl, CURLOPT_HEADER, FALSE);
        curl_setopt($curl, CURLOPT_USERPWD, $this->consumer_key.':'.$this->consumer_secret);
        $result = curl_exec($curl);
        $status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
        $result = json_decode($result);
        $access_token = $result->access_token;
        curl_close($curl);


        # header for stk push
        $stkheader = ['Content-Type:application/json','Authorization:Bearer '.$access_token];
        # initiating the transaction
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $initiate_url);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $stkheader); //setting custom header

        $curl_post_data = array(
            //Fill in the request parameters with valid values
            'BusinessShortCode' => $this->short_code,
            'Password' => $Password,
            'Timestamp' => $Timestamp,
            'TransactionType' => 'CustomerBuyGoodsOnline',
            'Amount' => $this->amount,
            'PartyA' => $phone,
            'PartyB' => $this->parent_short_code,
            'PhoneNumber' => $phone,
            'CallBackURL' => $this->CallBackURL,
            'AccountReference' => $this->accountReference,
            'TransactionDesc' => $phone." has paid ".$this->amount." to ".$this->short_code
        );

        $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);
        $response = curl_exec($curl);

        return $response;
    }

    public function status($transactionCode){
        $type = 4;
        $command = "TransactionStatusQuery";
        $remarks = "Transaction Status Query"; 
        $occasion = "Transaction Status Query";
        $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

        $access_token = ($this->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($this->consumer_key . ':' . $this->consumer_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($this->initiatorPassword, $encrypted, $publicKey, OPENSSL_PKCS1_PADDING); 
        $password = base64_encode($encrypted);

        //echo $token;

        $curl_post_data = array( 
            "Initiator" => $this->initiatorName, 
            "SecurityCredential" => $password, 
            "CommandID" => $command, 
            "TransactionID" => $transactionCode, 
            "PartyA" => $this->short_code, 
            "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); 
        
        return $result;

}

Secondly, we create a controller to manage the MPESA transaction requests. On your terminal type $ php artisan make:controller TransactionController

The controller TransactionController.php, have the following code:

<?php

namespace App\Http\Controllers;

use App\Repositories\MpesaStkpush;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;

class TransactionController extends Controller
{


    //Initiate STK Push
    public function stkPushRequest(Request $request){

        $accountReference='Transaction#'.Str::random(10);

        $amount= $request->amount);
        $phone=$this->formatPhone($request->phone_number);

        $mpesa=new MpesaStkpush();
        $stk=$mpesa->lipaNaMpesa(1,$phone,$accountReference);
        $invalid=json_decode($stk);

        if(@$invalid->errorCode){
            Session::flash('mpesa-error', 'Invalid phone number!');
            Session::flash('alert-class', 'alert-danger');

            return back();
        }

        return redirect('/confirm/'.encrypt($accountReference));
    }

    public function checkTransactionStatus($transactionCode){

        $mpesa=new MpesaStkpush();
        $status=$mpesa->status($transactionCode);

        $tStatus = $status->{'ResponseCode'};

        return $tStatus;
    }

    public function formatPhone($phone)
    {
        $phone = 'hfhsgdgs' . $phone;
        $phone = str_replace('hfhsgdgs0', '', $phone);
        $phone = str_replace('hfhsgdgs', '', $phone);
        $phone = str_replace('+', '', $phone);
        if (strlen($phone) == 9) {
            $phone = '254' . $phone;
        }
        return $phone;
    }

}

 

Thirdly, after setting up the controller, we will set up the routes for making these requests. So let us go to routes/api.php

<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| 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/mfc/stk/push', 'TransactionController@stkPushRequest');

After stk push was initiated, the user is redirected to a confirmation page which should be close to something like this:

When the user clicks “Complete order”,  an MPESA Transaction status query is initiated to check the status of the transaction (To see if the user actually PAID, CANCELED or if there was an ERROR).

run $ php artisan serve on your terminal to start your application if you haven’t. Use Postman service to test your request by using the URL: http://127.0.0.1:8000/api/v1/mfc/stk/push.

Share
49
Anselm Muchura
Anselm Muchura
Software developer and Graphic designer

Related posts

Integrating-Woocommerce-MPESA-payment-to-your Wordpress website
September 24, 2022

How to integrate MPESA stk push in woocommerce WordPress website


Read more
April 20, 2022

Lipa na MPESA STK-PUSH Integration to your PHP Website [UPDATED]


Read more
March 17, 2022

MPESA C2B API Integration to your PHP Website


Read more

1 Comment

  1. Billy says:
    October 9, 2022 at 10:40 AM

    Hi
    on stk push lines 124 and 126 you are using the variable $encrypted. Where has this been defined?

    Billy

    Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

More Blog

  • 0
    Introduction to Email and Web Security – Examples and Best Practices
    January 30, 2023
  • Brand Launch 3 tips to a Successful Brand Launch for all Businesses0
    Brand Launch: 3 tips to a Successful Brand Launch for all Businesses
    November 24, 2022
  • How to make an Impactful Documentary films - A Step By Step Guide0
    How to make Impactful Documentary film – A Step By Step Guide
    November 1, 2022
  • 0
    Netflix announces 46 beneficiaries of its Creative Equity Scholarship Fund in East Africa
    October 11, 2022
  • Integrating-Woocommerce-MPESA-payment-to-your Wordpress website1
    How to integrate MPESA stk push in woocommerce WordPress website
    September 24, 2022
  • 1
    How to Start a Blog and Make Money Online – The Ultimate Beginner’s Guide
    September 6, 2022
  • 0
    How to build an effective branded marketing caravan campaign
    August 23, 2022
  • 1
    Integrate MPESA Payment API to your Laravel Website
    August 1, 2022

Request a Quote

Give us a bit more detail here. Links to examples are very helpful. Feel free to include any questions you might have.

Quick links

  • Who we are
  • What we do
  • Our Work
  • Our Blog
  • Join our team
  • SDGs

Our Services

  • Communications & PR
  • Events Management
  • Design, Branding & Printing
  • Digital Solutions
  • Transformative Storytelling
  • Marketing & Advertising

Stalk us

  • Linkedin page
  • Facebook
  • Twitter
  • Instagram
  • Youtube
  • Medium


Hotline:

+254 777665548

© 2018-2023 MediaForce Communications | All Rights Reserved
  • Privacy Policy
  • Terms of use