Completed
Push — master ( 592bf8...840982 )
by Paul
01:11
created

Cbs::generateInvoice()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 31
rs 9.424
c 0
b 0
f 0
cc 4
nc 4
nop 1
1
<?php
2
/*
3
 * This file is part of the Laravel Cbs package.
4
 *
5
 * (c) Edward Paul <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace Infinitypaul\Cbs;
12
13
use GuzzleHttp\Client;
14
use Illuminate\Support\Facades\Config;
15
use Illuminate\Support\Facades\Log;
16
use Infinitypaul\Cbs\Exceptions\InvalidPostException;
17
use Infinitypaul\Cbs\Exceptions\NotSetException;
18
19
class Cbs
20
{
21
    /**
22
     * Issue Secret Key from CBS.
23
     * @var string
24
     */
25
    protected $secretKey;
26
27
    /**
28
     * Issue Client ID from CBS.
29
     * @var string
30
     */
31
    protected $clientId;
32
33
    /**
34
     * Issue URL from CBS.
35
     * @var string
36
     */
37
    protected $baseUrl;
38
39
    /**
40
     * Issue Revenue Head from CBS.
41
     * @var int
42
     */
43
    protected $revenueHeads;
44
45
    /**
46
     * Issue Category ID from CBS Admin.
47
     * @var int
48
     */
49
    protected $categoryId;
50
51
    /**
52
     *  Response from requests made to CBS.
53
     * @var mixed
54
     */
55
    protected $response;
56
57
    /**
58
     *  Hashed Key.
59
     * @var mixed
60
     */
61
    protected $signature;
62
63
    /**
64
     * Payment Url - CBS payment page.
65
     * @var string
66
     */
67
    protected $url;
68
69
    /**
70
     *  Response from CBS.
71
     * @var mixed
72
     */
73
    protected $invoice = [];
74
75
    /**
76
     * Instance of Client.
77
     * @var Client
78
     */
79
    protected $client;
80
81
    public function __construct()
82
    {
83
        $this->setUrl();
84
        $this->setConstant();
85
        $this->checkConstant();
86
    }
87
88
    public function setUrl()
89
    {
90
        $this->baseUrl = Config::get('mode') === 'test' ? Config::get('cbs.testUrl') : Config::get('cbs.liveURL');
91
    }
92
93
    /**
94
     * Get secret key from CBS config file.
95
     */
96
    public function setConstant()
97
    {
98
        $this->secretKey = Config::get('cbs.secret');
99
        $this->clientId = Config::get('cbs.clientId');
100
        $this->revenueHeads = Config::get('cbs.revenueHead');
101
        $this->categoryId = Config::get('cbs.categoryId');
102
    }
103
104
    protected function checkConstant()
105
    {
106
        if (! $this->revenueHeads) {
107
            throw new NotSetException('Set Your Revenue Head');
108
        }
109
        if (! $this->clientId) {
110
            throw new NotSetException('Set Your Client Id');
111
        }
112
        if (! $this->secretKey) {
113
            throw new NotSetException('Set Your Secret Id');
114
        }
115
        if (! $this->categoryId) {
116
            throw new NotSetException('Set Your Category Id');
117
        }
118
        if (! $this->baseUrl) {
119
            throw new NotSetException('Set Your Test and Live Base Url');
120
        }
121
    }
122
123
    protected function setSignature($amount, $callback)
124
    {
125
        $amount = number_format((float) $amount, 2, '.', '');
126
        $string = $this->revenueHeads.$amount.$callback.$this->clientId;
127
        //dd($string);
128
        $this->signature = base64_encode(hash_hmac('sha256', $string, $this->secretKey, true));
129
        $this->setRequestOptions();
130
    }
131
132
    /**
133
     * Set options for making the Client request.
134
     */
135
    private function setRequestOptions()
136
    {
137
        $this->client = new Client([
138
            'base_uri' => $this->baseUrl,
139
            'headers' => [
140
                'Content-Type' => 'application/json',
141
                'Accept' => 'application/json',
142
                'CLIENTID' => $this->clientId,
143
                'Signature' => $this->signature,
144
            ],
145
        ]);
146
    }
147
148
    /**
149
     * @param $relativeUri
150
     * @param string $method
151
     * @param array $body
152
     *
153
     * @return \Infinitypaul\Cbs\Cbs
154
     * @throws \Infinitypaul\Cbs\Exceptions\NotSetException
155
     */
156
    private function setHttpResponse($relativeUri, $method, $body = [])
157
    {
158
        if (is_null($method)) {
159
            throw new NotSetException('Empty Method Not Allowed');
160
        }
161
        $this->response = $this->client->{strtolower($method)}(
162
            $this->baseUrl.$relativeUri,
163
            ['body' => json_encode($body)]
164
        );
165
166
        return $this;
167
    }
168
169
    private function getResponse()
170
    {
171
        return json_decode($this->response->getBody(), true);
172
    }
173
174
175
    protected function setUser($data){
176
177
        if (isset($data['payerID'])) {
178
            $user = ['PayerId' => $data['payerID']];
179
        } else {
180
            $user = [
181
                'Recipient' => $data['full_name'],
182
                'Email' => $data['email'],
183
                'Address' => $data['address'],
184
                'PhoneNumber' => $data['mobile_number'],
185
                'TaxPayerIdentificationNumber' => $data['tin'],
186
            ];
187
        }
188
        return [
189
            'TaxEntity' => $user,
190
            'Amount' => intval($data['amount']),
191
            'InvoiceDescription' => $data['description'],
192
            'CategoryId' => $this->categoryId,
193
        ];
194
    }
195
196
    /**
197
     * Initiate a payment request to Cbs
198
     * Included the option to pass the payload to this method for situations
199
     * when the payload is built on the fly (not passed to the controller from a view).
200
     *
201
     * @param array $data
202
     *
203
     * @return \Infinitypaul\Cbs\Cbs
204
     * @throws \Infinitypaul\Cbs\Exceptions\NotSetException
205
     */
206
    public function generateInvoice($data)
207
    {
208
        if (empty($data)) {
209
            $TaxEntityInvoice = $this->setUser(request()->toArray());
210
            $callback = request()->callback;
211
            $quantity = request()->quantity;
212
            $ExternalRefNumber = request()->has('externalRefNumber') ? request()->externalRefNumber : null;
213
        } else {
214
            $TaxEntityInvoice = $this->setUser($data);
215
            $callback = $data['callback'];
216
            $quantity = $data['quantity'];
217
            $ExternalRefNumber = isset($data['externalRefNumber']) ? $data['externalRefNumber'] : null;
218
        }
219
220
        $data = [
221
            'RevenueHeadId' => $this->revenueHeads,
222
            'TaxEntityInvoice' => $TaxEntityInvoice,
223
            'CallBackURL' => $callback,
224
            'RequestReference' => ReferenceNumber::getHashedToken(),
225
            'Quantity' => $quantity,
226
            'ExternalRefNumber' => $ExternalRefNumber
227
228
        ];
229
230
        $this->setSignature($TaxEntityInvoice['Amount'], $callback);
231
        array_filter($data);
232
233
        $this->setHttpResponse('/api/v1/invoice/create', 'POST', $data);
234
235
        return $this;
236
    }
237
238
    /**
239
     * Set the invoice data from the callback response.
240
     *
241
     * @param array $data
242
     *
243
     * @return \Infinitypaul\Cbs\Cbs
244
     * @throws \Infinitypaul\Cbs\Exceptions\NotSetException
245
     */
246
    public function setInvoice($data = [])
247
    {
248
        $this->generateInvoice($data);
249
        $this->invoice = $this->getResponse();
250
251
        return $this;
252
    }
253
254
    /**
255
     * Get the invoice data from the callback response.
256
     */
257
    public function getData()
258
    {
259
        return $this->invoice;
260
    }
261
262
    /**
263
     * Get the invoice payment url from the callback response.
264
     */
265
    public function redirectNow()
266
    {
267
        return redirect($this->invoice['ResponseObject']['PaymentURL']);
268
    }
269
270
    /**
271
     * Compute Mac Address.
272
     *
273
     * @param $invoiceNumber
274
     * @param $paymentRef
275
     * @param $amount
276
     *
277
     *
278
     * @param $RequestReference
279
     *
280
     * @return string
281
     */
282
    protected function computeMac($invoiceNumber, $paymentRef, $amount, $RequestReference)
283
    {
284
        $amount = number_format((float) $amount, 2, '.', '');
285
        $string = $invoiceNumber.$paymentRef.$amount.$RequestReference;
286
        return base64_encode(hash_hmac('sha256', $string, $this->secretKey, true));
287
    }
288
289
    /**
290
     * Get Payment details if the transaction was verified successfully.
291
     *
292
     * @throws \Infinitypaul\Cbs\Exceptions\InvalidPostException
293
     */
294
    public function getPaymentData()
295
    {
296
        $mac = $this->computeMac(request()->InvoiceNumber, request()->PaymentRef, request()->AmountPaid, request()->RequestReference);
297
        if ($mac != request()->Mac) {
298
            throw new InvalidPostException('Invalid Call');
299
        } else {
300
            return response()->json(request()->toArray());
0 ignored issues
show
Bug introduced by
The method json does only exist in Illuminate\Contracts\Routing\ResponseFactory, but not in Illuminate\Http\Response.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
301
        }
302
    }
303
}
304