Mpesa B2C(Business to Customer) API

Mpesa B2C API is a gateway for disbursing funds to customers through Mpesa Bulk Payment account.

The Safaricom Business to Client API is useful when you want to make payments to Mpesa users from your company’s Mpesa account.

Using the Mpesa Portal for the payments is rather cumbersome and furthermore, you can automate the process of making payments to customers depending on your business logic.

In this guide, we will focus on setting up Mpesa B2C API using PHP.

Prerequisites

  1. An account from Mpesa developer portal
  2. An active bulk payment account from Mpesa(application is free, but you will require your business certificate, PIN of directors, a single leaf of cancelled cheque book and a photo or utility bill to prove existence of your business.)
  3. A domain name (e.g. www.example.com). This will help you create call back URL to notify your system when your transaction is finalized on the Mpesa side.
  4. A hosting plan (Bluehost is recommended)
  5. Knowledge of MySQL database
  6. Knowledge of PHP scripting Language

Step 1: Signing up with Mpesa Developer Portal

First, create an account at Mpesa Developer Portal If you don’t have an account. You will be required to supply your names, email address, Mobile number and other details.

Step 2: Create a B2C App(Business to Customer/Client)

Once your account is ready, sign in on the developer portal and create a B2C API. To do this, click on My APPs at the top Menu. Then click Add a new APP

On the next screen, enter the name of your app and check the box written “MPesa Sandbox For MPesa Sanbox B2B, B2C And C2B APIs”.

Your Mpesa B2C app will be created and approved within seconds and you will get a consumer secret and a consumer key.

Step 3: Making Payments to a Customer

Once you have the consumer key and consumer secret, you can start making requests to the Mpesa B2C end point using the PHP code below:

<?php

$shortcode="YOUR_SHORT_CODE_HERE";
$initiatorname="USER_NAME_FROM_MPESA_PORTAL_HERE";
$initiatorpassword="YOUR_PASSWORD_HERE";


$consumerkey    ="YOUR_CONSUMER_SECRET_HERE";
$consumersecret ="YOUR_CONSUMER_SECRET_HERE";


$commandid='BusinessPayment';
$recipient="25472XXXXXXX";
$amount="100";
$remarks='TEST BUSINESS DISBURSAL';
$occassion='JANUARY 2019';


$QueueTimeOutURL="YOUR_QUEUE_TIMEOUT_URL_HERE";
$ResultURL="YOUR_RESULT_URLHERE";



/*The below are production URLS CHANGE TO SANDBOX IF YOU HAVEN'T GONE LIVE */

$authorizationurl='https://api.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials';
$paymentrequesturl="https://api.safaricom.co.ke/mpesa/b2c/v1/paymentrequest";



/* FIRST WE AUTHENTICATE OUR API CALL */

/* BEGIN AUTHENTICATION TO GET ACCESS TOKEN*/

  // Request headers
  $headers = array(	
    'Content-Type: application/json; charset=utf-8'
  );

  // Request
  $ch = curl_init($authorizationurl);
  curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
  //curl_setopt($ch, CURLOPT_HEADER, TRUE); // Includes the header in the output
  curl_setopt($ch, CURLOPT_HEADER, FALSE); // excludes the header in the output

  curl_setopt($ch, CURLOPT_USERPWD, $consumerkey . ":" . $consumersecret); // HTTP Basic Authentication
  $result = curl_exec($ch);	

if(curl_errno($ch)){
    echo 'Request Error:' . curl_error($ch);
    exit();
}



$result = json_decode($result);

$access_token=$result->access_token;

curl_close($ch);


/* END AUTHENTICATION */



/* BEGIN PAYMENT REQUEST IF WE GOT ACCESS TOKEN*





if(!$access_token)

{

  echo " Invalid access token ". print_r($result);

}

else


{



$publicKey = "-----BEGIN CERTIFICATE-----
MIIGkzCCBXugAwIBAgIKXfBp5gAAAD+hNjANBgkqhkiG9w0BAQsFADBbMRMwEQYK
CZImiZPyLGQBGRYDbmV0MRkwFwYKCZImiZPyLGQBGRYJc2FmYXJpY29tMSkwJwYD
VQQDEyBTYWZhcmljb20gSW50ZXJuYWwgSXNzdWluZyBDQSAwMjAeFw0xNzA0MjUx
NjA3MjRaFw0xODAzMjExMzIwMTNaMIGNMQswCQYDVQQGEwJLRTEQMA4GA1UECBMH
TmFpcm9iaTEQMA4GA1UEBxMHTmFpcm9iaTEaMBgGA1UEChMRU2FmYXJpY29tIExp
bWl0ZWQxEzARBgNVBAsTClRlY2hub2xvZ3kxKTAnBgNVBAMTIGFwaWdlZS5hcGlj
YWxsZXIuc2FmYXJpY29tLmNvLmtlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAoknIb5Tm1hxOVdFsOejAs6veAai32Zv442BLuOGkFKUeCUM2s0K8XEsU
t6BP25rQGNlTCTEqfdtRrym6bt5k0fTDscf0yMCoYzaxTh1mejg8rPO6bD8MJB0c
FWRUeLEyWjMeEPsYVSJFv7T58IdAn7/RhkrpBl1dT7SmIZfNVkIlD35+Cxgab+u7
+c7dHh6mWguEEoE3NbV7Xjl60zbD/Buvmu6i9EYz+27jNVPI6pRXHvp+ajIzTSsi
eD8Ztz1eoC9mphErasAGpMbR1sba9bM6hjw4tyTWnJDz7RdQQmnsW1NfFdYdK0qD
RKUX7SG6rQkBqVhndFve4SDFRq6wvQIDAQABo4IDJDCCAyAwHQYDVR0OBBYEFG2w
ycrgEBPFzPUZVjh8KoJ3EpuyMB8GA1UdIwQYMBaAFOsy1E9+YJo6mCBjug1evuh5
TtUkMIIBOwYDVR0fBIIBMjCCAS4wggEqoIIBJqCCASKGgdZsZGFwOi8vL0NOPVNh
ZmFyaWNvbSUyMEludGVybmFsJTIwSXNzdWluZyUyMENBJTIwMDIsQ049U1ZEVDNJ
U1NDQTAxLENOPUNEUCxDTj1QdWJsaWMlMjBLZXklMjBTZXJ2aWNlcyxDTj1TZXJ2
aWNlcyxDTj1Db25maWd1cmF0aW9uLERDPXNhZmFyaWNvbSxEQz1uZXQ/Y2VydGlm
aWNhdGVSZXZvY2F0aW9uTGlzdD9iYXNlP29iamVjdENsYXNzPWNSTERpc3RyaWJ1
dGlvblBvaW50hkdodHRwOi8vY3JsLnNhZmFyaWNvbS5jby5rZS9TYWZhcmljb20l
MjBJbnRlcm5hbCUyMElzc3VpbmclMjBDQSUyMDAyLmNybDCCAQkGCCsGAQUFBwEB
BIH8MIH5MIHJBggrBgEFBQcwAoaBvGxkYXA6Ly8vQ049U2FmYXJpY29tJTIwSW50
ZXJuYWwlMjBJc3N1aW5nJTIwQ0ElMjAwMixDTj1BSUEsQ049UHVibGljJTIwS2V5
JTIwU2VydmljZXMsQ049U2VydmljZXMsQ049Q29uZmlndXJhdGlvbixEQz1zYWZh
cmljb20sREM9bmV0P2NBQ2VydGlmaWNhdGU/YmFzZT9vYmplY3RDbGFzcz1jZXJ0
aWZpY2F0aW9uQXV0aG9yaXR5MCsGCCsGAQUFBzABhh9odHRwOi8vY3JsLnNhZmFy
aWNvbS5jby5rZS9vY3NwMAsGA1UdDwQEAwIFoDA9BgkrBgEEAYI3FQcEMDAuBiYr
BgEEAYI3FQiHz4xWhMLEA4XphTaE3tENhqCICGeGwcdsg7m5awIBZAIBDDAdBgNV
HSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwJwYJKwYBBAGCNxUKBBowGDAKBggr
BgEFBQcDAjAKBggrBgEFBQcDATANBgkqhkiG9w0BAQsFAAOCAQEAC/hWx7KTwSYr
x2SOyyHNLTRmCnCJmqxA/Q+IzpW1mGtw4Sb/8jdsoWrDiYLxoKGkgkvmQmB2J3zU
ngzJIM2EeU921vbjLqX9sLWStZbNC2Udk5HEecdpe1AN/ltIoE09ntglUNINyCmf
zChs2maF0Rd/y5hGnMM9bX9ub0sqrkzL3ihfmv4vkXNxYR8k246ZZ8tjQEVsKehE
dqAmj8WYkYdWIHQlkKFP9ba0RJv7aBKb8/KP+qZ5hJip0I5Ey6JJ3wlEWRWUYUKh
gYoPHrJ92ToadnFCCpOlLKWc0xVxANofy6fqreOVboPO0qTAYpoXakmgeRNLUiar
0ah6M/q/KA==
-----END CERTIFICATE-----
";


openssl_public_encrypt($initiatorpassword, $encrypted, $publicKey, OPENSSL_PKCS1_PADDING);

//GENERATE SECURITY CREDENTIAL USING THE PUBLIC KEY ABOVE

$securitycredential=base64_encode($encrypted);

/* MAKE PAYMENT REQUEST */


$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $paymentrequesturl);
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type:application/json','Authorization:Bearer '.$access_token)); 

$curl_post_data = array(  
 
  'InitiatorName' => $initiatorname,
  'SecurityCredential' => $securitycredential,
  'CommandID' =>  $commandid,
  'Amount' =>  $amount,
  'PartyA' => $shortcode,
  'PartyB' =>  $recipient,  
  'Remarks' => $remarks,
  'QueueTimeOutURL' => $QueueTimeOutURL,
  'ResultURL' => $ResultURL,
  'Occassion' => $occassion
);

$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);


  $response = json_decode($curl_response);

  if(!isset($response->ConversationID))

  {
  echo "There was an error when submitting your request: $response->errorMessage";
  
  }

  else

  {
  echo "Success, $response->ResponseDescription ";
  }


}


?>

Step 4: Queue Timeout and Result URLs

The Mpesa B2C API Queue timeout URL is called if the transactions times out from the Mpesa side. Result URL is called once the transaction is finalized.

When you receive the status of the transaction on the results URL, you should analyze the response to see if the transaction succeeded or not.

A transaction may fail due to the following reasons:

  1. Incorrect security credentials
  2. Insufficient funds from the Mpesa B2C account. Please note the minimum amount you can load on the B2C account is Kshs. 5,000/=. But you should not worry, if you are just testing out the  Mpesa Business to Customer API, you can load the amount and then send it back to your phone number
  3. Authorization error: This happens if the username that you have specified does not have the rights to initiate the Mpesa B2C transaction.

Sample Success Response from Mpesa B2C gateway

{  
   "Result":{  
      "ResultType":0,
      "ResultCode":0,
      "ResultDesc":"The service request is processed successfully.",
      "OriginatorConversationID":"11369-5305957-1",
      "ConversationID":"AG_20190103_00004ad7c21029e28510",
      "TransactionID":"NA30XPKKVCW",
      "ResultParameters":{  
         "ResultParameter":[  
            {  
               "Key":"TransactionAmount",
               "Value":100
            },
            {  
               "Key":"TransactionReceipt",
               "Value":"NA30XKHVCW"
            },
            {  
               "Key":"ReceiverPartyPublicName",
               "Value":"2547XXXXXXX - JOHN DOE"
            },
            {  
               "Key":"TransactionCompletedDateTime",
               "Value":"03.01.2019 17:48:32"
            },
            {  
               "Key":"B2CUtilityAccountAvailableFunds",
               "Value":4425.00
            },
            {  
               "Key":"B2CWorkingAccountAvailableFunds",
               "Value":0.00
            },
            {  
               "Key":"B2CRecipientIsRegisteredCustomer",
               "Value":"Y"
            },
            {  
               "Key":"B2CChargesPaidAccountAvailableFunds",
               "Value":0.00
            }
         ]
      },
      "ReferenceData":{  
         "ReferenceItem":{  
            "Key":"QueueTimeoutURL",
            "Value":"http:\/\/internalapi.safaricom.co.ke\/mpesa\/b2cresults\/v1\/submit"
         }
      }
   }
}

Sample Error Message from Mpesa B2C API Gateway- The Initiator Information is Invalid

{  
   "Result":{  
      "ResultType":0,
      "ResultCode":2001,
      "ResultDesc":"The initiator information is invalid.",
      "OriginatorConversationID":"7488-6256766-1",
      "ConversationID":"AG_20190104_00004ce9fc41b15aa227",
      "TransactionID":"NA43XZPDE3",
      "ReferenceData":{  
         "ReferenceItem":{  
            "Key":"QueueTimeoutURL",
            "Value":"http:\/\/internalapi.safaricom.co.ke\/mpesa\/b2cresults\/v1\/submit"
         }
      }
   }
}

Sample Safaricom Mpesa B2C API Insufficient Funds JSON Error

{  
   "Result":{  
      "ResultType":0,
      "ResultCode":1,
      "ResultDesc":"The balance is insufficient for the transaction.",
      "OriginatorConversationID":"18221-6293510-1",
      "ConversationID":"AG_20190104_00005b7d5130c96080a9",
      "TransactionID":"Ni417ZUTBX",
      "ReferenceData":{  
         "ReferenceItem":{  
            "Key":"QueueTimeoutURL",
            "Value":"http:\/\/internalapi.safaricom.co.ke\/mpesa\/b2cresults\/v1\/submit"
         }
      }
   }
}

In simple terms, if the ResultCode parameter is 0, then it means the transaction is completed and successful. Any other values means an error.

Conclusion

This guide should give you an overview of how you should develop a Safaricom Mpesa B2C API. While it is not a conclusive list of all the things that you might require, it will assist you to program your app.

Use the code given here at your own risk. Also, never save your Mpesa login portal password on your hosting files for security reasons.

How to Develop Mpesa Integration to Website Using Safaricom C2B API

Introduction

In this guide, you are going to learn how to develop Mpesa integration to website. Mpesa is one of the most popular mobile money transfer services in the world.

The innovative product is offered by Safaricom – Kenya’s leading telecommunication company with the strongest and widest network coverage.

With Mpesa, anyone can send money to you in Kenya using their Safaricom sim card and a mobile phone that supports a Sim Tool Kit(STK).

Safaricom has a ‘Lipa na Mpesa’ service specifically tailored for businesses that want to collect payments through the Mpesa payment gateway for Till and Paybill numbers(short codes).

Lipa na Mpesa offers a lot of convenience to customers and businesses. Text notifications are sent to merchants’ nominated mobile numbers when customers make payments to the business’s short code that is issued for free by Safaricom.

Apart from the SMS notifications, it is possible to develop Mpesa integration to website. This is a more effective way of pushing Mpesa transactions details to a website’s database automatically.

The transaction can then be processed further to update a website work-flow or business logic. The same analogy is used by banks in Kenya to credit customers’ Mpesa transactions to their respective accounts.

Developers can integrate with M-Pesa payment gateway by following the steps below.

Prerequisites

  • A domain name e.g. www.example.com estimated cost $15/year . If you buy a hosting space from Bluehostyou will get a free domain name.
  • A web hosting space from a reputable company. I recommend Bluehost because their hosting service is more secure, reliable and fast.
  • Apache or any other web server that supports PHP.
  • MySql database.
  • PhpMyadmin to administer your database.
  • An ftp username with privileges to upload files to a web server.

Step 1: Create an account at Safaricom Developer Portal

Mpesa maintains a central developer portal at https://developer.safaricom.co.ke/login-register. Just click the link above to create your account.

You will need to enter the following details. Please make sure the details are accurate.

  • First Name *
  • Last Name *
  • Account Type *
  • Username *
  • E-mail address *
  • Company Name
  • Country *
  • Mobile Number *

Step 2: Creating a C2B API and Generating a Consumer Key and a Consumer Secret

Once your account is approved, Login to the Mpesa developer portal https://developer.safaricom.co.ke/login-register by entering your username and password.

Click the “My APPs” link at the top left to create your first app, and then click on the “Add a new APP” button on your right.

Since you are creating Mpesa integration to website using c2b API, check the box that reads, “Mpesa sandbox for b2b, b2c and c2b apis” . Then assign your app any name e.g. MyWebsite Api

Then, click on the “Create APP” button.

Once your app is created, you need to click it under the heading, “These are your apps! Explore them!

At the bottom left, you will see your consumer key and consumer secret. Just copy paste those details somewhere on your computer – we will need them later.

<!––nextpage––>

Step 3: Creating a Security Token to Safeguard Against Fake Transactions

Using M-Pesa payment gateway is a good way to receive payments on your website. However, it can become a target of hackers. To safeguard against this, you need to generate a strong password with a mix of letters, numbers and special characters. e..g

yourPU_RstrongPasswordSample$

The password will be used as an authorization mechanism to secure your website’s call back urls that Safaricom API will notify once your receive a payment on your Mpesa Till or Paybill number.

Step 4: Retrieve a Test Short-code

The Safaricom developer portal allows you to generate a short code that you can use to test your integration of Mpesa to your website before moving to production.

While logged in on the Mpesa developer website, click the link below to get the  test short code.

https://developer.safaricom.co.ke/test_credentials

Copy the 6 digit shortcode 1 number and keep it alongside the consumer key and consumer secret that you generate earlier.

Step 4: Creating a Database Table to Store Mpesa Transactions

Integrating Mpesa on your website requires you to have a  database for storing transactions. You need to create a database and a table. You can use phpMyadmin to do this.  Before you do this, make sure you have a secure web hosting service  from a reputable company like Bluehost.

Your table schema should look like this. Let’s give this table a name like mpesa_payments

Auto - Auto number
TransactionType Varchar 40
TransID  Varchar 40
TransTime Varchar 40
TransAmount double
BusinessShortCode Varchar 15
BillRefNumber Varchar 40
InvoiceNumber Varchar 40
ThirdPartyTransID Varchar 40
MSISDN Varchar 20
FirstName Varchar 60
MiddleName Varchar 60
LastName Varchar 60
OrgAccountBalance Double

The length of the variable characters used above can be optimized and we have just used an arbitrary length to make sure the transactions will not fail.

Step 5:  Creating a Folder on your Website to Store Validation and Confirmation URLs

Next we need to create a folder for holding Mpesa website API call back URL’s. When a customer makes payment to your till or Paybill number, Mpesa will first send the transaction details on your validation URL.

You should do your business logic to validate the transactions. For instance, you can check the amount or the account number and reject the transaction.

Create a folder on your website root. Assuming your website is www.example.com, you can create a folder like www.example.com/mpesa/ . However, using a random name is more secure e.g www.example.com/ixoisjus/

Step 6:  Creating a C2B validation Callback URL  

Next, you need to upload a PHP validation file to that folder. You can use notepad to create the file and give it a name like “validation.php

So your full validation URL will read like this www.example.com/mpesa/validation.php

Then, you need to copy paste the following text on that file.

<?php 

header("Content-Type:application/json"); 

if (!isset($_GET["token"]))
{
echo "Technical error";
exit();
}



if ($_GET["token"]!='yourPU_RstrongPasswordSample$')
{
echo "Invalid authorization";
exit();
}



/* 
here you need to parse the json format 
and do your business logic e.g. 
you can use the Bill Reference number 
or mobile phone of a customer 
to search for a matching record on your database. 
*/ 

/* 
Reject an Mpesa transaction 
by replying with the below code 
*/ 

echo '{"ResultCode":1, "ResultDesc":"Failed", "ThirdPartyTransID": 0}'; 

/* 
Accept an Mpesa transaction 
by replying with the below code 
*/ 

echo '{"ResultCode":0, "ResultDesc":"Success", "ThirdPartyTransID": 0}';
 
?>

As you can see , you can either reject or accept the transaction by replying with appropriate response.

Remember to change the token variable with the password that you created above.

Step 7:  Creating a C2B Confirmation Callback URL on Your Website

Create another file and give it a name like “confirmation.php

Your full confirmation URL will read like this www.example.com/mpesa/confirmation.php

The confirmation URL will be called back by Safaricom when a customer transaction is finalized on their side. Therefore, we need to strip the json input from the Mpesa API and save the transaction details on our database that we created above.

Just copy paste the below content on the confirmation.php file and upload it on your website. You can either do this using Filezilla or the file manager that ships with Cpanel especially if you are using Bluehost

Remember to replace the token variable with the password that you chose above. You also need to supply your Mysql hostname(servername), username, password and database name in the appropriate fields.

<?php

header("Content-Type:application/json");

if (!isset($_GET["token"]))
{
echo "Technical error";
exit();
}



if ($_GET["token"]!='yourPU_RstrongPasswordSample$')
{
echo "Invalid authorization";
exit();
}



if (!$request=file_get_contents('php://input'))

{
echo "Invalid input";
exit();
}






$con = mysqli_connect($servername, $username, $password, $dbname);

if (!$con) 
{
die("Connection failed: " . mysqli_connect_error());
}



//Put the json string that we received from Safaricom to an array
$array = json_decode($request, true);
$transactiontype= mysqli_real_escape_string($con,$array['TransactionType']); 
$transid=mysqli_real_escape_string($con,$array['TransID']); 
$transtime= mysqli_real_escape_string($con,$array['TransTime']); 
$transamount= mysqli_real_escape_string($con,$array['TransAmount']); 
$businessshortcode=  mysqli_real_escape_string($con,$array['BusinessShortCode']); 
$billrefno=  mysqli_real_escape_string($con,$array['BillRefNumber']); 
$invoiceno=  mysqli_real_escape_string($con,$array['InvoiceNumber']); 
$msisdn=  mysqli_real_escape_string($con,$array['MSISDN']); 
$orgaccountbalance=   mysqli_real_escape_string($con,$array['OrgAccountBalance']); 
$firstname=mysqli_real_escape_string($con,$array['FirstName']); 
$middlename=mysqli_real_escape_string($con,$array['MiddleName']); 
$lastname=mysqli_real_escape_string($con,$array['LastName']); 
 


$sql="INSERT INTO mpesa_payments
( 
TransactionType,
TransID,
TransTime,
TransAmount,
BusinessShortCode,
BillRefNumber,
InvoiceNumber,
MSISDN,
FirstName,
MiddleName,
LastName,
OrgAccountBalance
)  
VALUES  
( 
'$transactiontype', 
'$transid', 
'$transtime', 
'$transamount', 
'$businessshortcode', 
'$billrefno', 
'$invoiceno', 
'$msisdn',
'$firstname', 
'$middlename', 
'$lastname', 
'$orgaccountbalance' 
)";
 

if (!mysqli_query($con,$sql)) 
 
{ 
echo mysqli_error($con); 
} 
 
 
else 
{ 
echo '{"ResultCode":0,"ResultDesc":"Confirmation received successfully"}';
}
 
mysqli_close($con); 
?>

Step 8:  Registering Validation and Confirmation Callback URLs on Safaricom API

Finally, we need to register the validation and confirmation urls on the M-pesa payment gateway. This will enable safaricom to call our URL’s when a transaction occurs on their side.

To do this, we need to create a third file and upload it to our website. You can call this file register.php.

So your full register.php URL will read like this

www.example.com/mpesa/register.php

To register our validation and confirmation URL’s, we will use curl and PHP. Just copy paste the text below on your register.php file and replace your shortcode, consumer key and consumer secret.

<?php
header("Content-Type:application/json");
$shortcode='replacewithyourshortcode';
$consumerkey    ="replacewithyourconsumerkey";
$consumersecret ="replacewithyourconsumersecret";
$validationurl="enteryourvalidationurlhere";
$confirmationurl="enteryourconfirmationurlhere";
/* testing environment, comment the below two lines if on production */
$authenticationurl='https://sandbox.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials';
$registerurl = 'https://sandbox.safaricom.co.ke/mpesa/c2b/v1/registerurl';
/* production un-comment the below two lines if you are in production */
//$authenticationurl='https://api.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials';
//$registerurl = 'https://api.safaricom.co.ke/mpesa/c2b/v1/registerurl';
$credentials= base64_encode($consumerkey.':'.$consumersecret);
$username=$consumerkey ;
$password=$consumersecret;
  // Request headers
  $headers = array(  
    'Content-Type: application/json; charset=utf-8'
  );
  // Request
  $ch = curl_init($authenticationurl);
  curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
  //curl_setopt($ch, CURLOPT_HEADER, TRUE); // Includes the header in the output
  curl_setopt($ch, CURLOPT_HEADER, FALSE); // excludes the header in the output
  curl_setopt($ch, CURLOPT_USERPWD, $username . ":" . $password); // HTTP Basic Authentication
  $result = curl_exec($ch);  
  $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);  
$result = json_decode($result);
$access_token=$result->access_token;
curl_close($ch);

//Register urls
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $registerurl);
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type:application/json','Authorization:Bearer '.$access_token)); 
$curl_post_data = array(
  //Fill in the request parameters with valid values
  'ShortCode' => $shortcode,
  'ResponseType' => 'Cancelled',
  'ConfirmationURL' => $confirmationurl,
  'ValidationURL' => $validationurl
);
$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);
echo $curl_response;
?>

However, you need to append the password that you chose above on your validation and confirmation URL’s using a token variable when registering the URL’s.

So your validation and confirmation urls will read like this on the register.php file.

Validation URL

https://www.example.com/mpesa/validation.php?token=yoPURstrongPasswordGoeshere$

Confirmation URL

https://www.example.com/mpesa/confirmation.php?token=yoPURstrongPasswordGoeshere$

Once the file is ready, upload it on your website. You will then need to open the file with your web browser to register the URL’s.

So on your web browser,  visit www.example.com/mpesa/register.php and your urls will be registered automatically with the Mpesa API.

Step 9: Testing the Validation and Confirmation URLs Configurations

You can test the configurations of your validation and confirmation urls using our Mpesa API URLs simulator: https://www.tekfansworld.com/simulate/mpesa-c2b-api-simulation.php

This tool mimics what the Mpesa server does when a customer makes a transactions to your Paybill or Till number.

Once your validation and confirmation URLs are all set as discussed above, use our tool to send sample transactions to your website and see whether  Mpesa API works as expected.

Again, you can visit the tool from this link: https://www.tekfansworld.com/simulate/mpesa-c2b-api-simulation.php

The tool looks like this:

Step 10:  Moving Mpesa API to Production

If you are able to complete the above steps and you got a success message during url registration. You can now move to production. On the Safaricom developer portal, click on the, “Go Live” link at the portal, you will be taken through a series of steps to prove ownership of your Paybill or Till number.

You will also need to download an Excel test case document, look for the c2b worksheet name at the bottom.

On the worksheet, create a new column with the name Actual Results and enter the word ‘okay’ or ‘success’ all the way from top to bottom. This signifies that you were able to run all Mpesa API test cases on your C2B API on the sandbox environment.

Mpesa API testcases.xlsx
Mpesa API test cases

Once everything is finalized, your app will be moved to production and you will get a new set of consumer key and consumer secret. Then, you will need to re-register URL’s with your live Paybill or Till number plus the new set of credentials.

From this point forward, all transactions will be routed to your website database and you can do your business logic for further processing.

Pro Tip : Validation on your short code is not enabled by default. 

If you want validation for your Paybill or Till number, kindly write to APIfeedback@Safaricom.co.ke and ask them to activate the same.

Sample Email:

Greetings,

Kindly enable external validation for our Paybill/Till number 111111. Our organization name is Sample Company. 

We would like to validate all Mpesa transactions before they are completed.

Regards,

Signatories

Remember to replace 111111 with your Mpesa Paybill/Till number and Sample Company with the real name associated with your Paybill or Till number

Conclusion

You can use this Mpesa API documentation to develop a customer to business API for your website. Remember, you can always refer to the Mpesa developer portal tutorials in case you run into a problem.

However, if you have followed the above Mpesa integration for website tutorial step by step, your c2b API will work without any hiccups.

Also, for the best experience with your Mpesa API, I recommend Bluehost because it has a fast, reliable and secure hosting for Mpesa api gateway financing transactions.

Remember to check out our Mpesa C2B Simulator tool for simplified testing.

You might also like:

Mpesa B2C(Business to Customer) API

 

Rest API Best Practices for Beginners

In this guide, I am going to talk about REST API best practices that you can follow to craft a standard API that your developers can use to consume your data and services without any trouble.

Even if you are not designing your API for the public, following the best API design guidelines standardizes your application hence making it easier to maintain  in the future.

The majority of web players  like Google, Facebook, Twitter and Bigcommerce have public API’s. Unfortunately, each of these companies uses a different format.

So, if you are starting out as a developer, you might wonder whether there is standard format of creating APIs bearing in mind that such big companies are following their own conventions.

Luckily, there are industry’s best standard API design guidelines that you can follow and I am going to talk about them here.

Separate your REST API interface into Logical Resources

Creating an API is both an art and a science. Use your software architectural skills to make a rest API interface that is easy for developers to understand. Creating logical resources is not hard.

You need to consider all possible endpoints that your API will expose to the public or your in-house software application. For instance, when designing my API endpoints I start with offices, followed by system roles, e.t.c.  The same case applies to your application.

To put this into perspective an API for an online shop can have the following endpoints:

  • products_categories – www.example.com/api/v1/products_categories
  • products – www.example.com/api/v1/products
  • customers – www.example.com/api/v1/customers
  • sales_orders – www.example.com/api/v1/sales_orders

API Interface Design Principles

When I first designed my API’s, I used all kind of names on the endpoints because I wasn’t following any design guidelines. However, here are a few points that you must keep in mind before creating your resources.

Use Nouns Instead of Verbs

A noun is a word used to identify something while a verb is a “doing word” that describes an action. For instance, if you are creating a products resource, you shouldn’t use an endpoint like “createproduct” or “editproduct”. Instead use an endpoint like “products”.

Use Plurals on your API Endpoints

Developers can have a hard time trying to consume an API that has both the singular and plural forms. E.g. a poorly designed API for retrieving customers can have different endpoints like www.example.com/api/v1/customers and www.example.com/api/v1/customer.

The former can be used to create, delete or retrieve a single customer while the latter can return all customers. Such a design is completely confusing. Just use the plural form even when your api is returning a single resource.

Differentiate API Actions Using HTTP verbs

As mentioned above, a good API should use the plural form of the noun e.g. www.example.com/api/v1/customers. However, you can differentiate the different kind of actions on that endpoint by using http verbs: POST, GET, PUT and DELETE.

So any call to your API will perform the appropriate action and take care of CRUD (Create, Read, Update, and Delete) operations. The Post http verb will be used for creating new records, GET will retrieve  records, PUT will update the records while DELETE will remove an existing record from database.

Your API Endpoints Should Accept Resource Id’s

Resource Id’s are very important when your API consumers want to retrieve, update or delete a single record. E.g. a sample URL like www.example.com/api/v1/customers/21 should be able to retrieve a customer with Id # 21 when called using a GET http verb. A delete request with the same URL will delete the customer with that id.

Generate Resource Ids Internally During POST Requests

Generate the resource id internally in a post request. Don’t ask your API consumer to supply it on the POST payload. This can lead to all sort of problems including skipped id’s, non standard formats (e.g. in case of bank application) e.t.c

Sample json API response with an id returned

{

"id": "143562",

"name": "John Doe"

}

REST API Filtering, Sorting and Paging 

Filtering: Your API should handle filtering when consumers want to return only a few records. Filtering is possible using the GET parameters  embedded on the URL. For instance to retrieve all the products in a specific category, one might use an URL format like www.example.com/api/v1/products?Category_Id=4.

Sorting: The need of arranging and separating records from an API  is inevitable. A good example is when an API consumer wants to display the most recent records at the top of a list view but display the opposite on a report.

To achieve such a function, allow the developers to include the sort parameters when requesting a resource e.g. the url www.example.com/api/v1/products?sort=product_name will display all products arranged in ascending order  by the product_name field. Also the records can be arranged in a descending order by prefixing the sort field by a “-” minus/negative sign e.g. www.example.com/api/v1/products?sort=-product_name

Pagination: A resource returning a lot of records should allow paging otherwise it might crash your API server. Different rest paging best practices exist but the common one uses a page parameter on the URL E.g. www.example.com/api/v1/products?page=4.

Also, the API consumer should know the total number of pages and count of records expected in a resource. Pagination information should be included in a meta member at the end of the json document.

meta : {
"page": 5,
"per_page": 20,
"total_pages": 27,
"count": 521
}

This way, developers can display the total number of pages expected from a resource without errors.

Spell out Magic Numbers

Using magic numbers in a database environment is inevitable due to optimization. For instance, if you are designing an e-commerce api, the possible statuses of the order can be ‘paid’,’unpaid’,’shipped’

Including the information on the orders table will bloat your database. To avoid the problem, you create a different table with all the resources and assign ids for the same e.g. unpaid -0, paid -1, shipped -2.

Once you do that, you should remember to spell out the magic numbers when returning the response to the consumer as shown below. Otherwise, they will have to make two round trips to your API server to get the representation of each magic number.

{

"order_id": 5,

"status_id": 2,

"status_name": "shipped",

}

REST API Response Formats

Json has become the standard format of REST API responses and XML is quickly becoming deprecated. Json is lighter and easy to serialize or deserialize. The Json API response should contain 3 mandatory top level members including data, errors and meta. However, data and errors cannot co-exist in the same document.

Here is a sample json response with all elements:

{

"data" :[

{"product_id" : 1,"product_name" : "Coast Sheena Maxi Dress"},

{"product_id" : 2,"product_name" : "Reila Mini Dress"},

{"product_id" : 3,"product_name" : "Siffon Midi Yellow"}

]
meta : 
{ "page": 1, "per_page": 3, "total_pages": 4, "count": 12 }


}

Json API Response with Errors

Returning a single error in a REST api response is recommended as it allows the client to deal with the error properly. Always include an error code and the details. Title is optional.

{

"errors" :{
"code" : 400,
"title" : "Validation Failed",
"detail" : "First_Name is a required."
}

}

Field Name Casing in Json REST APIs

You can use camelCase or snake_case in field names but most experts agree that snake case is easier to read. When I first show an API provider using camelCase, I thought their developers were making typing errors and I can attest that camelCase does not look any good!

Examples of Cases Used in REST API Fields

  • camelCase:  e.g. productName, categoryName
  • snake_case :  e.g. product_name, category_name or Product_Name, Category_Name

Rest API Guidelines on HTTP Status Codes

Always Include the status header on every rest response in regards to the following.

  • 200 Ok – should be returned on a successful GET, POST, PUT, DELETE or POST action
  • 201 Created – should be returned to indicate that a new resource is created e.g. a new customers
  • 202 Accepted – indicates that a request has been successfully received but it’s still waiting processing. Common in the finance industry.
  • 204 No Content – used upon a successful deletion
  • 400 Bad Request – The request is malformed e.g. when you send a payload with validation errors
  • 401 Unauthorized – means that the api users couldn’t be authenticated on the server
  • 403 Forbidden – useful to restrict the api user from accessing restricted resources
  • 404 Not Found – return this status if an item is not found or when a user request a resource that does not exist.
  • 405 Method Not Allowed – returned when the http method is not allowed on a resource. For instance, if a user sends a delete request to the users’’ endpoint, the response should be returned.
  • 429 Too Many Requests – used alongside rate-limiting to avoid dos(Denial of Service) attack.
  • 500 Internal server error : Generated when there is a problem with the server e.g. due to failed database connection.

Versioning your REST API

An API version number (e.g. v1, v2, v3, e.t.c) should be included in the URL like www.example.com/api/v1 . A rule of thumb is to always support the previous version when you migrate to a new one.

 Increment the version number once your release a new version. Don’t replace the previous version’s files with the new release since these will break the developer’s code.

REST Web Services Security Best Practices

Use SSL everywhere and when a client requests data through the non-secure channel http, never redirect them to https but just reply with an error message.

SSL makes your API secure since your consumers could be accessing the resources from unsafe wifi-hotspots and cyber cafes which may lead to a man-in-the-middle attack.

Use strong hashing algorithms like bcrypt and avoid the less secure functions like md5 when storing passwords and authentication tokens.

Your API should also have a strong form of authentication. You can use Oath2 or Basic authentication. Remember to create strong authorization rules and use roles to differentiate the different categories that an API user can access.

Use rate limiting in the API resource to avoid users from abusing your service and block all IP addresses trying to brute-force passwords.

Conclusion

I hope the API interface design principles on this guide will assist you craft better API’s that follow the standard specifications.

Remember updating your API in the future can be a painful process and conforming to the industry’s best rest web service guidelines will save your time.

Although this is not an exhaustive list, it has covered the most common features every pragmatic restful design  of an API should consider.

Further readings