Api::get()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace CdekSDK2\Http;
6
7
use CdekSDK2\Constants;
8
use CdekSDK2\Exceptions\AuthException;
9
use CdekSDK2\Exceptions\RequestException;
10
use Nyholm\Psr7\Request;
11
use Nyholm\Psr7\Uri;
12
use Psr\Http\Client\ClientExceptionInterface;
13
use Psr\Http\Client\ClientInterface;
14
15
/**
16
 * Class Api
17
 * @package CdekSDK2\Http
18
 */
19
class Api
20
{
21
    /**
22
     * Аккаунт сервиса интеграции
23
     * @var string
24
     */
25
    private $account;
26
27
    /**
28
     * Секретный пароль сервиса интеграции
29
     * @var string
30
     */
31
    private $secure;
32
33
    /**
34
     * Тестовые настройки интеграции
35
     * @var bool
36
     */
37
    private $test = false;
38
39
    /**
40
     * @var string
41
     */
42
    private $token = '';
43
44
    /**
45
     * @var int
46
     */
47
    private $expire = 0;
48
49
    /**
50
     * @var ClientInterface
51
     */
52
    protected $client;
53
54
    /**
55
     * Api constructor.
56
     * @param ClientInterface $http
57
     * @param string|null $account
58
     * @param string|null $secure
59
     */
60 6
    public function __construct(ClientInterface $http, string $account = null, string $secure = null)
61
    {
62 6
        $this->account = $account ?? '';
63 6
        $this->secure = $secure ?? '';
64 6
        $this->client = $http;
65
    }
66
67
    /**
68
     *
69
     * @return string
70
     */
71 1
    public function getAccount(): string
72
    {
73 1
        return $this->account;
74
    }
75
76
    /**
77
     * @param string $account
78
     */
79
    public function setAccount(string $account): void
80
    {
81
        $this->account = $account;
82
    }
83
84
    /**
85
     * @return string
86
     */
87
    public function getToken(): string
88
    {
89
        return $this->token;
90
    }
91
92
    /**
93
     * @param string $token
94
     */
95
    public function setToken(string $token): void
96
    {
97
        $this->token = $token;
98
    }
99
100
    /**
101
     * @return string
102
     */
103 1
    public function getSecure(): string
104
    {
105 1
        return $this->secure;
106
    }
107
108
    /**
109
     * @param string $secure
110
     */
111 1
    public function setSecure(string $secure): void
112
    {
113 1
        $this->secure = $secure;
114
    }
115
116
    /**
117
     * @return bool
118
     */
119 1
    public function isTest(): bool
120
    {
121 1
        return $this->test;
122
    }
123
124
    /**
125
     * @param bool $test
126
     */
127 1
    public function setTest(bool $test): void
128
    {
129 1
        $this->test = $test;
130 1
        if ($test) {
131 1
            $this->account = Constants::TEST_ACCOUNT;
132 1
            $this->secure = Constants::TEST_SECURE;
133
        }
134
    }
135
136
    /**
137
     * Авторизация клиента в сервисе Интеграции
138
     * @return bool
139
     * @throws AuthException
140
     * @throws RequestException
141
     */
142 4
    public function authorize(): bool
143
    {
144 4
        $param = [
145 4
            Constants::AUTH_KEY_TYPE => Constants::AUTH_PARAM_CREDENTIAL,
146 4
            Constants::AUTH_KEY_CLIENT_ID => $this->account,
147 4
            Constants::AUTH_KEY_SECRET => $this->secure,
148 4
        ];
149 4
        $response = $this->post('/oauth/token', $param);
150 4
        if ($response->isOk()) {
151 3
            $token_info = $this->decodeBody($response->getBody());
152 3
            $this->token = $token_info['access_token'] ?? '';
153 3
            $this->expire = $token_info['expires_in'] ?? 0;
154 3
            $this->expire = time() + $this->expire - 10;
155 3
            return true;
156
        }
157 1
        throw new AuthException(Constants::AUTH_FAIL);
158
    }
159
160
    /**
161
     * @return bool
162
     */
163 4
    public function isExpired(): bool
164
    {
165 4
        return $this->expire < time();
166
    }
167
168
    /**
169
     * @return int
170
     */
171
    public function getExpire(): int
172
    {
173
        return $this->expire;
174
    }
175
176
    /**
177
     * @param int $timestamp
178
     */
179
    public function setExpire(int $timestamp): void
180
    {
181
        $this->expire = $timestamp;
182
    }
183
184
    /**
185
     * @param string $url
186
     * @param array $params
187
     * @return ApiResponse
188
     * @throws RequestException
189
     */
190 4
    public function post(string $url, array $params = []): ApiResponse
191
    {
192 4
        return $this->request('POST', $url, $params);
193
    }
194
195
    /**
196
     * @param string $url
197
     * @return ApiResponse
198
     * @throws RequestException
199
     */
200 1
    public function get(string $url): ApiResponse
201
    {
202 1
        return $this->request('GET', $url);
203
    }
204
205
    /**
206
     * @param string $url
207
     * @return ApiResponse
208
     * @throws RequestException
209
     */
210 1
    public function delete(string $url): ApiResponse
211
    {
212 1
        return $this->request('DELETE', $url);
213
    }
214
215
    /**
216
     * @param string $method
217
     * @param string $url
218
     * @param array $params
219
     * @return ApiResponse
220
     * @throws RequestException
221
     */
222 4
    protected function request(string $method, string $url, array $params = []): ApiResponse
223
    {
224 4
        $url = ($this->test ? Constants::API_URL_TEST : Constants::API_URL) . $url;
225 4
        $uri = new Uri($url);
226
        try {
227 4
            $headers = [
228 4
                'Accept' => 'application/json',
229 4
                'Content-Type' => 'application/json',
230 4
            ];
231 4
            if ($this->isExpired() && strripos($url, 'oauth/token') === false) {
232 3
                $this->authorize();
233 4
            } elseif (strripos($url, 'oauth/token') !== false) {
234 4
                $headers['Content-Type'] = 'application/x-www-form-urlencoded';
235
            }
236
237 4
            $body = (strripos($url, 'oauth/token') === false)
238 4
                ? (string)json_encode($params) : http_build_query($params);
239 4
            if (!empty($this->token)) {
240
                $headers['Authorization'] = 'Bearer ' . $this->token;
241
            }
242 4
            $request = new Request($method, $uri, $headers, $body);
243 4
            $response = $this->client->sendRequest($request);
244 4
            return new ApiResponse($response);
245
        } catch (ClientExceptionInterface $e) {
246
            throw new RequestException($e->getMessage(), (int)$e->getCode());
247
        } catch (\Exception $e) {
248
            throw new RequestException($e->getMessage(), (int)$e->getCode());
249
        }
250
    }
251
252
    /**
253
     * Преобразовываем json в массив
254
     * @param string $body
255
     * @return array
256
     */
257 3
    private function decodeBody(string $body): array
258
    {
259 3
        $decoded_body = json_decode($body, true);
260 3
        if ($decoded_body === null || !is_array($decoded_body)) {
261
            $decoded_body = [];
262
        }
263 3
        return $decoded_body;
264
    }
265
}
266