1 | <?php |
||
2 | |||
3 | /** @noinspection PhpComposerExtensionStubsInspection */ |
||
4 | |||
5 | namespace CfdiUtils\ConsultaCfdiSat; |
||
6 | |||
7 | use RuntimeException; |
||
8 | use SoapClient; |
||
9 | use SoapVar; |
||
10 | use stdClass; |
||
11 | |||
12 | class WebService |
||
13 | { |
||
14 | /** @var SoapClient|null */ |
||
15 | private $soapClient; |
||
16 | |||
17 | /** @var Config */ |
||
18 | private $config; |
||
19 | |||
20 | 11 | public function __construct(Config $config = null) |
|
21 | { |
||
22 | 11 | $this->config = $config ?: new Config(); |
|
23 | } |
||
24 | |||
25 | 7 | public function getConfig(): Config |
|
26 | { |
||
27 | 7 | return $this->config; |
|
28 | } |
||
29 | |||
30 | 5 | public function getSoapClient(): SoapClient |
|
31 | { |
||
32 | 5 | if (! $this->soapClient instanceof SoapClient) { |
|
33 | 5 | $this->soapClient = $this->createSoapClient(); |
|
34 | } |
||
35 | 5 | return $this->soapClient; |
|
36 | } |
||
37 | |||
38 | 1 | public function destroySoapClient() |
|
39 | { |
||
40 | 1 | $this->soapClient = null; |
|
41 | } |
||
42 | |||
43 | 5 | protected function createSoapClient(): SoapClient |
|
44 | { |
||
45 | /* |
||
46 | * options.location: required to build the object |
||
47 | * |
||
48 | * options.uri: required to build the object |
||
49 | * |
||
50 | * options.use: SOAP_ENCODED (default) or SOAP_LITERAL |
||
51 | * Both works but SOAP_LITERAL is cleaner |
||
52 | * |
||
53 | * options.style: SOAP_RPC (default) or SOAP_DOCUMENT |
||
54 | * SOAP_DOCUMENT removes the method name from soap body |
||
55 | * |
||
56 | */ |
||
57 | 5 | $config = $this->getConfig(); |
|
58 | 5 | $soapOptions = [ |
|
59 | 5 | 'location' => $config->getServiceUrl(), |
|
60 | 5 | 'uri' => 'http://tempuri.org/', |
|
61 | 5 | 'style' => SOAP_RPC, |
|
62 | 5 | 'use' => SOAP_LITERAL, |
|
63 | 5 | 'soap_version' => SOAP_1_1, |
|
64 | 5 | 'exceptions' => 1, |
|
65 | 5 | 'stream_context' => stream_context_create([ |
|
66 | 5 | 'ssl' => [ |
|
67 | 5 | 'verify_peer' => $config->shouldVerifyPeer(), |
|
68 | 5 | ], |
|
69 | 5 | ]), |
|
70 | 5 | 'connection_timeout' => $config->getTimeout(), |
|
71 | 5 | 'trace' => false, // use this setting for development |
|
72 | 5 | ]; |
|
73 | |||
74 | 5 | return new SoapClient(null, $soapOptions); |
|
75 | } |
||
76 | |||
77 | 8 | public function request(RequestParameters $requestParameters): StatusResponse |
|
78 | { |
||
79 | 8 | $rawResponse = $this->doRequestConsulta($requestParameters->expression()); |
|
80 | |||
81 | 8 | if (! ($rawResponse instanceof stdClass)) { |
|
82 | 1 | throw new RuntimeException('The consulta web service did not return any result'); |
|
83 | } |
||
84 | 7 | $result = (array) $rawResponse; |
|
85 | 7 | if (! isset($result['CodigoEstatus'])) { |
|
86 | 1 | throw new RuntimeException('The consulta web service did not have expected ConsultaResult:CodigoEstatus'); |
|
87 | } |
||
88 | 6 | if (! isset($result['Estado'])) { |
|
89 | 1 | throw new RuntimeException('The consulta web service did not have expected ConsultaResult:Estado'); |
|
90 | } |
||
91 | 5 | return new StatusResponse( |
|
92 | 5 | $result['CodigoEstatus'], |
|
93 | 5 | $result['Estado'], |
|
94 | 5 | $result['EsCancelable'] ?? '', |
|
95 | 5 | $result['EstatusCancelacion'] ?? '', |
|
96 | 5 | $result['ValidacionEFOS'] ?? '' |
|
97 | 5 | ); |
|
98 | } |
||
99 | |||
100 | /** |
||
101 | * This method exists to be able to mock SOAP call |
||
102 | * |
||
103 | * @param string $expression |
||
104 | * @return null|stdClass |
||
105 | *@internal |
||
106 | */ |
||
107 | 4 | protected function doRequestConsulta(string $expression): ?stdClass |
|
108 | { |
||
109 | /** @var int $encoding Override because inspectors does not know that second argument can be NULL */ |
||
110 | 4 | $encoding = null; |
|
111 | 4 | return $this->getSoapClient()->__soapCall( |
|
112 | 4 | 'Consulta', |
|
113 | 4 | [new SoapVar($expression, $encoding, '', '', 'expresionImpresa', 'http://tempuri.org/')], |
|
114 | 4 | ['soapaction' => 'http://tempuri.org/IConsultaCFDIService/Consulta'] |
|
115 | 4 | ); |
|
116 | } |
||
117 | } |
||
118 |