diff --git a/readme.md b/readme.md
index e0d5163..9aa160b 100644
--- a/readme.md
+++ b/readme.md
@@ -1,51 +1,55 @@
**Introduction**
This package seeks to help php developers implement the various Mpesa APIs without much hustle. It is based on the REST API whose documentation is available on https://developer.safaricom.co.ke.
-
+
**Installation using composer**
`composer require safaricom/mpesa`
-
-
+
+
**Configuration**
At your project root, create a .env file and in it set the consumer key and consumer secret as follows
`MPESA_CONSUMER_KEY= [consumer key]`
`MPESA_CONSUMER_SECRET=[consumer secret]`
+ `MPESA_PASSWORD=[your mpesa password]`
+ `MPESA_PUBLICKEYPATH=[/path/to/your/public_key_file.cer]`
`MPESA_ENV=[live or sandbox]`
For Laravel users, open the Config/App.php file and add `\Safaricom\Mpesa\MpesaServiceProvider::class` under providers and ` 'Mpesa'=> \Safaricom\Mpesa\MpesaServiceProvider::class` under aliases.
-
+
_Remember to edit the consumer_key and consumer_secret values appropriately when switching between sandbox and live_
-
+
**Usage**
-
- **Confirmation and validation urls**
+
+ **Confirmation and validation urls**
**B2C Payment Request**
-
+
This creates transaction between an M-Pesa short code to a phone number registered on M-Pesa.
-
-`$mpesa= new \Safaricom\Mpesa\Mpesa();`
-`$b2cTransaction=$mpesa->b2c($InitiatorName, $SecurityCredential, $CommandID, $Amount, $PartyA, $PartyB, $Remarks, $QueueTimeOutURL, $ResultURL, $Occasion);`
+`$mpesa= new \Safaricom\Mpesa\Mpesa();`
+Use this functional to generate the SecurityCredential if you have several different MPESA_PASSWORD and MPESA_PUBLICKEYPATH, if you only have one just declare your MPESA_PASSWORD and MPESA_PUBLICKEYPATH in your environment variables and do not pass it in subsequent functional calls
+`$SecurityCredential=$mpesa->generateSecurityCredential([$Password = null] [, $PublicKey = null]);`
+The $SecurityCredential is optional, it is automatically generated using your MPESA_PASSWORD and MPESA_PUBLICKEYPATH declared in your environment variables
+`$b2cTransaction=$mpesa->b2c($InitiatorName [, $SecurityCredential], $CommandID, $Amount, $PartyA, $PartyB, $Remarks, $QueueTimeOutURL, $ResultURL, $Occasion);`
**Account Balance Request**
-
+
This is used to enquire the balance on an M-Pesa BuyGoods (Till Number)
`$mpesa= new \Safaricom\Mpesa\Mpesa();`
-`$balanceInquiry=$mpesa->accountBalance($CommandID, $Initiator, $SecurityCredential, $PartyA, $IdentifierType, $Remarks, $QueueTimeOutURL, $ResultURL);`
+`$balanceInquiry=$mpesa->accountBalance($CommandID, $Initiator [, $SecurityCredential], $PartyA, $IdentifierType, $Remarks, $QueueTimeOutURL, $ResultURL);`
**Transaction Status Request**
-This is used to check the status of transaction.
+This is used to check the status of transaction.
`$mpesa= new \Safaricom\Mpesa\Mpesa();`
-`$trasactionStatus=$mpesa->transactionStatus($Initiator, $SecurityCredential, $CommandID, $TransactionID, $PartyA, $IdentifierType, $ResultURL, $QueueTimeOutURL, $Remarks, $Occasion);`
+`$trasactionStatus=$mpesa->transactionStatus($Initiator [, $SecurityCredential], $CommandID, $TransactionID, $PartyA, $IdentifierType, $ResultURL, $QueueTimeOutURL, $Remarks, $Occasion);`
@@ -85,7 +89,7 @@ This is used to initiate online payment on behalf of a customer.
**STK Push Status Query**
This is used to check the status of a Lipa Na M-Pesa Online Payment.
-
+
`$mpesa= new \Safaricom\Mpesa\Mpesa();`
`$STKPushRequestStatus=$mpesa->STKPushQuery($checkoutRequestID,$businessShortCode,$password,$timestamp);`
@@ -98,24 +102,21 @@ M-Pesa APIs are asynchronous. When a valid M-Pesa API request is received by the
**Obtaining post data from callbacks**
This is used to get post data from callback in json format. The data can be decoded and stored in a database.
-
+
`$mpesa= new \Safaricom\Mpesa\Mpesa();`
-
+
`$callbackData=$mpesa->getDataFromCallback();`
-
+
**Finishing a transaction**
After obtaining the Post data from the callbacks, use this at the end of your callback routes to complete the transaction
-
+
`$mpesa= new \Safaricom\Mpesa\Mpesa();`
-
+
`$callbackData=$mpesa->finishTransaction();`
If validation fails, pass `false` to `finishTransaction()`
`$mpesa= new \Safaricom\Mpesa\Mpesa();`
-
- `$callbackData=$mpesa->finishTransaction(false);`
-
-
+ `$callbackData=$mpesa->finishTransaction(false);`
diff --git a/src/Mpesa.php b/src/Mpesa.php
index aa49d0f..1e70375 100644
--- a/src/Mpesa.php
+++ b/src/Mpesa.php
@@ -18,15 +18,15 @@
class Mpesa
{
- /**
+ /**
* Define env method similar to laravel's
*
* @param String $env_param | Environment Param Name
- *
+ *
* @return String | Actual Param
*/
- public static function env($env_param){
-
+ public static function env($env_param)
+ {
$dotenv = new Dotenv();
$dotenv->load('../.env');
@@ -39,8 +39,8 @@ public static function env($env_param){
* This is used to generate tokens for the live environment
* @return mixed
*/
- public static function generateLiveToken(){
-
+ public static function generateLiveToken()
+ {
try {
$consumer_key = env("MPESA_CONSUMER_KEY");
$consumer_secret = env("MPESA_CONSUMER_SECRET");
@@ -49,7 +49,7 @@ public static function generateLiveToken(){
$consumer_secret = self::env("MPESA_CONSUMER_SECRET");
}
- if(!isset($consumer_key)||!isset($consumer_secret)){
+ if (!isset($consumer_key)||!isset($consumer_secret)) {
die("please declare the consumer key and consumer secret as defined in the documentation");
}
$url = 'https://api.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials';
@@ -65,17 +65,41 @@ public static function generateLiveToken(){
$curl_response = curl_exec($curl);
return json_decode($curl_response)->access_token;
+ }
+ /**
+ *Use this function to generate your security credential
+ * @param $password | Optional | Your Mpesa Password, Default to Declaration of MPESA_PASSWORD in Environment Variables
+ * @param $PublicKey | Optional | The path to the location of your public key file, Default to Declaration of MPESA_PUBLICKEYPATH in Environment Variables
+ */
+ public function generateSecurityCredential($Password = null, $PublicKey = null)
+ {
+ try {
+ $Password = env("MPESA_PASSWORD");
+ $PublicKey = env("MPESA_PUBLICKEYPATH");
+ } catch (\Throwable $th) {
+ $Password = self::env("MPESA_PASSWORD");
+ $PublicKey = self::env("MPESA_PUBLICKEYPATH");
+ }
- }
+ $fp=fopen($PublicKey, "r");
+ $pub_key=fread($fp, 8192);
+ fclose($fp);
+ $PK="";
+ $PK=openssl_get_publickey($pub_key);
+ openssl_public_encrypt($this->pass, $encrypted, $PK, OPENSSL_PKCS1_PADDING);
+ return $this->securityCredential = base64_encode($encrypted);
+
+ echo json_encode($resultArray);
+ }
/**
* use this function to generate a sandbox token
* @return mixed
*/
- public static function generateSandBoxToken(){
-
+ public static function generateSandBoxToken()
+ {
try {
$consumer_key = env("MPESA_CONSUMER_KEY");
$consumer_secret = env("MPESA_CONSUMER_SECRET");
@@ -84,7 +108,7 @@ public static function generateSandBoxToken(){
$consumer_secret = self::env("MPESA_CONSUMER_SECRET");
}
- if(!isset($consumer_key)||!isset($consumer_secret)){
+ if (!isset($consumer_key)||!isset($consumer_secret)) {
die("please declare the consumer key and consumer secret as defined in the documentation");
}
$url = 'https://sandbox.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials';
@@ -106,7 +130,7 @@ public static function generateSandBoxToken(){
* Use this function to initiate a reversal request
* @param $CommandID | Takes only 'TransactionReversal' Command id
* @param $Initiator | The name of Initiator to initiating the request
- * @param $SecurityCredential | Encrypted Credential of user getting transaction amount
+ * @param $SecurityCredential | Optional | Encrypted password for the initiator to autheticate the transaction request, Autogenerated with Environment variables MPESA_PASSWORD & MPESA_PUBLICKEYPATH
* @param $TransactionID | Unique Id received with every transaction response.
* @param $Amount | Amount
* @param $ReceiverParty | Organization /MSISDN sending the transaction
@@ -117,21 +141,25 @@ public static function generateSandBoxToken(){
* @param $Occasion | Optional Parameter
* @return mixed|string
*/
- public static function reversal($CommandID, $Initiator, $SecurityCredential, $TransactionID, $Amount, $ReceiverParty, $RecieverIdentifierType, $ResultURL, $QueueTimeOutURL, $Remarks, $Occasion){
-
+ public static function reversal($CommandID, $Initiator, $SecurityCredential = null, $TransactionID, $Amount, $ReceiverParty, $RecieverIdentifierType, $ResultURL, $QueueTimeOutURL, $Remarks, $Occasion)
+ {
try {
$environment = env("MPESA_ENV");
} catch (\Throwable $th) {
$environment = self::env("MPESA_ENV");
}
- if( $environment =="live"){
+ if($SecurityCredential == null) {
+ $SecurityCredential = generateSecurityCredential();
+ }
+
+ if ($environment =="live") {
$url = 'https://api.safaricom.co.ke/mpesa/reversal/v1/request';
$token=self::generateLiveToken();
- }elseif ($environment=="sandbox"){
+ } elseif ($environment=="sandbox") {
$url = 'https://sandbox.safaricom.co.ke/mpesa/reversal/v1/request';
$token=self::generateSandBoxToken();
- }else{
+ } else {
return json_encode(["Message"=>"invalid application status"]);
}
@@ -164,12 +192,11 @@ public static function reversal($CommandID, $Initiator, $SecurityCredential, $Tr
curl_setopt($curl, CURLOPT_HEADER, false);
$curl_response = curl_exec($curl);
return json_decode($curl_response);
-
}
/**
* @param $InitiatorName | This is the credential/username used to authenticate the transaction request.
- * @param $SecurityCredential | Encrypted password for the initiator to autheticate the transaction request
+ * @param $SecurityCredential | Optional | Encrypted password for the initiator to autheticate the transaction request, Autogenerated with Environment variables MPESA_PASSWORD & MPESA_PUBLICKEYPATH
* @param $CommandID | Unique command for each transaction type e.g. SalaryPayment, BusinessPayment, PromotionPayment
* @param $Amount | The amount being transacted
* @param $PartyA | Organization’s shortcode initiating the transaction.
@@ -180,21 +207,25 @@ public static function reversal($CommandID, $Initiator, $SecurityCredential, $Tr
* @param $Occasion | Optional
* @return string
*/
- public static function b2c($InitiatorName, $SecurityCredential, $CommandID, $Amount, $PartyA, $PartyB, $Remarks, $QueueTimeOutURL, $ResultURL, $Occasion){
-
+ public static function b2c($InitiatorName, $SecurityCredential = null, $CommandID, $Amount, $PartyA, $PartyB, $Remarks, $QueueTimeOutURL, $ResultURL, $Occasion)
+ {
try {
$environment = env("MPESA_ENV");
} catch (\Throwable $th) {
$environment = self::env("MPESA_ENV");
}
- if( $environment =="live"){
+ if($SecurityCredential == null) {
+ $SecurityCredential = generateSecurityCredential();
+ }
+
+ if ($environment =="live") {
$url = 'https://api.safaricom.co.ke/mpesa/b2c/v1/paymentrequest';
$token=self::generateLiveToken();
- }elseif ($environment=="sandbox"){
+ } elseif ($environment=="sandbox") {
$url = 'https://sandbox.safaricom.co.ke/mpesa/b2c/v1/paymentrequest';
$token=self::generateSandBoxToken();
- }else{
+ } else {
return json_encode(["Message"=>"invalid application status"]);
}
@@ -226,7 +257,6 @@ public static function b2c($InitiatorName, $SecurityCredential, $CommandID, $Amo
$curl_response = curl_exec($curl);
return json_encode($curl_response);
-
}
/**
* Use this function to initiate a C2B transaction
@@ -237,21 +267,21 @@ public static function b2c($InitiatorName, $SecurityCredential, $CommandID, $Amo
* @param $BillRefNumber | Bill Reference Number (Optional).
* @return mixed|string
*/
- public static function c2b($ShortCode, $CommandID, $Amount, $Msisdn, $BillRefNumber ){
-
+ public static function c2b($ShortCode, $CommandID, $Amount, $Msisdn, $BillRefNumber)
+ {
try {
$environment = env("MPESA_ENV");
} catch (\Throwable $th) {
$environment = self::env("MPESA_ENV");
}
-
- if( $environment =="live"){
+
+ if ($environment =="live") {
$url = 'https://api.safaricom.co.ke/mpesa/c2b/v1/simulate';
$token=self::generateLiveToken();
- }elseif ($environment=="sandbox"){
+ } elseif ($environment=="sandbox") {
$url = 'https://sandbox.safaricom.co.ke/mpesa/c2b/v1/simulate';
$token=self::generateSandBoxToken();
- }else{
+ } else {
return json_encode(["Message"=>"invalid application status"]);
}
@@ -277,7 +307,6 @@ public static function c2b($ShortCode, $CommandID, $Amount, $Msisdn, $BillRef
curl_setopt($curl, CURLOPT_HEADER, false);
$curl_response = curl_exec($curl);
return $curl_response;
-
}
@@ -285,7 +314,7 @@ public static function c2b($ShortCode, $CommandID, $Amount, $Msisdn, $BillRef
* Use this to initiate a balance inquiry request
* @param $CommandID | A unique command passed to the M-Pesa system.
* @param $Initiator | This is the credential/username used to authenticate the transaction request.
- * @param $SecurityCredential | Encrypted password for the initiator to autheticate the transaction request
+ * @param $SecurityCredential | Optional | Encrypted password for the initiator to autheticate the transaction request, Autogenerated with Environment variables MPESA_PASSWORD & MPESA_PUBLICKEYPATH
* @param $PartyA | Type of organization receiving the transaction
* @param $IdentifierType |Type of organization receiving the transaction
* @param $Remarks | Comments that are sent along with the transaction.
@@ -293,21 +322,25 @@ public static function c2b($ShortCode, $CommandID, $Amount, $Msisdn, $BillRef
* @param $ResultURL | The path that stores information of transaction
* @return mixed|string
*/
- public static function accountBalance($CommandID, $Initiator, $SecurityCredential, $PartyA, $IdentifierType, $Remarks, $QueueTimeOutURL, $ResultURL){
-
+ public static function accountBalance($CommandID, $Initiator, $SecurityCredential = null, $PartyA, $IdentifierType, $Remarks, $QueueTimeOutURL, $ResultURL)
+ {
try {
$environment = env("MPESA_ENV");
} catch (\Throwable $th) {
$environment = self::env("MPESA_ENV");
}
- if( $environment =="live"){
+ if($SecurityCredential == null) {
+ $SecurityCredential = generateSecurityCredential();
+ }
+
+ if ($environment =="live") {
$url = 'https://api.safaricom.co.ke/mpesa/accountbalance/v1/query';
$token=self::generateLiveToken();
- }elseif ($environment=="sandbox"){
+ } elseif ($environment=="sandbox") {
$url = 'https://sandbox.safaricom.co.ke/mpesa/accountbalance/v1/query';
$token=self::generateSandBoxToken();
- }else{
+ } else {
return json_encode(["Message"=>"invalid application status"]);
}
@@ -341,7 +374,7 @@ public static function accountBalance($CommandID, $Initiator, $SecurityCredentia
/**
* Use this function to make a transaction status request
* @param $Initiator | The name of Initiator to initiating the request.
- * @param $SecurityCredential | Encrypted password for the initiator to autheticate the transaction request.
+ * @param $SecurityCredential | Optional | Encrypted password for the initiator to autheticate the transaction request, Autogenerated with Environment variables MPESA_PASSWORD & MPESA_PUBLICKEYPATH
* @param $CommandID | Unique command for each transaction type, possible values are: TransactionStatusQuery.
* @param $TransactionID | Organization Receiving the funds.
* @param $PartyA | Organization/MSISDN sending the transaction
@@ -352,21 +385,25 @@ public static function accountBalance($CommandID, $Initiator, $SecurityCredentia
* @param $Occasion | Optional Parameter
* @return mixed|string
*/
- public function transactionStatus($Initiator, $SecurityCredential, $CommandID, $TransactionID, $PartyA, $IdentifierType, $ResultURL, $QueueTimeOutURL, $Remarks, $Occasion){
-
+ public function transactionStatus($Initiator, $SecurityCredential = null, $CommandID, $TransactionID, $PartyA, $IdentifierType, $ResultURL, $QueueTimeOutURL, $Remarks, $Occasion)
+ {
try {
$environment = env("MPESA_ENV");
} catch (\Throwable $th) {
$environment = self::env("MPESA_ENV");
}
-
- if( $environment =="live"){
+
+ if($SecurityCredential == null) {
+ $SecurityCredential = generateSecurityCredential();
+ }
+
+ if ($environment =="live") {
$url = 'https://api.safaricom.co.ke/mpesa/transactionstatus/v1/query';
$token=self::generateLiveToken();
- }elseif ($environment=="sandbox"){
+ } elseif ($environment=="sandbox") {
$url = 'https://sandbox.safaricom.co.ke/mpesa/transactionstatus/v1/query';
$token=self::generateSandBoxToken();
- }else{
+ } else {
return json_encode(["Message"=>"invalid application status"]);
}
@@ -404,7 +441,7 @@ public function transactionStatus($Initiator, $SecurityCredential, $CommandID, $
/**
* Use this function to initiate a B2B request
* @param $Initiator | This is the credential/username used to authenticate the transaction request.
- * @param $SecurityCredential | Encrypted password for the initiator to autheticate the transaction request.
+ * @param $SecurityCredential | Optional | Encrypted password for the initiator to autheticate the transaction request, Autogenerated with Environment variables MPESA_PASSWORD & MPESA_PUBLICKEYPATH.
* @param $Amount | Base64 encoded string of the B2B short code and password, which is encrypted using M-Pesa public key and validates the transaction on M-Pesa Core system.
* @param $PartyA | Organization’s short code initiating the transaction.
* @param $PartyB | Organization’s short code receiving the funds being transacted.
@@ -418,21 +455,25 @@ public function transactionStatus($Initiator, $SecurityCredential, $CommandID, $
* @return mixed|string
*/
- public function b2b($Initiator, $SecurityCredential, $Amount, $PartyA, $PartyB, $Remarks, $QueueTimeOutURL, $ResultURL, $AccountReference, $commandID, $SenderIdentifierType, $RecieverIdentifierType){
-
+ public function b2b($Initiator, $SecurityCredential = null, $Amount, $PartyA, $PartyB, $Remarks, $QueueTimeOutURL, $ResultURL, $AccountReference, $commandID, $SenderIdentifierType, $RecieverIdentifierType)
+ {
try {
$environment = env("MPESA_ENV");
} catch (\Throwable $th) {
$environment = self::env("MPESA_ENV");
}
-
- if( $environment =="live"){
+
+ if($SecurityCredential == null) {
+ $SecurityCredential = generateSecurityCredential();
+ }
+
+ if ($environment =="live") {
$url = 'https://api.safaricom.co.ke/mpesa/b2b/v1/paymentrequest';
$token=self::generateLiveToken();
- }elseif ($environment=="sandbox"){
+ } elseif ($environment=="sandbox") {
$url = 'https://sandbox.safaricom.co.ke/mpesa/b2b/v1/paymentrequest';
$token=self::generateSandBoxToken();
- }else{
+ } else {
return json_encode(["Message"=>"invalid application status"]);
}
$curl = curl_init();
@@ -458,7 +499,6 @@ public function b2b($Initiator, $SecurityCredential, $Amount, $PartyA, $PartyB,
curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);
$curl_response = curl_exec($curl);
return $curl_response;
-
}
/**
@@ -476,27 +516,27 @@ public function b2b($Initiator, $SecurityCredential, $Amount, $PartyA, $PartyB,
* @param $Remark | Remarks
* @return mixed|string
*/
- public function STKPushSimulation($BusinessShortCode, $LipaNaMpesaPasskey, $TransactionType, $Amount, $PartyA, $PartyB, $PhoneNumber, $CallBackURL, $AccountReference, $TransactionDesc, $Remark){
-
+ public function STKPushSimulation($BusinessShortCode, $LipaNaMpesaPasskey, $TransactionType, $Amount, $PartyA, $PartyB, $PhoneNumber, $CallBackURL, $AccountReference, $TransactionDesc, $Remark)
+ {
try {
$environment = env("MPESA_ENV");
} catch (\Throwable $th) {
$environment = self::env("MPESA_ENV");
}
-
- if( $environment =="live"){
+
+ if ($environment =="live") {
$url = 'https://api.safaricom.co.ke/mpesa/stkpush/v1/processrequest';
$token = self::generateLiveToken();
- }elseif ($environment=="sandbox"){
+ } elseif ($environment=="sandbox") {
$url = 'https://sandbox.safaricom.co.ke/mpesa/stkpush/v1/processrequest';
$token = self::generateSandBoxToken();
- }else{
+ } else {
return json_encode(["Message"=>"invalid application status"]);
}
- $timestamp='20'.date( "ymdhis");
+ $timestamp='20'.date("ymdhis");
$password=base64_encode($BusinessShortCode.$LipaNaMpesaPasskey.$timestamp);
$curl = curl_init();
@@ -526,8 +566,6 @@ public function STKPushSimulation($BusinessShortCode, $LipaNaMpesaPasskey, $Tran
curl_setopt($curl, CURLOPT_HEADER, false);
$curl_response=curl_exec($curl);
return $curl_response;
-
-
}
@@ -539,21 +577,21 @@ public function STKPushSimulation($BusinessShortCode, $LipaNaMpesaPasskey, $Tran
* @param $timestamp | Timestamp
* @return mixed|string
*/
- public static function STKPushQuery($environment, $checkoutRequestID, $businessShortCode, $password, $timestamp){
-
+ public static function STKPushQuery($environment, $checkoutRequestID, $businessShortCode, $password, $timestamp)
+ {
try {
$environment = env("MPESA_ENV");
} catch (\Throwable $th) {
$environment = self::env("MPESA_ENV");
}
-
- if( $environment =="live"){
+
+ if ($environment =="live") {
$url = 'https://api.safaricom.co.ke/mpesa/stkpushquery/v1/query';
$token=self::generateLiveToken();
- }elseif ($environment=="sandbox"){
+ } elseif ($environment=="sandbox") {
$url = 'https://sandbox.safaricom.co.ke/mpesa/stkpushquery/v1/query';
$token=self::generateSandBoxToken();
- }else{
+ } else {
return json_encode(["Message"=>"invalid application status"]);
}
@@ -608,10 +646,9 @@ public function finishTransaction($status = true)
/**
*Use this function to get callback data posted in callback routes
*/
- public function getDataFromCallback(){
+ public function getDataFromCallback()
+ {
$callbackJSONData=file_get_contents('php://input');
return $callbackJSONData;
}
-
-
}