Passed
Pull Request — master (#218)
by
unknown
02:32
created

JibitClient::getOrderById()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 1
c 1
b 0
f 1
nc 1
nop 1
dl 0
loc 3
rs 10
1
<?php
2
namespace Shetabit\Multipay\Drivers\Jibit;
3
4
class JibitClient
5
{
6
    /**
7
     * Access token
8
     * @var string
9
     */
10
    public $accessToken;
11
12
    /**
13
     * API key
14
     *
15
     * @var string
16
     */
17
    private $apiKey;
18
19
    /**
20
     * Secret key
21
     *
22
     * @var string
23
     */
24
    private $secretKey;
25
26
    /**
27
     * Refresh token
28
     * @var string
29
     */
30
    private $refreshToken;
31
32
    /**
33
     * Cache
34
     *
35
     * @var JibitFileCache
36
     */
37
    private $cache;
38
39
    /**
40
     * Base URL
41
     *
42
     * @var string
43
     */
44
    public $baseUrl;
45
46
47
    public function __construct($apiKey, $secretKey, $baseUrl, $cachePath)
48
    {
49
        $this->baseUrl = $baseUrl;
50
        $this->apiKey = $apiKey;
51
        $this->secretKey = $secretKey;
52
        $this->cache = new JibitFileCache($cachePath, 'jibit', '.cache');
53
    }
54
55
    /**
56
     * Request payment
57
     *
58
     * @param int $amount
59
     * @param string $referenceNumber
60
     * @param string $userIdentifier
61
     * @param string $callbackUrl
62
     * @param string $currency
63
     * @param null $description
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $description is correct as it would always require null to be passed?
Loading history...
64
     * @param $additionalData
65
     * @return bool|mixed|string
66
     * @throws \Shetabit\Multipay\Exceptions\PurchaseFailedException
67
     */
68
    public function paymentRequest($amount, $referenceNumber, $userIdentifier, $callbackUrl, $currency = 'IRR', $description = null, $additionalData = null)
69
    {
70
        $this->generateToken();
71
72
        $data = [
73
            'additionalData' => $additionalData,
74
            'amount' => $amount,
75
            'callbackUrl' => $callbackUrl,
76
            'clientReferenceNumber' => $referenceNumber,
77
            'currency' => $currency,
78
            'userIdentifier' => $userIdentifier,
79
            'description' => $description,
80
        ];
81
82
        return $this->callCurl('/purchases', $data, true);
83
    }
84
85
    /**
86
     *
87
     * Get order by ID
88
     * @param $id
89
     * @return bool|mixed|string
90
     * @throws \Shetabit\Multipay\Exceptions\PurchaseFailedException
91
     */
92
    public function getOrderById($id)
93
    {
94
        return  $this->callCurl('/purchases?purchaseId=' . $id, [], true, 0, 'GET');
95
    }
96
97
    /**
98
     * Generate token
99
     *
100
     * @param bool $isForce
101
     * @return string
102
     * @throws \Shetabit\Multipay\Exceptions\PurchaseFailedException
103
     */
104
    private function generateToken($isForce = false)
105
    {
106
        $this->cache->eraseExpired();
107
108
        if ($isForce === false && $this->cache->isCached('accessToken')) {
109
            return $this->setAccessToken($this->cache->retrieve('accessToken'));
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->setAccessToken($t...etrieve('accessToken')) targeting Shetabit\Multipay\Driver...lient::setAccessToken() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
110
        } elseif ($this->cache->isCached('refreshToken')) {
111
            $refreshToken = $this->refreshTokens();
112
113
            if ($refreshToken !== 'ok') {
114
                return $this->generateNewToken();
115
            }
116
        } else {
117
            return $this->generateNewToken();
118
        }
119
120
        throw new \Shetabit\Multipay\Exceptions\PurchaseFailedException('Token generation encountered an error.');
121
    }
122
123
    private function refreshTokens()
124
    {
125
        $data = [
126
            'accessToken' => str_replace('Bearer ', '', $this->cache->retrieve('accessToken')),
127
            'refreshToken' => $this->cache->retrieve('refreshToken'),
128
        ];
129
130
        $result = $this->callCurl('/tokens/refresh', $data, false);
131
132
        if (empty($result['accessToken'])) {
133
            throw new \Shetabit\Multipay\Exceptions\PurchaseFailedException('Refresh token encountered an error.');
134
        }
135
136
        if (!empty($result['accessToken'])) {
137
            $this->cache->store('accessToken', 'Bearer ' . $result['accessToken'], 24 * 60 * 60 - 60);
138
            $this->cache->store('refreshToken', $result['refreshToken'], 48 * 60 * 60 - 60);
139
140
            $this->setAccessToken('Bearer ' . $result['accessToken']);
141
            $this->setRefreshToken($result['refreshToken']);
142
143
            return 'ok';
144
        }
145
146
        throw new \Shetabit\Multipay\Exceptions\PurchaseFailedException('Refresh token encountered an error.');
147
    }
148
149
    /**
150
     * Call curl
151
     *
152
     * @param $url
153
     * @param $arrayData
154
     * @param bool $haveAuth
155
     * @param int $try
156
     * @param string $method
157
     * @return bool|mixed|string
158
     * @throws \Shetabit\Multipay\Exceptions\PurchaseFailedException
159
     */
160
    private function callCurl($url, $arrayData, $haveAuth = false, $try = 0, $method = 'POST')
161
    {
162
        $data = $arrayData;
163
        $jsonData = json_encode($data);
164
        $accessToken = '';
165
166
        if ($haveAuth) {
167
            $accessToken = $this->getAccessToken();
168
        }
169
170
        $ch = curl_init($this->baseUrl . $url);
171
        curl_setopt($ch, CURLOPT_USERAGENT, 'Jibit.class Rest Api');
172
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
173
        curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
174
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
175
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
176
            'Content-Type: application/json',
177
            'Authorization: ' . $accessToken,
178
            'Content-Length: ' . strlen($jsonData)
179
        ]);
180
181
        $result = curl_exec($ch);
182
        $err = curl_error($ch);
183
        $result = json_decode($result, true);
0 ignored issues
show
Bug introduced by
It seems like $result can also be of type true; however, parameter $json of json_decode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

183
        $result = json_decode(/** @scrutinizer ignore-type */ $result, true);
Loading history...
184
        curl_close($ch);
185
186
        if ($err) {
187
            throw new \Shetabit\Multipay\Exceptions\PurchaseFailedException('cURL Error #:' . $err);
188
        }
189
190
        if (empty($result['errors'])) {
191
            return $result;
192
        }
193
194
        if ($haveAuth === true && $result['errors'][0]['code'] === 'security.auth_required') {
195
            $this->generateToken(true);
196
197
            if ($try === 0) {
198
                return $this->callCurl($url, $arrayData, $haveAuth, 1, $method);
199
            }
200
201
            throw new \Shetabit\Multipay\Exceptions\PurchaseFailedException('Authentication encountered an error.');
202
        }
203
204
        return $result;
205
    }
206
207
    /**
208
     * Get access token
209
     *
210
     * @return mixed
211
     */
212
    public function getAccessToken()
213
    {
214
        return $this->accessToken;
215
    }
216
217
    /**
218
     * Set access token
219
     *
220
     * @param mixed $accessToken
221
     */
222
    public function setAccessToken($accessToken)
223
    {
224
        $this->accessToken = $accessToken;
225
    }
226
227
    /**
228
     * Set refresh token
229
     *
230
     * @param mixed $refreshToken
231
     */
232
    public function setRefreshToken($refreshToken)
233
    {
234
        $this->refreshToken = $refreshToken;
235
    }
236
237
    /**
238
     * Generate new token
239
     *
240
     * @return string
241
     * @throws \Shetabit\Multipay\Exceptions\PurchaseFailedException
242
     */
243
    private function generateNewToken()
244
    {
245
        $data = [
246
            'apiKey' => $this->apiKey,
247
            'secretKey' => $this->secretKey,
248
        ];
249
250
        $result = $this->callCurl('/tokens', $data);
251
252
        if (empty($result['accessToken'])) {
253
            throw new \Shetabit\Multipay\Exceptions\PurchaseFailedException('Token generation encoutered an error.');
254
        }
255
256
        if (! empty($result['accessToken'])) {
257
            $this->cache->store('accessToken', 'Bearer ' . $result['accessToken'], 24 * 60 * 60 - 60);
258
            $this->cache->store('refreshToken', $result['refreshToken'], 48 * 60 * 60 - 60);
259
260
            $this->setAccessToken('Bearer ' . $result['accessToken']);
261
            $this->setRefreshToken($result['refreshToken']);
262
263
            return 'ok';
264
        }
265
266
        throw new \Shetabit\Multipay\Exceptions\PurchaseFailedException('Token generation encoutered an error.');
267
    }
268
269
    /**
270
     * Verify payment
271
     *
272
     * @param string $purchaseId
273
     * @return bool|mixed|string
274
     * @throws \Shetabit\Multipay\Exceptions\PurchaseFailedException
275
     */
276
    public function paymentVerify($purchaseId)
277
    {
278
        $this->generateToken();
279
        $data = [];
280
281
        return $this->callCurl('/purchases/' . $purchaseId . '/verify', $data, true, 0, 'GET');
282
    }
283
}
284