Issues (8)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/Daraja.php (8 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Savannabits\Daraja;
4
5
use Symfony\Component\Dotenv\Dotenv;
6
7
class Daraja
8
{
9
10
    private  $consumer_key, $consumer_secret, $access_token, $environment;
11
    /**
12
     * Define env method similar to laravel's
13
     *
14
     * @param String $env_param | Environment Param Name
15
     *
16
     * @return array|false|string
17
     */
18
    public static function env($env_param){
19
20
        $dotenv = new Dotenv();
21
22
        $dotenv->load('../.env');
23
24
        $env = getenv($env_param);
25
26
        return $env;
27
    }
28
29
    /**
30
     * This is used to return an instance of the class especially when it is being used statically.
31
     * @return Daraja
32
     */
33
    public static function getInstance() {
34
        return new self;
35
    }
36
37
    /**
38
     * Generate instance's member credentials during runtime which will be used to generate tokens and make other calls
39
     * @param $mpesa_consumer_key
40
     * @param $mpesa_consumer_secret
41
     * @return Daraja
42
     */
43
    public function setCredentials($mpesa_consumer_key, $mpesa_consumer_secret, $mpesa_env='sandbox') {
44
        if (!strlen($mpesa_consumer_key)|| !strlen($mpesa_consumer_secret)){
45
            die("Please provide a valid consumer key and secret as provided by safaricom");
46
        }
47
        if ($mpesa_env!=='sandbox' && $mpesa_env !=='live') {
48
            die('mpesa_env MUST be either sandbox or live');
49
        }
50
        $this->consumer_key = $mpesa_consumer_key;
51
        $this->consumer_secret = $mpesa_consumer_secret;
52
        $this->environment = $mpesa_env;
53
        return $this;
54
    }
55
56
    /**
57
     * This is used to generate tokens for the live environment
58
     * @return mixed
59
     */
60 View Code Duplication
    public function generateLiveToken(){
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
61
        if(!isset($this->consumer_key)||!isset($this->consumer_secret)){
62
            die("please set the consumer key and consumer secret as defined in the documentation. You can use setCredentials() before calling this function.");
63
        }
64
        $consumer_key = $this->consumer_key;
65
        $consumer_secret = $this->consumer_secret;
66
        $url = 'https://api.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials';
67
        $curl = curl_init();
68
        curl_setopt($curl, CURLOPT_URL, $url);
69
        $credentials = base64_encode($consumer_key.':'.$consumer_secret);
70
        curl_setopt($curl, CURLOPT_HTTPHEADER, array('Authorization: Basic '.$credentials)); //setting a custom header
71
        curl_setopt($curl, CURLOPT_HEADER, false);
72
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
73
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
74
        $curl_response = curl_exec($curl);
75
        $this->access_token = optional(json_decode($curl_response))->access_token;
76
        if (!$this->access_token) {
77
            abort(500, "Access token could not be generated.");
78
        }
79
        return $this;
80
    }
81
82
    public function getAccessToken() {
83
        return $this->access_token;
84
    }
85
    /**
86
     * use this function to generate a sandbox token
87
     * @return mixed
88
     */
89 View Code Duplication
    public function generateSandBoxToken(){
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
90
91
        if(!isset($this->consumer_key)||!isset($this->consumer_secret)){
92
            die("please set the consumer key and consumer secret as defined in the documentation. You can use setCredentials() before calling this function.");
93
        }
94
        $consumer_key = $this->consumer_key;
95
        $consumer_secret = $this->consumer_secret;
96
        $url = 'https://sandbox.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials';
97
        $curl = curl_init();
98
        curl_setopt($curl, CURLOPT_URL, $url);
99
        $credentials = base64_encode($consumer_key.':'.$consumer_secret);
100
        curl_setopt($curl, CURLOPT_HTTPHEADER, array('Authorization: Basic '.$credentials)); //setting a custom header
101
        curl_setopt($curl, CURLOPT_HEADER, false);
102
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
103
104
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
105
106
        $curl_response = curl_exec($curl);
107
108
        $this->access_token = optional(json_decode($curl_response))->access_token;
109
        if (!$this->access_token) {
110
            abort(500, "Access token could not be generated.");
111
        }
112
        return $this;
113
    }
114
115
    /**
116
     * Register Validation and Confirmation Callbacks
117
     * @param $shortCode | The MPESA Short Code
118
     * @param string $confirmationURL | Confirmation Callback URL
119
     * @param string|null $validationURL | Validation Callback URL
120
     * @param string $responseType | Default Response type in case the validation URL is unreachable or is undefined. Either Cancelled or Completed as per the safaricom documentation
121
     * @return false|mixed|string
122
     */
123 View Code Duplication
    public function registerCallbacks($shortCode,$confirmationURL, $validationURL=null, $responseType="Cancelled") {
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
124
        $environment = $this->environment;
125
        if( $environment =="live"){
126
            $url = "https://api.safaricom.co.ke/mpesa/c2b/v1/registerurl";
127
            $this->generateLiveToken();
128
        }elseif ($environment=="sandbox"){
129
            $url = "https://sandbox.safaricom.co.ke/mpesa/c2b/v1/registerurl";
130
            $this->generateSandBoxToken();
131
        }else{
132
            return json_encode(["Message"=>"Invalid App environment. Please set it via setCredentials() to either live or sandbox."]);
133
        }
134
135
        $token = $this->getAccessToken();
136
        $curl = curl_init();
137
138
        curl_setopt($curl, CURLOPT_URL, $url);
139
        curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type:application/json','Authorization:Bearer '.$token));
140
141
142
        $curl_post_data = array(
143
            "ValidationURL" => $validationURL,
144
            "ConfirmationURL" => $confirmationURL,
145
            "ResponseType" => $responseType,
146
            "ShortCode" => $shortCode
147
        );
148
149
        $data_string = json_encode($curl_post_data);
150
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
151
        curl_setopt($curl, CURLOPT_POST, true);
152
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);
153
        curl_setopt($curl, CURLOPT_HEADER, false);
154
        $curl_response = curl_exec($curl);
155
        return json_decode($curl_response);
156
    }
157
158
    /**
159
     * Generate an encrypted security credential from the initiator password on either live or sandbox env.
160
     * @param string $initiatorPassword
161
     * @param string $env live|sandbox
162
     */
163
    public function encryptInitiatorPassword($initiatorPassword, $env="sandbox") {
164
        if (!in_array($env,["live", "sandbox"])) {
165
            throw new \Exception("Environment must be either live or sandbox");
166
        }
167
        $publicKeyFile = config('daraja.mpesa.cert_path')."/".config('daraja.mpesa.'.$env.'_cert_name');
168
        $publicKey = $this->preparePublicKey($publicKeyFile);
169
        openssl_public_encrypt($initiatorPassword, $encrypted,$publicKey, OPENSSL_PKCS1_PADDING);
170
        return base64_encode($encrypted);
171
    }
172
173
    public function preparePublicKey($publicKeyFile) {
174
        $pkey = file_get_contents($publicKeyFile);
175
        $pkey = str_replace(["\r", "\n"],"", $pkey);
176
        $pkey = str_replace(["-----BEGIN CERTIFICATE-----"],"-----BEGIN CERTIFICATE-----\n", $pkey);
177
        $final = str_replace(["-----END CERTIFICATE-----"],"\n-----END CERTIFICATE-----", $pkey);
178
        return $final;
179
    }
180
181
    /**
182
     * Use this function to initiate a reversal request. This is an abstracted function that takes care of SecurityCredential Generation
183
     * @param $Initiator | The name of Initiator - Username of user initiating the transaction
184
     * @param $InitiatorPassword |    Encrypted Initiator Password / security credential
185
     * @param $TransactionID | Unique Id received with every transaction response.
186
     * @param $Amount | Amount
187
     * @param $ReceiverParty | Organization /MSISDN sending the transaction
188
     * @param $ResultURL | The path that stores information of transaction
189
     * @param $QueueTimeOutURL | The path that stores information of time out transaction
190
     * @param $Remarks | Comments that are sent along with the transaction.
191
     * @param $Occasion |    Optional Parameter
192
     * @return mixed|string
193
     * @throws \Exception
194
     */
195
    public function reverseTransaction($Initiator, $InitiatorPassword, $TransactionID, $Amount, $ReceiverParty, $ResultURL, $QueueTimeOutURL, $Remarks, $Occasion, $ReceiverIdentifierType=11) {
196
//        $SecurityCredential = $this->encryptInitiatorPassword($InitiatorPassword,$this->environment);
197
        $CommandID = 'TransactionReversal';
198
        return $this->reversal($CommandID,$Initiator,$InitiatorPassword,$TransactionID,$Amount,$ReceiverParty,$ReceiverIdentifierType,$ResultURL,$QueueTimeOutURL,$Remarks,$Occasion);
199
    }
200
201
    /**
202
     * Use this function to initiate a transaciton status query
203
     * @param $Initiator | The username of the user initiating the transaction. This is the credential/username used to authenticate the transaction request
204
     * @param $InitiatorPassword | Encrypted Security Credential. see daraja docs on how to encrypt
205
     * @param $TransactionID | Mpesa confirmation code of the trasaction whose query we are checking
206
     * @param $PartyA | The shortcode or msisdn of the organization that is receiving the transaction
207
     * @param $ResultURL | Where will the result be sent to
208
     * @param $QueueTimeOutURL | In case of a timeout, this url will be called.
209
     * @param $Remarks |Comments sent along with the transaction
210
     * @param $Occasion | Optional Parameter.
211
     * @param int $IdentifierType | The type of organization receiving the transaction: 1 = MSISDN, 2 = TILL, 4 = Org shortcode
212
     * @return mixed|string
213
     * @throws \Exception
214
     */
215
    public function checkTransactionStatus($Initiator, $InitiatorPassword, $TransactionID, $PartyA, $ResultURL, $QueueTimeOutURL, $Remarks, $Occasion, $IdentifierType=4) {
216
//        $SecurityCredential = $this->encryptInitiatorPassword($InitiatorPassword,$this->environment);
217
        $CommandID = 'TransactionStatusQuery';
218
        return $this->transactionStatus($Initiator, $InitiatorPassword, $CommandID, $TransactionID, $PartyA, $IdentifierType, $ResultURL, $QueueTimeOutURL, $Remarks, $Occasion);
219
    }
220
    /**
221
     * Use this function to initiate a reversal request. This is the lowest level function that can change even the Organization Id Type.
222
     * @param $CommandID | Takes only 'TransactionReversal' Command id
223
     * @param $Initiator | The name of Initiator to initiating  the request
224
     * @param $SecurityCredential | 	Encrypted Credential of user getting transaction amount
225
     * @param $TransactionID | Unique Id received with every transaction response.
226
     * @param $Amount | Amount
227
     * @param $ReceiverParty | Organization /MSISDN sending the transaction
228
     * @param $RecieverIdentifierType | Type of organization receiving the transaction
229
     * @param $ResultURL | The path that stores information of transaction
230
     * @param $QueueTimeOutURL | The path that stores information of time out transaction
231
     * @param $Remarks | Comments that are sent along with the transaction.
232
     * @param $Occasion | 	Optional Parameter
233
     * @return mixed|string
234
     */
235 View Code Duplication
    private function reversal($CommandID, $Initiator, $SecurityCredential, $TransactionID, $Amount, $ReceiverParty, $RecieverIdentifierType, $ResultURL, $QueueTimeOutURL, $Remarks, $Occasion){
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
236
237
        $environment = $this->environment;
238
        if( $environment =="live"){
239
            $url = 'https://api.safaricom.co.ke/mpesa/reversal/v1/request';
240
            $this->generateLiveToken();
241
        }elseif ($environment=="sandbox"){
242
            $url = 'https://sandbox.safaricom.co.ke/mpesa/reversal/v1/request';
243
            $this->generateSandBoxToken();
244
        }else{
245
            return json_encode(["Message"=>"invalid application status. Please set mpesa_env credential as either live or sandbox."]);
246
        }
247
248
        $token = $this->getAccessToken();
249
250
        $curl = curl_init();
251
252
        curl_setopt($curl, CURLOPT_URL, $url);
253
        curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type:application/json','Authorization:Bearer '.$token));
254
255
        $curl_post_data = array(
256
            'CommandID' => $CommandID,
257
            'Initiator' => $Initiator,
258
            'SecurityCredential' => $SecurityCredential,
259
            'TransactionID' => $TransactionID,
260
            'Amount' => $Amount,
261
            'ReceiverParty' => $ReceiverParty,
262
            'RecieverIdentifierType' => $RecieverIdentifierType,
263
            'ResultURL' => $ResultURL,
264
            'QueueTimeOutURL' => $QueueTimeOutURL,
265
            'Remarks' => $Remarks,
266
            'Occasion' => $Occasion
267
        );
268
269
        $data_string = json_encode($curl_post_data);
270
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
271
        curl_setopt($curl, CURLOPT_POST, true);
272
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);
273
        curl_setopt($curl, CURLOPT_HEADER, false);
274
        $curl_response = curl_exec($curl);
275
        return json_decode($curl_response);
276
    }
277
278
    /**
279
     * @param $InitiatorName | 	This is the credential/username used to authenticate the transaction request.
280
     * @param $SecurityCredential | Encrypted password for the initiator to autheticate the transaction request
281
     * @param $CommandID | Unique command for each transaction type e.g. SalaryPayment, BusinessPayment, PromotionPayment
282
     * @param $Amount | The amount being transacted
283
     * @param $PartyA | Organization’s shortcode initiating the transaction.
284
     * @param $PartyB | Phone number receiving the transaction
285
     * @param $Remarks | Comments that are sent along with the transaction.
286
     * @param $QueueTimeOutURL | The timeout end-point that receives a timeout response.
287
     * @param $ResultURL | The end-point that receives the response of the transaction
288
     * @param $Occasion | 	Optional
289
     * @return string
290
     */
291
    public function b2c($InitiatorName, $SecurityCredential, $CommandID, $Amount, $PartyA, $PartyB, $Remarks, $QueueTimeOutURL, $ResultURL, $Occasion){
292
293
        $environment = $this->environment;
294
295
        if( $environment =="live"){
296
            $url = 'https://api.safaricom.co.ke/mpesa/b2c/v1/paymentrequest';
297
            $token=self::generateLiveToken();
298
        } elseif ($environment=="sandbox"){
299
            $url = 'https://sandbox.safaricom.co.ke/mpesa/b2c/v1/paymentrequest';
300
            $token=self::generateSandBoxToken();
301
        }else{
302
            return json_encode(["Message"=>"invalid application status. Please set mpesa_env to either live or sandbox via setCredentials()"]);
303
        }
304
305
306
        $curl = curl_init();
307
        curl_setopt($curl, CURLOPT_URL, $url);
308
        curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type:application/json','Authorization:Bearer '.$token));
309
310
311
        $curl_post_data = array(
312
            'InitiatorName' => $InitiatorName,
313
            'SecurityCredential' => $SecurityCredential,
314
            'CommandID' => $CommandID ,
315
            'Amount' => $Amount,
316
            'PartyA' => $PartyA ,
317
            'PartyB' => $PartyB,
318
            'Remarks' => $Remarks,
319
            'QueueTimeOutURL' => $QueueTimeOutURL,
320
            'ResultURL' => $ResultURL,
321
            'Occasion' => $Occasion
322
        );
323
324
        $data_string = json_encode($curl_post_data);
325
326
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
327
        curl_setopt($curl, CURLOPT_POST, true);
328
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);
329
330
        $curl_response = curl_exec($curl);
331
332
        return json_encode($curl_response);
333
334
    }
335
    /**
336
     * Use this function to initiate a C2B transaction
337
     * @param $ShortCode | 6 digit M-Pesa Till Number or PayBill Number
338
     * @param $CommandID | Unique command for each transaction type.
339
     * @param $Amount | The amount been transacted.
340
     * @param $Msisdn | MSISDN (phone number) sending the transaction, start with country code without the plus(+) sign.
341
     * @param $BillRefNumber | 	Bill Reference Number (Optional).
342
     * @return mixed|string
343
     */
344 View Code Duplication
    public function c2b($ShortCode, $CommandID, $Amount, $Msisdn, $BillRefNumber ){
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
345
        $environment = $this->environment;
346
        if( $environment =="live"){
347
            $url = 'https://api.safaricom.co.ke/mpesa/c2b/v1/simulate';
348
            $this->generateLiveToken();
349
        }elseif ($environment=="sandbox"){
350
            $url = 'https://sandbox.safaricom.co.ke/mpesa/c2b/v1/simulate';
351
            $this->generateSandBoxToken();
352
        }else{
353
            return json_encode(["Message"=>"invalid application status. Please set mpesa_env to either sandbox or live"]);
354
        }
355
356
        $token = $this->getAccessToken();
357
        $curl = curl_init();
358
        curl_setopt($curl, CURLOPT_URL, $url);
359
        curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type:application/json','Authorization:Bearer '.$token));
360
361
        $curl_post_data = array(
362
            'ShortCode' => $ShortCode,
363
            'CommandID' => $CommandID,
364
            'Amount' => $Amount,
365
            'Msisdn' => $Msisdn,
366
            'BillRefNumber' => $BillRefNumber
367
        );
368
369
        $data_string = json_encode($curl_post_data);
370
371
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
372
        curl_setopt($curl, CURLOPT_POST, true);
373
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);
374
        curl_setopt($curl, CURLOPT_HEADER, false);
375
        $curl_response = curl_exec($curl);
376
        return $curl_response;
377
    }
378
379
380
    /**
381
     * Use this to initiate a balance inquiry request
382
     * @param $CommandID | A unique command passed to the M-Pesa system.
383
     * @param $Initiator | 	This is the credential/username used to authenticate the transaction request.
384
     * @param $SecurityCredential | Encrypted password for the initiator to autheticate the transaction request
385
     * @param $PartyA | Type of organization receiving the transaction
386
     * @param $IdentifierType |Type of organization receiving the transaction
387
     * @param $Remarks | Comments that are sent along with the transaction.
388
     * @param $QueueTimeOutURL | The path that stores information of time out transaction
389
     * @param $ResultURL | 	The path that stores information of transaction
390
     * @return mixed|string
391
     */
392
    public function accountBalance($CommandID, $Initiator, $SecurityCredential, $PartyA, $IdentifierType, $Remarks, $QueueTimeOutURL, $ResultURL){
393
394
        $environment = $this->environment;
395
        if( $environment =="live"){
396
            $url = 'https://api.safaricom.co.ke/mpesa/accountbalance/v1/query';
397
            $this->generateLiveToken();
398
        }elseif ($environment=="sandbox"){
399
            $url = 'https://sandbox.safaricom.co.ke/mpesa/accountbalance/v1/query';
400
            $this->generateSandBoxToken();
401
        }else{
402
            return json_encode(["Message"=>"invalid application environment"]);
403
        }
404
405
        $token = $this->getAccessToken();
406
        $curl = curl_init();
407
        curl_setopt($curl, CURLOPT_URL, $url);
408
        curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type:application/json','Authorization:Bearer '.$token)); //setting custom header
409
410
411
        $curl_post_data = array(
412
            'CommandID' => $CommandID,
413
            'Initiator' => $Initiator,
414
            'SecurityCredential' => $SecurityCredential,
415
            'PartyA' => $PartyA,
416
            'IdentifierType' => $IdentifierType,
417
            'Remarks' => $Remarks,
418
            'QueueTimeOutURL' => $QueueTimeOutURL,
419
            'ResultURL' => $ResultURL
420
        );
421
422
        $data_string = json_encode($curl_post_data);
423
424
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
425
        curl_setopt($curl, CURLOPT_POST, true);
426
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);
427
        curl_setopt($curl, CURLOPT_HEADER, false);
428
        $curl_response = curl_exec($curl);
429
        return $curl_response;
430
    }
431
432
    /**
433
     * Use this function to make a transaction status request
434
     * @param $Initiator | The name of Initiator to initiating the request.
435
     * @param $SecurityCredential | 	Encrypted password for the initiator to autheticate the transaction request.
436
     * @param $CommandID | Unique command for each transaction type, possible values are: TransactionStatusQuery.
437
     * @param $TransactionID | Organization Receiving the funds.
438
     * @param $PartyA | Organization/MSISDN sending the transaction
439
     * @param $IdentifierType | Type of organization receiving the transaction
440
     * @param $ResultURL | The path that stores information of transaction
441
     * @param $QueueTimeOutURL | The path that stores information of time out transaction
442
     * @param $Remarks | 	Comments that are sent along with the transaction
443
     * @param $Occasion | 	Optional Parameter
444
     * @return mixed|string
445
     */
446 View Code Duplication
    private function transactionStatus($Initiator, $SecurityCredential, $CommandID, $TransactionID, $PartyA, $IdentifierType, $ResultURL, $QueueTimeOutURL, $Remarks, $Occasion){
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
447
448
        $environment = $this->environment;
449
450
        if( $environment =="live"){
451
            $url = 'https://api.safaricom.co.ke/mpesa/transactionstatus/v1/query';
452
            $this->generateLiveToken();
453
        }elseif ($environment=="sandbox"){
454
            $url = 'https://sandbox.safaricom.co.ke/mpesa/transactionstatus/v1/query';
455
            $this->generateSandBoxToken();
456
        }else{
457
            return json_encode(["Message"=>"invalid application status"]);
458
        }
459
460
        $token = $this->getAccessToken();
461
        $curl = curl_init();
462
        curl_setopt($curl, CURLOPT_URL, $url);
463
        curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type:application/json','Authorization:Bearer '.$token)); //setting custom header
464
465
466
        $curl_post_data = array(
467
            'Initiator' => $Initiator,
468
            'SecurityCredential' => $SecurityCredential,
469
            'CommandID' => $CommandID,
470
            'TransactionID' => $TransactionID,
471
            'PartyA' => $PartyA,
472
            'IdentifierType' => $IdentifierType,
473
            'ResultURL' => $ResultURL,
474
            'QueueTimeOutURL' => $QueueTimeOutURL,
475
            'Remarks' => $Remarks,
476
            'Occasion' => $Occasion
477
        );
478
479
        $data_string = json_encode($curl_post_data);
480
481
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
482
        curl_setopt($curl, CURLOPT_POST, true);
483
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);
484
        curl_setopt($curl, CURLOPT_HEADER, false);
485
        $curl_response = curl_exec($curl);
486
487
488
        return $curl_response;
489
    }
490
491
492
    /**
493
     * Use this function to initiate a B2B request
494
     * @param $Initiator | This is the credential/username used to authenticate the transaction request.
495
     * @param $SecurityCredential | Encrypted password for the initiator to autheticate the transaction request.
496
     * @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.
497
     * @param $PartyA | Organization’s short code initiating the transaction.
498
     * @param $PartyB | Organization’s short code receiving the funds being transacted.
499
     * @param $Remarks | Comments that are sent along with the transaction.
500
     * @param $QueueTimeOutURL | The path that stores information of time out transactions.it should be properly validated to make sure that it contains the port, URI and domain name or publicly available IP.
501
     * @param $ResultURL | The path that receives results from M-Pesa it should be properly validated to make sure that it contains the port, URI and domain name or publicly available IP.
502
     * @param $AccountReference | Account Reference mandatory for “BusinessPaybill” CommandID.
503
     * @param $commandID | Unique command for each transaction type, possible values are: BusinessPayBill, MerchantToMerchantTransfer, MerchantTransferFromMerchantToWorking, MerchantServicesMMFAccountTransfer, AgencyFloatAdvance
504
     * @param $SenderIdentifierType | Type of organization sending the transaction.
505
     * @param $RecieverIdentifierType | Type of organization receiving the funds being transacted.
506
507
     * @return mixed|string
508
     */
509
    public function b2b($Initiator, $SecurityCredential, $Amount, $PartyA, $PartyB, $Remarks, $QueueTimeOutURL, $ResultURL, $AccountReference, $commandID, $SenderIdentifierType, $RecieverIdentifierType){
510
511
        $environment = $this->environment;
512
513
        if( $environment =="live"){
514
            $url = 'https://api.safaricom.co.ke/mpesa/b2b/v1/paymentrequest';
515
            $this->generateLiveToken();
516
        }elseif ($environment=="sandbox"){
517
            $url = 'https://sandbox.safaricom.co.ke/mpesa/b2b/v1/paymentrequest';
518
            $this->generateSandBoxToken();
519
        }else{
520
            return json_encode(["Message"=>"invalid application status"]);
521
        }
522
523
        $token = $this->getAccessToken();
524
525
        $curl = curl_init();
526
        curl_setopt($curl, CURLOPT_URL, $url);
527
        curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type:application/json','Authorization:Bearer '.$token)); //setting custom header
528
        $curl_post_data = array(
529
            'Initiator' => $Initiator,
530
            'SecurityCredential' => $SecurityCredential,
531
            'CommandID' => $commandID,
532
            'SenderIdentifierType' => $SenderIdentifierType,
533
            'RecieverIdentifierType' => $RecieverIdentifierType,
534
            'Amount' => $Amount,
535
            'PartyA' => $PartyA,
536
            'PartyB' => $PartyB,
537
            'AccountReference' => $AccountReference,
538
            'Remarks' => $Remarks,
539
            'QueueTimeOutURL' => $QueueTimeOutURL,
540
            'ResultURL' => $ResultURL
541
        );
542
        $data_string = json_encode($curl_post_data);
543
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
544
        curl_setopt($curl, CURLOPT_POST, true);
545
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);
546
        $curl_response = curl_exec($curl);
547
        return $curl_response;
548
549
    }
550
551
    /**
552
     * Use this function to initiate an STKPush Simulation
553
     * @param $BusinessShortCode | The organization shortcode used to receive the transaction.
554
     * @param $LipaNaMpesaPasskey | The password for encrypting the request. This is generated by base64 encoding BusinessShortcode, Passkey and Timestamp.
555
     * @param $TransactionType | The transaction type to be used for this request. Only CustomerPayBillOnline is supported.
556
     * @param $Amount | The amount to be transacted.
557
     * @param $PartyA | The MSISDN sending the funds.
558
     * @param $PartyB | The organization shortcode receiving the funds
559
     * @param $PhoneNumber | The MSISDN sending the funds.
560
     * @param $CallBackURL | The url to where responses from M-Pesa will be sent to.
561
     * @param $AccountReference | Used with M-Pesa PayBills.
562
     * @param $TransactionDesc | A description of the transaction.
563
     * @param $Remark | Remarks
564
     * @return mixed|string
565
     */
566
    public function STKPushSimulation($BusinessShortCode, $LipaNaMpesaPasskey, $TransactionType, $Amount, $PartyA, $PartyB, $PhoneNumber, $CallBackURL, $AccountReference, $TransactionDesc, $Remark){
0 ignored issues
show
The parameter $Remark is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
567
568
        $environment = $this->environment;
569
570
        if( $environment =="live"){
571
            $url = 'https://api.safaricom.co.ke/mpesa/stkpush/v1/processrequest';
572
            $this->generateLiveToken();
573
        }elseif ($environment=="sandbox"){
574
            $url = 'https://sandbox.safaricom.co.ke/mpesa/stkpush/v1/processrequest';
575
            $this->generateSandBoxToken();
576
        }else{
577
            return json_encode(["Message"=>"invalid application status"]);
578
        }
579
580
        $token = $this->getAccessToken();
581
582
        $timestamp= date(    "Ymdhis");
583
        $password=base64_encode($BusinessShortCode.$LipaNaMpesaPasskey.$timestamp);
584
585
        $curl = curl_init();
586
        curl_setopt($curl, CURLOPT_URL, $url);
587
        curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type:application/json','Authorization:Bearer '.$token));
588
589
590
        $curl_post_data = array(
591
            'BusinessShortCode' => $BusinessShortCode,
592
            'Password' => $password,
593
            'Timestamp' => $timestamp,
594
            'TransactionType' => $TransactionType,
595
            'Amount' => $Amount,
596
            'PartyA' => $PartyA,
597
            'PartyB' => $PartyB,
598
            'PhoneNumber' => $PhoneNumber,
599
            'CallBackURL' => $CallBackURL,
600
            'AccountReference' => $AccountReference,
601
            'TransactionDesc' => $TransactionDesc
602
        );
603
604
        $data_string = json_encode($curl_post_data);
605
606
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
607
        curl_setopt($curl, CURLOPT_POST, true);
608
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);
609
        curl_setopt($curl, CURLOPT_HEADER, false);
610
        $curl_response=curl_exec($curl);
611
        return $curl_response;
612
613
    }
614
615
616
    /**
617
     * Use this function to initiate an STKPush Status Query request.
618
     * @param $checkoutRequestID | Checkout RequestID
619
     * @param $businessShortCode | Business Short Code
620
     * @param $password | Password
621
     * @param $timestamp | Timestamp
622
     * @return mixed|string
623
     */
624 View Code Duplication
    public function STKPushQuery($checkoutRequestID, $businessShortCode, $password, $timestamp){
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
625
626
        $environment =$this->environment;
627
628
        if( $environment =="live"){
629
            $url = 'https://api.safaricom.co.ke/mpesa/stkpushquery/v1/query';
630
            $this->generateLiveToken();
631
        }elseif ($environment=="sandbox"){
632
            $url = 'https://sandbox.safaricom.co.ke/mpesa/stkpushquery/v1/query';
633
            $this->generateSandBoxToken();
634
        }else{
635
            return json_encode(["Message"=>"invalid application status"]);
636
        }
637
        $token = $this->getAccessToken();
638
639
        $curl = curl_init();
640
        curl_setopt($curl, CURLOPT_URL, $url);
641
        curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type:application/json','Authorization:Bearer '.$token));
642
643
        $curl_post_data = array(
644
            'BusinessShortCode' => $businessShortCode,
645
            'Password' => $password,
646
            'Timestamp' => $timestamp,
647
            'CheckoutRequestID' => $checkoutRequestID
648
        );
649
650
        $data_string = json_encode($curl_post_data);
651
652
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
653
        curl_setopt($curl, CURLOPT_POST, true);
654
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);
655
        curl_setopt($curl, CURLOPT_HEADER, false);
656
657
        $curl_response = curl_exec($curl);
658
659
        return $curl_response;
660
    }
661
662
    /**
663
     *Use this function to confirm all transactions in callback routes
664
     */
665
    public function finishTransaction($status = true)
666
    {
667
        if ($status === true) {
668
            $resultArray=[
669
                "ResultDesc"=>"Confirmation Service request accepted successfully",
670
                "ResultCode"=>"0"
671
            ];
672
        } else {
673
            $resultArray=[
674
                "ResultDesc"=>"Confirmation Service not accepted",
675
                "ResultCode"=>"1"
676
            ];
677
        }
678
679
        header('Content-Type: application/json');
680
        echo json_encode($resultArray);
681
    }
682
683
684
    /**
685
     *Use this function to get callback data posted in callback routes
686
     */
687
    public function getDataFromCallback(){
688
        $callbackJSONData=file_get_contents('php://input');
689
        return $callbackJSONData;
690
    }
691
692
}
693