Completed
Push — master ( 8c6699...bb7b9f )
by Stanley
03:14 queued 16s
created

MpesaApiClient::removeLastSlash()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
eloc 1
nc 1
nop 1
1
<?php
2
3
namespace Starnerz\LaravelDaraja;
4
5
use GuzzleHttp\Client;
6
use Illuminate\Support\Facades\Route;
7
use GuzzleHttp\Exception\ClientException;
8
use GuzzleHttp\Exception\ServerException;
9
use Starnerz\LaravelDaraja\Exceptions\MpesaApiRequestException;
10
11
class MpesaApiClient
12
{
13
    /**
14
     * Guzzle client initialization.
15
     *
16
     * @var Client
17
     */
18
    protected $client;
19
20
    /**
21
     * Safaricom MPESA APIs application consumer key.
22
     *
23
     * @var string
24
     */
25
    protected $consumerKey;
26
27
    /**
28
     * Safaricom MPESA APIs application consumer secret.
29
     *
30
     * @var string
31
     */
32
    protected $consumerSecret;
33
34
    /**
35
     * Access token generated by Safaricom MPESA APIs.
36
     *
37
     * @var string
38
     */
39
    protected $accessToken;
40
41
    /**
42
     * Identifier organization Map on Safaricom MPESA APIs.
43
     *
44
     * @var array
45
     */
46
    protected $identifier = [
47
        'msisdn' => '1', // MSISDN
48
        'till' => '2', // Till Number
49
        'paybill' => '4', // Shortcode
50
    ];
51
52
    /**
53
     * Make the initializations required to make calls to the Safaricom MPESA APIs
54
     * and throw the necessary exception if there are any missing required
55
     * configurations.
56
     */
57
    public function __construct()
58
    {
59
        $this->validateConfigurations();
60
61
        $mode = config('laravel-daraja.mode');
62
63
        $options = [
64
            'base_uri' => config('laravel-daraja.base_url.'.$mode),
65
            'verify' => $mode === 'sandbox' ? false : true,
66
        ];
67
68
        $this->client = new Client($options);
69
        $this->consumerKey = config('laravel-daraja.consumer_key');
70
        $this->consumerSecret = config('laravel-daraja.consumer_secret');
71
        $this->getAccessToken();
72
    }
73
74
    /**
75
     * Check if it contains a route name and return full route or
76
     * return the string assuming its a full URL.
77
     *
78
     * @param $urlConfig
79
     * @return string
80
     */
81
    protected function setUrl($urlConfig)
82
    {
83
        return Route::has($urlConfig) ? route($urlConfig) : $urlConfig;
84
    }
85
86
    /**
87
     * Get access token from Safaricom MPESA APIs.
88
     *
89
     * @return mixed
90
     */
91
    protected function getAccessToken()
92
    {
93
        // Set the auth option
94
        $options = [
95
            'auth' => [
96
                $this->consumerKey,
97
                $this->consumerSecret,
98
            ],
99
        ];
100
101
        $accessTokenDetails = $this->call('oauth/v1/generate?grant_type=client_credentials', $options, 'GET');
102
        $this->accessToken = $accessTokenDetails->access_token;
103
    }
104
105
    /**
106
     * Validate configurations.
107
     */
108
    protected function validateConfigurations()
109
    {
110
        // Validate keys
111
        if (empty(config('laravel-daraja.consumer_key'))) {
112
            throw new \InvalidArgumentException('Consumer key has not been set.');
113
        }
114
        if (empty(config('laravel-daraja.consumer_secret'))) {
115
            throw new \InvalidArgumentException('Consumer secret has not been set');
116
        }
117
    }
118
119
    /**
120
     * Generate encrypted security credential.
121
     *
122
     * @param $plaintext
123
     * @return string
124
     * @internal param null|string $password
125
     */
126
    protected function securityCredential($plaintext)
127
    {
128
        $publicKey = file_get_contents(__DIR__.'/../cert.cer');
129
130
        openssl_public_encrypt($plaintext, $encrypted, $publicKey, OPENSSL_PKCS1_PADDING);
131
132
        return base64_encode($encrypted);
133
    }
134
135
    /**
136
     * Make API calls to Safaricom MPESA APIs.
137
     *
138
     * @param string $url
139
     * @param array $options
140
     * @param string $method
141
     * @return mixed
142
     * @throws MpesaApiRequestException
143
     */
144
    protected function call($url, $options = [], $method = 'POST')
145
    {
146
        if (isset($this->accessToken)) {
147
            $options['headers'] = ['Authorization' => 'Bearer '.$this->accessToken];
148
        }
149
150
        try {
151
            $response = $this->client->request($method, $url, $options);
152
153
            return json_decode($response->getBody()->getContents());
154
        } catch (ServerException $e) {
155
            $response = json_decode($e->getResponse()->getBody()->getContents());
156
            if (isset($response->Envelope)) {
157
                $message = 'Safaricom APIs: '.$response->Envelope->Body->Fault->faultstring;
158
                throw new MpesaApiRequestException($message, $e->getCode());
159
            }
160
            throw new MpesaApiRequestException('Safaricom APIs: '.$response->errorMessage, $e->getCode());
161
        } catch (ClientException $e) {
162
            $response = json_decode($e->getResponse()->getBody()->getContents());
163
            throw new MpesaApiRequestException('Safaricom APIs: '
164
                .$response->errorMessage, $e->getCode());
165
        }
166
    }
167
}
168