mpesa api integration in laravel 7
Laravel

M-pesa API integration in laravel 7 part 2

M-pesa api integration .MPESA is the most convenient way to send and receive money in kenya. In addition, customers can be able to make business payments, business can make payments to customers or other businesses.

MPESA released their new API(Application Programming Interface)to enable developers to access MPESA services. Such services included in the API are B2B, B2C, C2B, and reversals.

In part 1, we learned how to generate M-PESA access token, so if you have not gone through part 1 please do.In this lesson we are going to continue with our tutorial series and we are going to learn how we can create an STK push.

STK Push Integration to M-PESA on Daraja

Lipa Na M-PESA Online payment API is used to initiate the M-PESA transaction on behalf of a customer using STK push. This is the same technique mySafaricom App uses whenever the app is used to make payments. Have a look at Safaricom App at Google play. Learn more about STK push M-PESA API.

Now that we have a brief overview of what STK push is, we are going to discuss what you need to create a successful M-PESA STK push. The following parameters are required:

  1. Business shortcode – this is the organization’s shortcode to receive a transaction.
  2. Password – password for encrypting request, which is a base64 encoding.
  3. Timestamp – this is the transaction timestamp, which should be in the following format yyyymmddhhiiss.
  4. Transaction type – M-PESA API requires developers to use the CustomerPayBillOnline type for this transaction.
  5. Amount – we need to pass the amount to be transacted.
  6. PartyA – the phone number sending the funds.
  7. PartyB – organization shortcode receiving the funds.
  8. PhoneNumber – the phone number sending the funds.
  9. CallBackURL – the URL response where M-PESA response will be sent.
  10. Account Reference – used with M-PESA paybills.
  11. TransactionDesc – this is the description of the transaction.

Now that we know what Lipa Na M-PESA online payment request parameters are, it is time to code. Since we will be using M-PESA sandbox, let us locate the details that we need from Safaricom Daraja, login to your M-PESA Daraja account and visit the test credentials. You will get the following screenshot:

safaricom test credentials

In our Laravel application, we had created the MpesaController.php file, make sure that app/Http/Controllers/MpesaController.php has the following code:

<?php
namespace App\Http\Controllers;
use Carbon\Carbon;
use Illuminate\Http\Request;
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' => 254706584018, // replace this with your phone number
            'PartyB' => 174379,
            'PhoneNumber' => 254706584018, // replace this with your phone number
            'CallBackURL' => 'https://webtech.co.ke/',
            'AccountReference' => "webtech-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;
    }
}

From our code:

lipaNaMpesaPassword ()-we created a method called lipaNaMpesaPassword () which we use to generate the password required by the M-Pesa STK push parameter.

$lipa_time-we get the current time using Carbon and format the time according to the M-Pesa requirement.we create a variable called passkey and we pass a value given to us by Safaricom in test credentials.

$BusinessShortCode – we create a variable called business shortcode and we pass the value from M-Pesa test credentials.

$timestamp – we just create a variable called timestamp and pass the value we get from $lipa_time.

$lipa_na_mpesa_password – we define a variable called Lipa na mpesa password and we concatenate our business short code, passkey, and timestamp using base64 encode.

return $lipa_na_mpesa_password – we return our generated password and that is how we generate Lipa Na M-Pesa password.

customerMpesaSTKPush()–, we define a method called customerMpesaSTKPush ().

$url – we define a variable called URL and we pass Safaricom STK processing request for the test environment.

$curl – we create a variable called curl and we initialize curl. To learn more about curl visit PHP curl documentation.

$curl_setopt– we define our array where we use authorization keyword Bearer and we pass our access token using the generateAccessToken () method we created in part 1.

$curl_post_data – we define a variable called curl_post_data and pass an array of our STK push parameters that we discussed earlier. This how we pass STK push parameters. Learn more about Lipa Na Mpesa Online Payment.

$data_string – we use json_encode on our request parameters.

$curl_response – we define a variable called curl response and we execute our curl request.

return $curl_response– we return our curl response.

Now that we have our STK push method set up, the next step is to create a URL. Open routes/api.php file and make sure api.php file 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/webtech/stk/push', 'MpesaController@customerMpesaSTKPush');

On the last line,we define our post URL for initiating our STK push. Now we are ready to test our code. Make sure your development server is running by using the following command:

Now run your application and test using postman:

successful stk push

C2B M-PESA INTEGRATION

Next tutorial, we are going to learn how to create C2B M-Pesa integration.

In this lesson we are going to learn how to create M-Pesa migrations and create confirmation and validation method.

M-pesa migration

Laravel comes with a very powerful migration system that behaves like version control for your databases, which allows the development team to easily modify and share the applications database schema. Visit Laravel migrations to learn more about the migrations, in this tutorial we are going to create one table for storing our transactions. In this tutorial series, we are going to create an Eloquent model together with a database migration by running the following command:

php artisan make:model MpesaTransaction -m

The next step is to define our columns in the newly created migration file. Before we can define our column in the created migration, we need to know what Safaricom Mpesa api sends as a confirmation response. Here is a screenshot of Safaricom confirmation response for C2B api:

c2b confirmation response

Now that we know what Safaricom sends as confirmation response, open the mpesa_transaction_table.php file located in database/migrations folder and make sure it has the following code:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateMpesaTransactionsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('mpesa_transactions', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('FirstName')->nullable();
            $table->string('MiddleName')->nullable();
            $table->string('LastName')->nullable();
            $table->string('TransactionType')->nullable();
            $table->string('TransID')->nullable();
            $table->string('TransTime')->nullable();
            $table->string('BusinessShortCode')->nullable();
            $table->string('BillRefNumber')->nullable();
            $table->string('InvoiceNumber')->nullable();
            $table->string('ThirdPartyTransID')->nullable();
            $table->string('MSISDN')->nullable();
            $table->decimal('TransAmount', 8, 2)->nullable();
            $table->decimal('OrgAccountBalance', 8, 2)->nullable();
            $table->softDeletes();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('mpesa_transactions');
    }
}
mpesa transaction table

The next step is to run all our outstanding migrations, running the following command:

php artisan migrate

The next step is to create the validation and confirmation method, we are going to start with the validation method and then confirmation method, open our MpesaController.php file 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://webtech.co.ke/',
            'AccountReference' => "webtech 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;
    }

}

The next step is to create our confirmation and validation urls. Open api.php file, located in routes folder 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/webtech/stk/push', 'MpesaController@customerMpesaSTKPush');
Route::post('v1/webtech/validation', 'MpesaController@mpesaValidation');
Route::post('v1/webtech/transaction/confirmation', 'MpesaController@mpesaConfirmation');

From our code:

  • Line 93 to 99 – we have created a method called createValidationResponse () which takes two parameters namely result_code and result_description. Safaricom expects you to send a json response to either to accept payment or decline the payment.
  • Line 94 – we create a variable called result_code and we use json_encode to convert our object into a json representation.
  • Line 95 –  we create a new instance of the response.
  • Line 96 – we set our header by defining our content to json.
  • Line 97 –  we set our content.
  • Line 98 –  we return our response.
  • Line 107 to 112 – we define our Mpesa validation method. At the moment, this method does nothing useful apart from accepting payment.
  • Line 109 – we define our response code to zero, which tells Safaricom to allow the transaction. If you use any other number the transaction will be rejected.
  • Line 110 – we define our description, in this case, we accept the payment.
  • Line 111 – we call our createValidationResponse () method and pass our validation parameters.
  • Line 118 to 146 – we define our Mpesa confirmation method; this method saves our transactions in our databases.
  • Line 120 – we create a variable called content and we use the json_decode () method which converts json string into a php variable. We also use a request to pass the Safaricom response.
  • Line 122 – we create a variable called mpesa_transaction and create a new instance of our MpesaTransaction model.
  • Line 124 to 135 – we map our database column with the Safaricom response.
  • Line 136 –  we save our transaction in the database.

we have added two new routes. , we have created our validation URL and we have mapped it to our validation method in MpesaController.php file. , we have created our confirmation URL and we have mapped it to our confirmation method in MpesaController.php file

Next part 3

Similar Posts

Leave a Reply

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