Passed
Push — master ( d743e2...20969e )
by Jhao
01:54
created

SingleAccessClient   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 149
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 12
Bugs 0 Features 0
Metric Value
eloc 76
c 12
b 0
f 0
dl 0
loc 149
ccs 52
cts 52
cp 1
rs 10
wmc 13

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A getTrackingUrl() 0 3 1
A getClient() 0 3 1
A callSoapMethod() 0 15 3
A assembleCashOnDeliveryRequestArguments() 0 8 1
A assembleAuthorizationHeader() 0 6 1
A assembleTrackingRequestArguments() 0 10 1
A getTrackingEvents() 0 16 2
A getCashOnDeliveryEvents() 0 15 2
1
<?php
2
3
/**
4
 * This file is part of RussianPost SDK package.
5
 *
6
 * © Appwilio (http://appwilio.com), greabock (https://github.com/greabock), JhaoDa (https://github.com/jhaoda)
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Appwilio\RussianPostSDK\Tracking;
15
16
use Psr\Log\NullLogger;
17
use Psr\Log\LoggerAwareTrait;
18
use Psr\Log\LoggerAwareInterface;
19
use Appwilio\RussianPostSDK\Tracking\Single\TrackingEventsResponse;
20
use Appwilio\RussianPostSDK\Tracking\Single\CashOnDeliveryEventsRequest;
21
use Appwilio\RussianPostSDK\Tracking\Single\CashOnDeliveryEventsResponse;
22
use Appwilio\RussianPostSDK\Tracking\Exceptions\SingleAccessException;
23
24
class SingleAccessClient implements LoggerAwareInterface
25
{
26
    use LoggerAwareTrait;
27
28
    public const LANG_ENG = 'ENG';
29
    public const LANG_RUS = 'RUS';
30
31
    public const HISTORY_OPERATIONS    = 0;
32
    public const HISTORY_NOTIFICATIONS = 1;
33
34
    protected const LINK_URL = 'https://www.pochta.ru/tracking';
35
    protected const WSDL_URL = 'https://tracking.pochta.ru/tracking-web-static/rtm34_wsdl.xml';
36
37
    protected const XML_NS_DATA     = 'http://russianpost.org/operationhistory/data';
38
    protected const XML_NS_COD_DATA = 'http://www.russianpost.org/RTM/DataExchangeESPP/Data';
39
40
    /** @var \SoapClient */
41
    protected $client;
42
43
    /** @var string */
44
    private $login;
45
46
    /** @var string */
47
    private $password;
48
49
    private $options = [
50
        'soap_version' => SOAP_1_2,
51
        'trace'        => 1,
52
        'classmap'     => [
53
            'Rtm02Parameter'                   => Single\Parameter::class,
54
55
            'getOperationHistoryResponse'      => Single\TrackingEventsResponse::class,
56
            'OperationHistoryRecord'           => Single\TrackingEvent::class,
57
            'Address'                          => Single\TrackingEventAddress::class,
58
            'Country'                          => Single\TrackingEventCountry::class,
59
            'OperationHistoryData'             => Single\TrackingEventsWrapper::class,
60
            'OperationParameters'              => Single\TrackingEventOperationParameters::class,
61
            'UserParameters'                   => Single\TrackingEventUserParameters::class,
62
            'ItemParameters'                   => Single\TrackingEventItemParameters::class,
63
            'AddressParameters'                => Single\TrackingEventAddressParameters::class,
64
            'FinanceParameters'                => Single\TrackingEventFinanceParameters::class,
65
66
            'PostalOrderEvent'                 => Single\CashOnDeliveryEvent::class,
67
            'PostalOrderEventsForMailResponse' => Single\CashOnDeliveryEventsResponse::class,
68
            'PostalOrderEventsForMailInput'    => Single\CashOnDeliveryEventsRequest::class,
69
            // Mai – не опечатка
70
            'PostalOrderEventsForMaiOutput'    => Single\CashOnDeliveryEventsWrapper::class,
71
        ],
72
    ];
73
74 8
    public function __construct(string $login, string $password)
75
    {
76 8
        $this->login = $login;
77 8
        $this->password = $password;
78
79 8
        $this->logger = new NullLogger();
80 8
    }
81
82 1
    public function getTrackingUrl(string $number): string
83
    {
84 1
        return self::LINK_URL."#{$number}";
85
    }
86
87 4
    public function getTrackingEvents(
88
        string $track,
89
        string $language = self::LANG_RUS,
90
        int $type = self::HISTORY_OPERATIONS
91
    ): TrackingEventsResponse {
92
        /** @var TrackingEventsResponse $response */
93 4
        $response = $this->callSoapMethod(
94 4
            'getOperationHistory',
95 4
            $this->assembleTrackingRequestArguments($track, $language, $type)
96
        );
97
98 2
        if (\count($response->getEvents()) === 0) {
99 1
            throw SingleAccessException::becauseEmptyTrackingResponse($track);
100
        }
101
102 1
        return $response;
103
    }
104
105 2
    public function getCashOnDeliveryEvents(
106
        string $track,
107
        string $language = self::LANG_RUS
108
    ): CashOnDeliveryEventsResponse {
109
        /** @var CashOnDeliveryEventsResponse $response */
110 2
        $response = $this->callSoapMethod(
111 2
            'PostalOrderEventsForMail',
112 2
            $this->assembleCashOnDeliveryRequestArguments($track, $language)
113
        );
114
115 2
        if (\count($response->getEvents()) === 0) {
116 1
            throw SingleAccessException::becauseEmptyCODResponse($track);
117
        }
118
119 1
        return $response;
120
    }
121
122 6
    protected function getClient(): \SoapClient
123
    {
124 6
        return $this->client ?? ($this->client = new \SoapClient(self::WSDL_URL, $this->options));
125
    }
126
127 6
    private function callSoapMethod(string $method, \SoapVar $arguments)
128
    {
129
        try {
130 6
            return $this->getClient()->__soapCall($method, [$arguments]);
131 2
        } catch (\SoapFault $e) {
132 2
            if (\property_exists($e, 'detail')) {
133 1
                $detail = \get_object_vars($e->detail);
134
135 1
                throw new SingleAccessException(\key($detail).': '.\current($detail), $e->getCode(), $e);
136
            }
137
138 1
            throw new SingleAccessException($e->getMessage(), $e->getCode(), $e);
139
        } finally {
140 6
            $this->logger->info("pochta.ru Single Tracking request: {$this->getClient()->__getLastRequest()}");
141 6
            $this->logger->info("pochta.ru Single Tracking response: {$this->getClient()->__getLastResponse()}");
142
        }
143
    }
144
145 4
    private function assembleTrackingRequestArguments(string $track, string $language, int $type): \SoapVar
146
    {
147 4
        return new \SoapVar([
148 4
            new \SoapVar([
149 4
                new \SoapVar($track, \XSD_STRING, '', '', 'Barcode', self::XML_NS_DATA),
150 4
                new \SoapVar($type, \XSD_STRING, '', '', 'MessageType', self::XML_NS_DATA),
151 4
                new \SoapVar($language, \XSD_STRING, '', '', 'Language', self::XML_NS_DATA),
152 4
            ], \SOAP_ENC_OBJECT, '', '', 'OperationHistoryRequest', self::XML_NS_DATA),
153 4
            $this->assembleAuthorizationHeader(),
154 4
        ], \SOAP_ENC_OBJECT);
155
    }
156
157 2
    private function assembleCashOnDeliveryRequestArguments(string $code, string $language): \SoapVar
158
    {
159 2
        $input = new CashOnDeliveryEventsRequest($code, $language);
160
161 2
        return new \SoapVar([
162 2
            new \SoapVar($input, \SOAP_ENC_OBJECT, '', '', 'PostalOrderEventsForMailInput', self::XML_NS_COD_DATA),
163 2
            $this->assembleAuthorizationHeader(),
164 2
        ], \SOAP_ENC_OBJECT);
165
    }
166
167 6
    private function assembleAuthorizationHeader(): \SoapVar
168
    {
169 6
        return new \SoapVar([
170 6
            new \SoapVar($this->login, \XSD_STRING, '', '', 'login', self::XML_NS_DATA),
171 6
            new \SoapVar($this->password, \XSD_STRING, '', '', 'password', self::XML_NS_DATA),
172 6
        ], \SOAP_ENC_OBJECT, '', '', 'AuthorizationHeader', self::XML_NS_DATA);
173
    }
174
}
175