Client::getCustomerFormCertificateBlank()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 5
c 2
b 0
f 0
dl 0
loc 9
rs 10
cc 1
nc 1
nop 2
1
<?php
2
3
namespace nikserg\CRMCertificateAPI;
4
5
use GuzzleHttp\Exception\GuzzleException;
6
use GuzzleHttp\RequestOptions;
7
use nikserg\CRMCertificateAPI\exceptions\BooleanResponseException;
8
use nikserg\CRMCertificateAPI\exceptions\InvalidRequestException;
9
use nikserg\CRMCertificateAPI\exceptions\NotFoundException;
10
use nikserg\CRMCertificateAPI\exceptions\ServerException;
11
use nikserg\CRMCertificateAPI\exceptions\TransportException;
12
use nikserg\CRMCertificateAPI\models\request\ChangeStatus;
13
use nikserg\CRMCertificateAPI\models\request\CheckSnils;
14
use nikserg\CRMCertificateAPI\models\request\Egrul as EgrulRequest;
15
use nikserg\CRMCertificateAPI\models\request\CheckPassport;
16
use nikserg\CRMCertificateAPI\models\request\CustomerFormDocuments;
17
use nikserg\CRMCertificateAPI\models\request\DetectPlatforms as DetectPlatformsRequest;
18
use nikserg\CRMCertificateAPI\models\request\PartnerFullPrice as PartnerFullPriceRequest;
19
use nikserg\CRMCertificateAPI\models\request\PartnerPlatforms as PartnerPlatformsRequest;
20
use nikserg\CRMCertificateAPI\models\request\PartnerProducts as PartnerProductsRequest;
21
use nikserg\CRMCertificateAPI\models\request\PartnerStores as PartnerStoresRequest;
22
use nikserg\CRMCertificateAPI\models\request\SendCheckRef;
23
use nikserg\CRMCertificateAPI\models\request\SendCustomerForm as SendCustomerFormRequest;
24
use nikserg\CRMCertificateAPI\models\request\SendCustomerFormData;
25
use nikserg\CRMCertificateAPI\models\response\BooleanResponse;
26
use nikserg\CRMCertificateAPI\models\response\Esia\Egrul as EgrulResponse;
27
use nikserg\CRMCertificateAPI\models\response\GetCustomerForm;
28
use nikserg\CRMCertificateAPI\models\response\GetOpportunity;
29
use nikserg\CRMCertificateAPI\models\response\models\Store;
30
use nikserg\CRMCertificateAPI\models\response\PassportCheck;
31
use nikserg\CRMCertificateAPI\models\response\SnilsCheck;
32
use nikserg\CRMCertificateAPI\models\response\models\DetectPlatformVariantPlatform;
33
use nikserg\CRMCertificateAPI\models\response\models\PartnerPlatform;
34
use nikserg\CRMCertificateAPI\models\response\models\PartnerProduct;
35
use nikserg\CRMCertificateAPI\models\response\DetectPlatformVariant;
36
use nikserg\CRMCertificateAPI\models\response\ReferralUser;
37
use nikserg\CRMCertificateAPI\models\response\SendCustomerForm as SendCustomerFormResponse;
38
use Psr\Http\Message\ResponseInterface;
39
40
/**
41
 * Клиент для связи с CRM
42
 *
43
 * @package nikserg\CRMCertificateAPI
44
 */
45
class Client
46
{
47
    /**
48
     * @var string
49
     */
50
    protected $apiKey;
51
52
    /**
53
     * @var string
54
     */
55
    protected $url;
56
57
    /**
58
     * @var \GuzzleHttp\Client
59
     */
60
    protected $guzzle;
61
62
    /**
63
     * @param string $apiKey
64
     * @param string $url
65
     */
66
    public function __construct($apiKey, $url = 'https://crm.uc-itcom.ru/index.php')
67
    {
68
        $this->apiKey = $apiKey;
69
        $this->url = trim($url, " /");
70
        $this->guzzle = new \GuzzleHttp\Client([
71
            RequestOptions::VERIFY      => false,
72
            RequestOptions::HTTP_ERRORS => false,
73
        ]);
74
    }
75
76
    /**
77
     * @param       $method
78
     * @param       $endpoint
79
     * @param array $options
80
     * @return ResponseInterface
81
     * @throws NotFoundException
82
     * @throws ServerException
83
     * @throws TransportException
84
     * @throws InvalidRequestException
85
     */
86
    protected function request($method, $endpoint, $options = [])
87
    {
88
        $options[RequestOptions::QUERY]['key'] = $this->apiKey;
89
        try {
90
            $response = $this->guzzle->request($method, "$this->url/gateway/itkExchange/$endpoint", $options);
91
        } catch (GuzzleException $e) {
92
            throw new TransportException("Ошибка запроса; {$e->getMessage()}");
93
        }
94
        switch ($response->getStatusCode()) {
95
            case 200:
96
            case 204:
97
                return $response;
98
            case 400:
99
                throw new InvalidRequestException("$endpoint: Неверный формат запроса");
100
            case 404:
101
                throw new NotFoundException("$endpoint: Сущность или точка АПИ не найдены");
102
            case 500:
103
                throw new ServerException("$endpoint: Ошибка сервера \n" . $response->getBody()->getContents());
104
            default:
105
                throw new TransportException("$endpoint: Неожиданный код ответа {$response->getStatusCode()}");
106
        }
107
    }
108
109
    /**
110
     * @param       $method
111
     * @param       $endpoint
112
     * @param       $data
113
     * @param array $options
114
     * @return mixed
115
     * @throws NotFoundException
116
     * @throws ServerException
117
     * @throws TransportException
118
     * @throws InvalidRequestException
119
     */
120
    protected function requestJson($method, $endpoint, $data, $options = [])
121
    {
122
        $options[RequestOptions::QUERY]['key'] = $this->apiKey;
123
        $options[RequestOptions::JSON] = $data;
124
        try {
125
            $response = $this->guzzle->request($method, "$this->url/gateway/itkExchange/$endpoint", $options);
126
        } catch (GuzzleException $e) {
127
            throw new TransportException("Ошибка запроса; {$e->getMessage()}");
128
        }
129
        try {
130
            $data = $this->getJsonBody($response);
131
            switch ($response->getStatusCode()) {
132
                case 200:
133
                    return $data;
134
                case 400:
135
                    throw new InvalidRequestException("$endpoint: " . $data->error->message ?? $data->message ?? "Неверный формат запроса");
136
                case 404:
137
                    throw new NotFoundException("$endpoint: " . $data->error->message ?? $data->message ?? "Сущность или точка АПИ не найдены");
138
                case 500:
139
                    throw new ServerException("$endpoint: " . $data->error->message ?? $data->message ?? "Неожиданная ошибка сервера");
140
                default:
141
                    throw new TransportException("$endpoint: " . $data->error->message ?? $data->message ?? "Неожиданный код ответа {$response->getStatusCode()}");
142
            }
143
        } catch (TransportException $e) {
144
            throw new TransportException('Ошибка во время отправки запроса ' . print_r([
145
                    $method,
146
                    $this->url . $endpoint,
147
                    $options,
148
                    $data,
149
                ], true) . ': ' . $e->getMessage(), $e->getCode(), $e);
150
        }
151
    }
152
153
    /**
154
     * @param ResponseInterface $response
155
     * @return mixed
156
     * @throws TransportException
157
     */
158
    private function getJsonBody(ResponseInterface $response)
159
    {
160
        $body = $response->getBody();
161
        if (strlen($body) === 0) {
162
            throw new TransportException('Пустое тело ответа на JSON запрос. Код ответа ' . $response->getStatusCode());
163
        }
164
        $json = json_decode($body);
165
        $jsonErrorCode = json_last_error();
166
        $jsonErrorMessage = json_last_error_msg();
167
        if ($jsonErrorCode !== JSON_ERROR_NONE) {
168
            throw new TransportException("$jsonErrorMessage: $body", $jsonErrorCode);
169
        }
170
        return $json;
171
    }
172
173
    /**
174
     * Отправить запрос на создание заявки на сертификат
175
     *
176
     * @param SendCustomerFormRequest $customerForm
177
     * @return SendCustomerFormResponse
178
     * @throws InvalidRequestException
179
     * @throws NotFoundException
180
     * @throws ServerException
181
     * @throws TransportException
182
     */
183
    public function sendCustomerForm(SendCustomerFormRequest $customerForm)
184
    {
185
        $result = $this->requestJson('POST', 'pushCustomerForm', $customerForm);
186
        return $this->fill(SendCustomerFormResponse::class, $result);
187
    }
188
189
    /**
190
     * Получить информацию о заявке на сертификат
191
     *
192
     * @param int $customerFormCrmId
193
     * @return GetCustomerForm
194
     * @throws InvalidRequestException
195
     * @throws NotFoundException
196
     * @throws ServerException
197
     * @throws TransportException
198
     */
199
    public function getCustomerForm($customerFormCrmId)
200
    {
201
        $result = $this->getJsonBody($this->request('GET', 'pullCustomerForm', [
202
            RequestOptions::QUERY => [
203
                'id' => $customerFormCrmId,
204
            ],
205
        ]));
206
        return $this->fill(GetCustomerForm::class, $result);
207
    }
208
209
    /**
210
     * Получить информацию о сделки
211
     *
212
     * @param $opportunityCrmId
213
     * @return GetOpportunity
214
     * @throws InvalidRequestException
215
     * @throws NotFoundException
216
     * @throws ServerException
217
     * @throws TransportException
218
     */
219
    public function getOpportunity($opportunityCrmId)
220
    {
221
        $result = $this->getJsonBody($this->request('GET', 'pullOpportunity', [
222
            RequestOptions::QUERY => [
223
                'id' => $opportunityCrmId,
224
            ],
225
        ]));
226
        return $this->fill(GetOpportunity::class, $result);
227
    }
228
229
    /**
230
     * Изменить статус заявки
231
     *
232
     * @param ChangeStatus $changeStatus
233
     * @return BooleanResponse
234
     * @throws BooleanResponseException
235
     * @throws InvalidRequestException
236
     * @throws NotFoundException
237
     * @throws ServerException
238
     * @throws TransportException
239
     */
240
    public function changeStatus(ChangeStatus $changeStatus)
241
    {
242
        $result = $this->requestJson('POST', 'pushCustomerFormStatus', $changeStatus);
243
        $response = new BooleanResponse();
244
        $response->status = $result->status;
245
        $response->message = $result->message ?? null;
246
        if (!$response->status) {
247
            throw new BooleanResponseException('Ошибка при обновлении статуса в CRM ' . print_r($response, true));
248
        }
249
        return $response;
250
    }
251
252
    /**
253
     * Удалить заявку на сертификат
254
     *
255
     * @param int $customerFormCrmId
256
     * @return BooleanResponse
257
     * @throws BooleanResponseException
258
     * @throws InvalidRequestException
259
     * @throws NotFoundException
260
     * @throws ServerException
261
     * @throws TransportException
262
     */
263
    public function deleteCustomerForm($customerFormCrmId)
264
    {
265
        $result = $this->getJsonBody($this->request('GET', 'deleteCustomerForm', [
266
            RequestOptions::QUERY => [
267
                'id' => $customerFormCrmId,
268
            ],
269
        ]));
270
        $response = new BooleanResponse();
271
        $response->status = $result->status;
272
        $response->message = $result->message ?? null;
273
        if (!$response->status) {
274
            throw new BooleanResponseException('Ошибка при удалении заявки в CRM ' . print_r($response, true));
275
        }
276
        return $response;
277
    }
278
279
    /**
280
     * Получить заявление на выпуск сертификата
281
     *
282
     * @param int    $customerFormCrmId
283
     * @param string $format
284
     * @return string
285
     * @throws InvalidRequestException
286
     * @throws NotFoundException
287
     * @throws ServerException
288
     * @throws TransportException
289
     */
290
    public function getCustomerFormClaim($customerFormCrmId, $format = 'pdf')
291
    {
292
        $result = $this->request('GET', 'union', [
293
            RequestOptions::QUERY => [
294
                'id'     => $customerFormCrmId,
295
                'format' => $format,
296
            ],
297
        ]);
298
        return $result->getBody()->getContents();
299
    }
300
301
    /**
302
     * Получить заявление на выпуск сертификата
303
     *
304
     * @param int    $customerFormCrmId
305
     * @param string $format
306
     * @return string
307
     * @throws InvalidRequestException
308
     * @throws NotFoundException
309
     * @throws ServerException
310
     * @throws TransportException
311
     */
312
    public function getCustomerFormCertificateBlank($customerFormCrmId, $format = 'pdf')
313
    {
314
        $result = $this->request('GET', 'certificateBlank', [
315
            RequestOptions::QUERY => [
316
                'id'     => $customerFormCrmId,
317
                'format' => $format,
318
            ],
319
        ]);
320
        return $result->getBody()->getContents();
321
    }
322
323
    /**
324
     * Выписка ЕГРЮЛ
325
     *
326
     * @param EgrulRequest $request
327
     * @return EgrulResponse
328
     * @throws InvalidRequestException
329
     * @throws NotFoundException
330
     * @throws ServerException
331
     * @throws TransportException
332
     */
333
    public function egrul(EgrulRequest $request)
334
    {
335
        return new EgrulResponse($this->requestJson('GET', 'egrul', $request));
336
    }
337
338
    /**
339
     * Отправить данные бланка заявки на сертификат
340
     *
341
     * @param int                  $crmCustomerFormId
342
     * @param SendCustomerFormData $customerFormData
343
     * @return SendCustomerFormResponse
344
     * @throws InvalidRequestException
345
     * @throws NotFoundException
346
     * @throws ServerException
347
     * @throws TransportException
348
     */
349
    public function sendCustomerFormData($crmCustomerFormId, SendCustomerFormData $customerFormData)
350
    {
351
        $result = $this->requestJson('POST', 'pushCustomerFormData', [
352
            'id'       => $crmCustomerFormId,
353
            'formData' => $customerFormData,
354
        ]);
355
        return $this->fill(SendCustomerFormResponse::class, $result);
356
    }
357
358
    /**
359
     * Расширенная проверка паспортных данных
360
     *
361
     * @param CheckPassport $request
362
     * @return PassportCheck
363
     * @throws InvalidRequestException
364
     * @throws NotFoundException
365
     * @throws ServerException
366
     * @throws TransportException
367
     */
368
    public function checkPassport(CheckPassport $request)
369
    {
370
        $result = $this->requestJson('GET', 'checkPassport', $request);
371
        return $this->fill(PassportCheck::class, $result);
372
    }
373
374
    /**
375
     * Проверка СНИЛС данных
376
     *
377
     * @param CheckSnils $request
378
     * @return SnilsCheck
379
     * @throws InvalidRequestException
380
     * @throws NotFoundException
381
     * @throws ServerException
382
     * @throws TransportException
383
     */
384
    public function checkSnils(CheckSnils $request)
385
    {
386
        $result = $this->requestJson('GET', 'checkSnils', $request);
387
        return $this->fill(SnilsCheck::class, $result);
388
    }
389
390
    /**
391
     * Получение информации о реферальном пользователе
392
     *
393
     * @param SendCheckRef $sendCheckRef
394
     * @return ReferralUser|null - null если реферальный пользователь не найден
395
     * @throws InvalidRequestException
396
     * @throws NotFoundException
397
     * @throws ServerException
398
     * @throws TransportException
399
     */
400
    public function getReferralUser(SendCheckRef $sendCheckRef)
401
    {
402
        $result = $this->requestJson('POST', 'getRefUserInfo', $sendCheckRef);
403
        if ($result === null) {
404
            return null;
405
        }
406
        return $this->fill(ReferralUser::class, $result);
407
    }
408
409
    /**
410
     * Определить варианты площадок для переданного списка ОИДов
411
     *
412
     * @param DetectPlatformsRequest $request
413
     * @return DetectPlatformVariant[]
414
     * @throws InvalidRequestException
415
     * @throws NotFoundException
416
     * @throws ServerException
417
     * @throws TransportException
418
     */
419
    public function detectPlatforms(DetectPlatformsRequest $request)
420
    {
421
        $result = $this->requestJson('POST', 'detectPlatforms', $request);
422
        if (empty($result->variants)) {
423
            return [];
424
        }
425
        $return = [];
426
        foreach ($result->variants as $variant) {
427
            $variantModel = new DetectPlatformVariant();
428
            $variantModel->platforms = [];
429
            foreach ($variant->platforms as $value => $name) {
430
                $platform = new DetectPlatformVariantPlatform();
431
                $platform->value = $value;
432
                $platform->name = $name;
433
                $variantModel->platforms[] = $platform;
434
            }
435
            $variantModel->price = $variant->price;
436
            $variantModel->excluded = $variant->excluded;
437
            $return[] = $variantModel;
438
        }
439
        return $return;
440
    }
441
442
    /**
443
     * @param CustomerFormDocuments $documents
444
     * @return bool
445
     * @throws InvalidRequestException
446
     * @throws NotFoundException
447
     * @throws ServerException
448
     * @throws TransportException
449
     */
450
    public function pushCustomerFormDocuments(CustomerFormDocuments $documents)
451
    {
452
        $multipart = [
453
            [
454
                'name'     => 'customerFormId',
455
                'contents' => $documents->customerFormId,
456
            ],
457
        ];
458
        if ($documents->signedClaim) {
459
            $multipart[] = [
460
                'name'     => 'signedClaim',
461
                'filename' => 'claim.pdf.sig',
462
                'contents' => $documents->signedClaim,
463
            ];
464
        }
465
        if ($documents->signedBlank) {
466
            $multipart[] = [
467
                'name'     => 'signedBlank',
468
                'filename' => 'blank.pdf.sig',
469
                'contents' => $documents->signedBlank,
470
            ];
471
        }
472
        $this->request('POST', 'pushCustomerFormDocuments', [
473
            RequestOptions::MULTIPART => $multipart,
474
        ]);
475
        return true;
476
    }
477
478
    /**
479
     * Получает платформы, доступные партнеру переданному в запросе
480
     *
481
     * @param PartnerPlatformsRequest $request
482
     * @return PartnerPlatform[]
483
     * @throws InvalidRequestException
484
     * @throws NotFoundException
485
     * @throws ServerException
486
     * @throws TransportException
487
     */
488
    public function getPartnerPlatformsAll(PartnerPlatformsRequest $request)
489
    {
490
        $result = $this->requestJson('POST', 'getPartnerPlatforms', $request);
491
        return $this->fillList(PartnerPlatform::class, $result->platforms);
492
    }
493
494
    /**
495
     * Получает продукты, настроенные для партнера переданного в запросе
496
     *
497
     * @param PartnerProductsRequest $request
498
     * @return PartnerProduct[]
499
     * @throws InvalidRequestException
500
     * @throws NotFoundException
501
     * @throws ServerException
502
     * @throws TransportException
503
     */
504
    public function getPartnerProductsAll(PartnerProductsRequest $request)
505
    {
506
        $result = $this->requestJson('POST', 'getPartnerProducts', $request);
507
        return $this->fillList(PartnerProduct::class, $result->products);
508
    }
509
510
    /**
511
     * Отдает сумму по выбранным продуктам и плаформам для партнера
512
     *
513
     * @param PartnerFullPriceRequest $fullPriceRequest
514
     * @return float
515
     * @throws InvalidRequestException
516
     * @throws NotFoundException
517
     * @throws ServerException
518
     * @throws TransportException
519
     */
520
    public function getPartnerFullPrice(PartnerFullPriceRequest $fullPriceRequest)
521
    {
522
        $result = $this->requestJson('POST', 'getPartnerFullPrice', $fullPriceRequest);
523
        return $result->price;
524
    }
525
526
    /**
527
     * Отдает список точек/складов/трансферов партнера
528
     *
529
     * @param PartnerStoresRequest $partnerStores
530
     * @return Store[]
531
     * @throws InvalidRequestException
532
     * @throws NotFoundException
533
     * @throws ServerException
534
     * @throws TransportException
535
     */
536
    public function getPartnerStores(PartnerStoresRequest $partnerStores)
537
    {
538
        $result = $this->requestJson('POST', 'getPartnerStores', $partnerStores);
539
        return $this->fillList(Store::class, $result->stores);
540
    }
541
542
    public function fill($class, $attributes)
543
    {
544
        $model = new $class;
545
        foreach ($attributes as $attribute => $value) {
546
            $model->$attribute = $value;
547
        }
548
        return $model;
549
    }
550
551
    public function fillList($class, $list)
552
    {
553
        $models = [];
554
        foreach ($list as $item) {
555
            $models[] = $this->fill($class, $item);
556
        }
557
        return $models;
558
    }
559
560
    #region urls
561
562
    /**
563
     * Ссылка для скачивания сертификата
564
     *
565
     * @param $customerFormId
566
     * @param $token
567
     * @return string
568
     */
569
    public function certificateDownloadUrl($customerFormId, $token)
570
    {
571
        return $this->url . '/customerForms/external/downloadCertificate?token=' . $token . '&customerFormId=' . $customerFormId;
572
    }
573
574
    /**
575
     * Ссылка для скачивания реализации
576
     *
577
     * @param $customerFormId
578
     * @param $token
579
     * @return string
580
     */
581
    public function realizationDownloadUrl($customerFormId, $token)
582
    {
583
        return $this->url . '/customerForms/external/downloadFirstRealization?token=' . $token . '&customerFormId=' . $customerFormId;
584
    }
585
586
    /**
587
     * Индивидуальная ссылка для редактирования
588
     *
589
     * @param $token
590
     * @return string
591
     */
592
    public function editUrl($token)
593
    {
594
        return $this->url . '/customerForms/external?token=' . $token;
595
    }
596
597
    /**
598
     * Индивидуальная ссылка для генерации
599
     *
600
     * @param      $token
601
     * @param      $generatonToken
602
     * @param bool $iframe Выводить отображение для фрейма
603
     * @return string
604
     */
605
    public function generationUrl($token, $generatonToken, $iframe = false)
606
    {
607
        $return = $this->url . '/customerForms/external/generate?token=' . $token . '&generationToken=' . $generatonToken;
608
        if ($iframe) {
609
            $return .= '&iframe=1';
610
        }
611
        return $return;
612
    }
613
614
    /**
615
     * Ссылка на фрейм
616
     *
617
     * @param $customerFormId
618
     * @param $token
619
     * @return string
620
     */
621
    public function customerFormFrameUrl($customerFormId, $token)
622
    {
623
        return $this->url . '/customerForms/external/step1?token=' . $token . '&customerFormId=' . $customerFormId;
624
    }
625
626
    /**
627
     * Ссылка для записи сертификата на носитель
628
     *
629
     * @param $customerFormId
630
     * @param $token
631
     * @return string
632
     */
633
    public function certificateWriteUrl($customerFormId, $token)
634
    {
635
        return $this->url . '/customerForms/external/writeCertificate?token=' . $token . '&customerFormId=' . $customerFormId;
636
    }
637
    #endregion urls
638
}
639