Issues (3)

src/NovaPoshta.php (1 issue)

Severity
1
<?php
2
3
namespace Daaner\NovaPoshta;
4
5
use Daaner\NovaPoshta\Contracts\NovaPoshtaInterface;
6
use Exception;
7
use Illuminate\Http\Client\Response as ClientResponse;
8
use Illuminate\Support\Facades\Http;
9
use Illuminate\Support\Facades\Log;
10
11
class NovaPoshta implements NovaPoshtaInterface
12
{
13
    protected $api;
14
    protected $url;
15
    protected $dev;
16
17
    protected $return;
18
19
    protected $model;
20
    protected $calledMethod;
21
    protected $methodProperties;
22
23
    /**
24
     * NovaPoshta constructor main settings.
25
     */
26
    public function __construct()
27
    {
28
        $this->dev = config('novaposhta.dev');
29
        $this->getApi();
30
        $this->url = config('novaposhta.base_uri').config('novaposhta.point');
31
32
        $this->return = [
33
            'success' => false,
34
            'result' => null,
35
            'info' => [],
36
        ];
37
    }
38
39
    /**
40
     * @return void
41
     */
42
    public function getApi(): void
43
    {
44
        if (! $this->api) {
45
            $this->api = config('novaposhta.api_key');
46
        }
47
    }
48
49
    /**
50
     * Устанавливаем API токен отличный от значения в конфиге.
51
     *
52
     * @param  string  $api  API токен
53
     * @return $this
54
     */
55
    public function setApi(string $api): self
56
    {
57
        $this->api = $api;
58
59
        return $this;
60
    }
61
62
    /**
63
     * @param  bool  $auth
64
     * @return ClientResponse|string|array
65
     */
66
    public function getData(bool $auth = true)
67
    {
68
        $url = $this->url.'/'.$this->model.'/'.$this->calledMethod;
69
70
        $body = [];
71
        $body['modelName'] = $this->model;
72
        $body['calledMethod'] = $this->calledMethod;
73
        $body['methodProperties'] = $this->methodProperties;
74
75
        if ($auth) {
76
            $body['apiKey'] = $this->api;
77
        }
78
79
        if ($this->dev) {
80
            $this->development($auth);
81
        }
82
83
        try {
84
            $response = Http::timeout(config('novaposhta.http_response_timeout', 3))
85
                ->retry(
86
                    config('novaposhta.http_retry_max_time', 2),
87
                    config('novaposhta.http_retry_delay', 500)
88
                )
89
                ->withHeaders([
90
                    'Accept' => 'application/json',
91
                    'Content-Type' => 'application/json',
92
                ])
93
                ->post($url, $body);
94
        } catch (Exception $e) {
95
            if ($e->getCode() == 401) {
96
                // Ошибка API ключа
97
                $response = __('novaposhta::novaposhta.statusCode.20000200068');
98
            } else {
99
                $response = $e->getMessage();
100
            }
101
        }
102
103
        return $response;
104
    }
105
106
    /**
107
     * @param  string  $model  Модель Новой Почты
108
     * @param  string  $calledMethod  Метод модели
109
     * @param  array|null  $methodProperties  Тело запроса
110
     * @param  bool  $auth  Использовать ли аутентификацию токеном или нет
111
     * @return array
112
     */
113
    public function getResponse(
114
        string $model,
115
        string $calledMethod,
116
        ?array $methodProperties,
117
        bool $auth = true
118
    ): array {
119
        $this->model = $model;
120
        $this->calledMethod = $calledMethod;
121
        $this->methodProperties = $methodProperties;
122
123
        $response = $this->getData($auth);
124
125
        // Ошибка курла
126
        if (! ($response instanceof ClientResponse)) {
0 ignored issues
show
$response is always a sub-type of Illuminate\Http\Client\Response.
Loading history...
127
            $this->return['info']['error'] = $response;
128
            $this->return['info']['StatusCode'] = '20000100016'; // Сервис не доступен
129
            $this->return['info']['StatusLocale'] = __('novaposhta::novaposhta.error_data');
130
131
            return $this->return;
132
        }
133
134
        // Ошибка запроса или 401
135
        if ($response->failed()) {
136
            $this->return['info']['error'] = trans('novaposhta::novaposhta.error_data');
137
138
            return $this->return;
139
        }
140
141
        // если что-то не JSON (типа application/pdf)
142
        if ($response->header('Content-Type') !== 'application/json') {
143
            $this->return['success'] = $response->ok();
144
145
            $this->return['info']['file'] = true;
146
            $this->return['info']['ContentType'] = $response->header('Content-Type');
147
            $this->return['info']['ContentDisposition'] = $response->header('Content-Disposition') ?? '';
148
149
            $this->return['result'] = $response->body();
150
151
            return $this->return;
152
        }
153
154
        $answer = $response->json();
155
156
        /**
157
         * Development.
158
         */
159
        if ($this->dev) {
160
            $this->return['dev'] = $answer;
161
        }
162
163
        // TODO: Возможно, исправлено
164
        if ($auth === false && isset($answer[0])) {
165
            /**
166
             * Костыль для Новой Почты.
167
             * Спасибо Вам большое, что нормально не выдаете ответ :).
168
             */
169
            $answer = $answer[0];
170
        }
171
172
        if (isset($answer['success'])) {
173
            $this->return['success'] = $answer['success'];
174
        }
175
176
        if (isset($answer['data'])) {
177
            $this->return['result'] = $answer['data'];
178
        }
179
180
        /**
181
         * Формирование info.
182
         */
183
        $this->return['info'] = $this->addInfo($answer);
184
185
        return $this->return;
186
    }
187
188
    /**
189
     * Формирование информации.
190
     * Ошибки, уведомления.
191
     *
192
     * @param  mixed  $answer  Ответ от НП
193
     */
194
    public function addInfo($answer): array
195
    {
196
        $info = [];
197
198
        if (isset($answer['warnings']) && $answer['warnings']) {
199
            $info['warnings'] = $answer['warnings'];
200
        }
201
202
        if (isset($answer['infoCodes']) && $answer['infoCodes']) {
203
            $info['infoCodes'] = $answer['infoCodes'];
204
205
            foreach ($answer['infoCodes'] as $err) {
206
                $info['infoCodes'] = $err;
207
            }
208
            if (isset($answer['infoCodes'][0])) {
209
                $info['StatusLocale'] = __('novaposhta::novaposhta.statusCode.'.$answer['infoCodes'][0]);
210
            }
211
        }
212
213
        if (isset($answer['errors']) && $answer['errors']) {
214
            $info['errors'] = $answer['errors'];
215
            if ($answer['errorCodes']) {
216
                foreach ($answer['errorCodes'] as $err) {
217
                    $info['StatusCode'] = $err;
218
                }
219
                if (isset($answer['errorCodes'][0])) {
220
                    $info['StatusLocale'] = __('novaposhta::novaposhta.statusCode.'.$answer['errorCodes'][0]);
221
                }
222
            }
223
        }
224
225
        if (isset($answer['info']) && $answer['info']) {
226
            $info['info'] = $answer['info'];
227
        }
228
229
        return $info;
230
    }
231
232
    /**
233
     * Логирование запроса.
234
     *
235
     * @param  bool  $auth  Аутентификация
236
     * @return void
237
     */
238
    public function development(bool $auth): void
239
    {
240
        Log::debug('= = = = = = = = = = = = = = = = = = = =');
241
        Log::debug($this->model.' / '.$this->calledMethod.' // apiKey: '.(int) $auth);
242
        Log::debug('--------------------');
243
244
        if (! empty($this->methodProperties)) {
245
            try {
246
                Log::notice(json_encode($this->methodProperties));
247
            } catch (Exception $e) {
248
                Log::notice('method json_encode error');
249
            }
250
        }
251
    }
252
}
253