These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace NFePHP\NFe; |
||
4 | |||
5 | /** |
||
6 | * Class responsible for communication with SEFAZ extends |
||
7 | * NFePHP\NFe\Common\Tools |
||
8 | * |
||
9 | * @category NFePHP |
||
10 | * @package NFePHP\NFe\Tools |
||
11 | * @copyright NFePHP Copyright (c) 2008-2020 |
||
12 | * @license http://www.gnu.org/licenses/lgpl.txt LGPLv3+ |
||
13 | * @license https://opensource.org/licenses/MIT MIT |
||
14 | * @license http://www.gnu.org/licenses/gpl.txt GPLv3+ |
||
15 | * @author Roberto L. Machado <linux.rlm at gmail dot com> |
||
16 | * @link http://github.com/nfephp-org/sped-nfe for the canonical source repository |
||
17 | */ |
||
18 | |||
19 | use NFePHP\Common\Strings; |
||
20 | use NFePHP\Common\Signer; |
||
21 | use NFePHP\Common\UFList; |
||
22 | use NFePHP\NFe\Common\Tools as ToolsCommon; |
||
23 | use RuntimeException; |
||
24 | use InvalidArgumentException; |
||
25 | |||
26 | class Tools extends ToolsCommon |
||
27 | { |
||
28 | const EVT_CONFIRMACAO = 210200; //only one per nfe seq=n |
||
29 | const EVT_CIENCIA = 210210; //only one per nfe seq=1 |
||
30 | const EVT_DESCONHECIMENTO = 210220; //only one per nfe seq=n |
||
31 | const EVT_NAO_REALIZADA = 210240; //only one per nfe but seq=n |
||
32 | const EVT_CCE = 110110; //many seq=n |
||
33 | const EVT_CANCELA = 110111; //only seq=1 |
||
34 | const EVT_CANCELASUBSTITUICAO = 110112; |
||
35 | const EVT_EPEC = 110140; //only seq=1 |
||
36 | const EVT_ATORINTERESSADO = 110150; |
||
37 | const EVT_COMPROVANTE_ENTREGA = 110130; |
||
38 | const EVT_CANCELAMENTO_COMPROVANTE_ENTREGA = 110131; |
||
39 | |||
40 | /** |
||
41 | * Request authorization to issue NFe in batch with one or more documents |
||
42 | * @param array $aXml array of nfe's xml |
||
43 | * @param string $idLote lote number |
||
44 | * @param int $indSinc flag to use synchronous communication |
||
45 | * @param bool $compactar flag to compress data with gzip |
||
46 | * @param array $xmls array with xmls substitutes if contigency is on |
||
47 | * @return string soap response xml |
||
48 | * @throws InvalidArgumentException |
||
49 | */ |
||
50 | public function sefazEnviaLote( |
||
51 | $aXml, |
||
52 | $idLote = '', |
||
53 | $indSinc = 0, |
||
54 | $compactar = false, |
||
55 | &$xmls = [] |
||
56 | ) { |
||
57 | if (!is_array($aXml)) { |
||
58 | throw new InvalidArgumentException('Envia Lote: XMLs de NF-e deve ser um array!'); |
||
59 | } |
||
60 | if ($indSinc == 1 && count($aXml) > 1) { |
||
61 | throw new InvalidArgumentException('Envio sincrono deve ser usado para enviar ' |
||
62 | . 'uma UNICA nota por vez. Você está tentando enviar varias.'); |
||
63 | } |
||
64 | $servico = 'NfeAutorizacao'; |
||
65 | $this->checkContingencyForWebServices($servico); |
||
66 | if ($this->contingency->type != '') { |
||
67 | // Em modo de contingencia esses XMLs deverão ser modificados e re-assinados e retornados |
||
68 | // no parametro $xmls para serem armazenados pelo aplicativo pois serão alterados. |
||
69 | foreach ($aXml as $doc) { |
||
70 | //corrigir o xml para o tipo de contigência setado |
||
71 | $xmls[] = $this->correctNFeForContingencyMode($doc); |
||
72 | } |
||
73 | $aXml = $xmls; |
||
74 | } |
||
75 | $ax = []; |
||
76 | foreach ($aXml as $xml) { |
||
77 | //verifica se o modelo do XML é o mesmo setado na classe |
||
78 | //gera um exception se não for |
||
79 | $this->checkModelFromXml($xml); |
||
80 | $ax[] = trim(preg_replace("/<\?xml.*?\?>/", "", $xml)); |
||
81 | } |
||
82 | $sxml = trim(implode("", $ax)); |
||
83 | $this->servico($servico, $this->config->siglaUF, $this->tpAmb); |
||
84 | $request = "<enviNFe xmlns=\"$this->urlPortal\" versao=\"$this->urlVersion\">" |
||
85 | . "<idLote>$idLote</idLote>" |
||
86 | . "<indSinc>$indSinc</indSinc>" |
||
87 | . "$sxml" |
||
88 | . "</enviNFe>"; |
||
89 | $this->isValid($this->urlVersion, $request, 'enviNFe'); |
||
90 | $this->lastRequest = $request; |
||
91 | //montagem dos dados da mensagem SOAP |
||
92 | $parameters = ['nfeDadosMsg' => $request]; |
||
93 | $body = "<nfeDadosMsg xmlns=\"$this->urlNamespace\">$request</nfeDadosMsg>"; |
||
94 | if ($compactar) { |
||
95 | $gzdata = base64_encode(gzencode($request, 9, FORCE_GZIP)); |
||
96 | $parameters = ['nfeDadosMsgZip' => $gzdata]; |
||
97 | $body = "<nfeDadosMsgZip xmlns=\"$this->urlNamespace\">$gzdata</nfeDadosMsgZip>"; |
||
98 | } |
||
99 | $this->lastResponse = $this->sendRequest($body, $parameters); |
||
100 | return $this->lastResponse; |
||
101 | } |
||
102 | |||
103 | /** |
||
104 | * Check status of Batch of NFe sent by receipt of this shipment |
||
105 | * @param string $recibo |
||
106 | * @param int $tpAmb |
||
107 | * @return string |
||
108 | * @throws InvalidArgumentException |
||
109 | */ |
||
110 | 1 | public function sefazConsultaRecibo($recibo, $tpAmb = null) |
|
111 | { |
||
112 | 1 | if (empty($recibo)) { |
|
113 | 1 | throw new InvalidArgumentException('Consulta Recibo: numero do recibo vazio!'); |
|
114 | } |
||
115 | if (empty($tpAmb)) { |
||
116 | $tpAmb = $this->tpAmb; |
||
117 | } |
||
118 | //carrega serviço |
||
119 | $servico = 'NfeRetAutorizacao'; |
||
120 | $this->checkContingencyForWebServices($servico); |
||
121 | $this->servico($servico, $this->config->siglaUF, $tpAmb); |
||
122 | if ($this->urlService == '') { |
||
123 | $msg = "A consulta de NFe nao esta disponivel na SEFAZ {$this->config->siglaUF}!"; |
||
124 | throw new RuntimeException($msg); |
||
125 | } |
||
126 | $request = "<consReciNFe xmlns=\"$this->urlPortal\" versao=\"$this->urlVersion\">" |
||
127 | . "<tpAmb>$tpAmb</tpAmb>" |
||
128 | . "<nRec>$recibo</nRec>" |
||
129 | . "</consReciNFe>"; |
||
130 | $this->isValid($this->urlVersion, $request, 'consReciNFe'); |
||
131 | $this->lastRequest = $request; |
||
132 | $parameters = ['nfeDadosMsg' => $request]; |
||
133 | $body = "<nfeDadosMsg xmlns=\"$this->urlNamespace\">$request</nfeDadosMsg>"; |
||
134 | $this->lastResponse = $this->sendRequest($body, $parameters); |
||
135 | return $this->lastResponse; |
||
136 | } |
||
137 | |||
138 | /** |
||
139 | * Check the NFe status for the 44-digit key and retrieve the protocol |
||
140 | * @param string $chave |
||
141 | * @param int $tpAmb |
||
142 | * @return string |
||
143 | * @throws InvalidArgumentException |
||
144 | */ |
||
145 | 3 | public function sefazConsultaChave($chave, $tpAmb = null) |
|
146 | { |
||
147 | 3 | if (empty($chave)) { |
|
148 | 1 | throw new InvalidArgumentException('Consulta chave: a chave esta vazia!'); |
|
149 | } |
||
150 | 2 | if (strlen($chave) != 44 || !is_numeric($chave)) { |
|
151 | 2 | throw new InvalidArgumentException("Consulta chave: chave \"$chave\" invalida!"); |
|
152 | } |
||
153 | $uf = UFList::getUFByCode(substr($chave, 0, 2)); |
||
154 | if (empty($tpAmb)) { |
||
155 | $tpAmb = $this->tpAmb; |
||
156 | } |
||
157 | //carrega serviço |
||
158 | $servico = 'NfeConsultaProtocolo'; |
||
159 | $this->checkContingencyForWebServices($servico); |
||
160 | $this->servico($servico, $uf, $tpAmb); |
||
161 | $request = "<consSitNFe xmlns=\"$this->urlPortal\" versao=\"$this->urlVersion\">" |
||
162 | . "<tpAmb>$tpAmb</tpAmb>" |
||
163 | . "<xServ>CONSULTAR</xServ>" |
||
164 | . "<chNFe>$chave</chNFe>" |
||
165 | . "</consSitNFe>"; |
||
166 | $this->isValid($this->urlVersion, $request, 'consSitNFe'); |
||
167 | $this->lastRequest = $request; |
||
168 | $parameters = ['nfeDadosMsg' => $request]; |
||
169 | $body = "<nfeDadosMsg xmlns=\"$this->urlNamespace\">$request</nfeDadosMsg>"; |
||
170 | $this->lastResponse = $this->sendRequest($body, $parameters); |
||
171 | return $this->lastResponse; |
||
172 | } |
||
173 | |||
174 | /** |
||
175 | * Request to disable one or an NFe sequence of a given series |
||
176 | * @param int $nSerie |
||
177 | * @param int $nIni |
||
178 | * @param int $nFin |
||
179 | * @param string $xJust |
||
180 | * @param int $tpAmb |
||
181 | * @param string $ano |
||
182 | * @return string |
||
183 | * @throws InvalidArgumentException |
||
184 | */ |
||
185 | public function sefazInutiliza($nSerie, $nIni, $nFin, $xJust, $tpAmb = null, $ano = null) |
||
186 | { |
||
187 | if (empty($nIni) || empty($nFin) || empty($xJust)) { |
||
188 | throw new InvalidArgumentException('Inutilizacao: parametros incompletos!'); |
||
189 | } |
||
190 | if (empty($tpAmb)) { |
||
191 | $tpAmb = $this->tpAmb; |
||
192 | } |
||
193 | $xJust = Strings::replaceUnacceptableCharacters($xJust); |
||
194 | $servico = 'NfeInutilizacao'; |
||
195 | $this->checkContingencyForWebServices($servico); |
||
196 | //carrega serviço |
||
197 | $this->servico($servico, $this->config->siglaUF, $tpAmb); |
||
198 | $cnpj = $this->config->cnpj; |
||
199 | $strAno = $ano; |
||
200 | if (empty($ano)) { |
||
201 | $strAno = (string) date('y'); |
||
202 | } |
||
203 | $strSerie = str_pad($nSerie, 3, '0', STR_PAD_LEFT); |
||
204 | $strInicio = str_pad($nIni, 9, '0', STR_PAD_LEFT); |
||
205 | $strFinal = str_pad($nFin, 9, '0', STR_PAD_LEFT); |
||
206 | $idInut = "ID" |
||
207 | . $this->urlcUF |
||
208 | . $strAno |
||
209 | . $cnpj |
||
210 | . $this->modelo |
||
211 | . $strSerie |
||
212 | . $strInicio |
||
213 | . $strFinal; |
||
214 | //limpa os caracteres indesejados da justificativa |
||
215 | $xJust = Strings::replaceUnacceptableCharacters($xJust); |
||
216 | //montagem do corpo da mensagem |
||
217 | $msg = "<inutNFe xmlns=\"$this->urlPortal\" versao=\"$this->urlVersion\">" . |
||
218 | "<infInut Id=\"$idInut\">" . |
||
219 | "<tpAmb>$tpAmb</tpAmb>" . |
||
220 | "<xServ>INUTILIZAR</xServ>" . |
||
221 | "<cUF>$this->urlcUF</cUF>" . |
||
222 | "<ano>$strAno</ano>" . |
||
223 | "<CNPJ>$cnpj</CNPJ>" . |
||
224 | "<mod>$this->modelo</mod>" . |
||
225 | "<serie>$nSerie</serie>" . |
||
226 | "<nNFIni>$nIni</nNFIni>" . |
||
227 | "<nNFFin>$nFin</nNFFin>" . |
||
228 | "<xJust>$xJust</xJust>" . |
||
229 | "</infInut></inutNFe>"; |
||
230 | //assina a solicitação |
||
231 | $request = Signer::sign( |
||
232 | $this->certificate, |
||
233 | $msg, |
||
234 | 'infInut', |
||
235 | 'Id', |
||
236 | $this->algorithm, |
||
237 | $this->canonical |
||
238 | ); |
||
239 | $request = Strings::clearXmlString($request, true); |
||
240 | $this->isValid($this->urlVersion, $request, 'inutNFe'); |
||
241 | $this->lastRequest = $request; |
||
242 | $parameters = ['nfeDadosMsg' => $request]; |
||
243 | $body = "<nfeDadosMsg xmlns=\"$this->urlNamespace\">$request</nfeDadosMsg>"; |
||
244 | $this->lastResponse = $this->sendRequest($body, $parameters); |
||
245 | return $this->lastResponse; |
||
246 | } |
||
247 | |||
248 | /** |
||
249 | * Search for the registration data of an NFe issuer, |
||
250 | * if in contingency mode this service will cause a |
||
251 | * Exception and remember not all Sefaz have this service available, |
||
252 | * so it will not work in some cases. |
||
253 | * @param string $uf federation unit (abbreviation) |
||
254 | * @param string $cnpj CNPJ number (optional) |
||
255 | * @param string $iest IE number (optional) |
||
256 | * @param string $cpf CPF number (optional) |
||
257 | * @return string xml soap response |
||
258 | * @throws InvalidArgumentException |
||
259 | */ |
||
260 | public function sefazCadastro($uf, $cnpj = '', $iest = '', $cpf = '') |
||
261 | { |
||
262 | $filter = ''; |
||
263 | if (!empty($cnpj)) { |
||
264 | $filter = "<CNPJ>$cnpj</CNPJ>"; |
||
265 | } elseif (!empty($iest)) { |
||
266 | $filter = "<IE>$iest</IE>"; |
||
267 | } elseif (!empty($cpf)) { |
||
268 | $filter = "<CPF>$cpf</CPF>"; |
||
269 | } |
||
270 | if (empty($uf) || empty($filter)) { |
||
271 | throw new InvalidArgumentException('Sigla UF esta vazia ou CNPJ+IE+CPF vazios!'); |
||
272 | } |
||
273 | //carrega serviço |
||
274 | $servico = 'NfeConsultaCadastro'; |
||
275 | $this->checkContingencyForWebServices($servico); |
||
276 | $this->servico($servico, $uf, $this->tpAmb, true); |
||
277 | $request = "<ConsCad xmlns=\"$this->urlPortal\" versao=\"$this->urlVersion\">" |
||
278 | . "<infCons>" |
||
279 | . "<xServ>CONS-CAD</xServ>" |
||
280 | . "<UF>$uf</UF>" |
||
281 | . "$filter" |
||
282 | . "</infCons>" |
||
283 | . "</ConsCad>"; |
||
284 | if (strtoupper($uf) == 'MT') { |
||
285 | $request = "<nfeDadosMsg>$request</nfeDadosMsg>" ; |
||
286 | } |
||
287 | $this->isValid($this->urlVersion, $request, 'consCad'); |
||
288 | $this->lastRequest = $request; |
||
289 | $parameters = ['nfeDadosMsg' => $request]; |
||
290 | if ($this->urlVersion === '2.00') { |
||
291 | $this->objHeader = new \SOAPHeader( |
||
292 | $this->urlNamespace, |
||
293 | 'nfeCabecMsg', |
||
294 | ['cUF' => $this->urlcUF, 'versaoDados' => $this->urlVersion] |
||
295 | ); |
||
296 | } |
||
297 | $body = "<nfeDadosMsg xmlns=\"$this->urlNamespace\">$request</nfeDadosMsg>"; |
||
298 | $this->lastResponse = $this->sendRequest($body, $parameters); |
||
299 | return $this->lastResponse; |
||
300 | } |
||
301 | |||
302 | /** |
||
303 | * Check services status SEFAZ/SVC |
||
304 | * If $uf is empty use normal check with contingency |
||
305 | * If $uf is NOT empty ignore contingency mode |
||
306 | * @param string $uf initials of federation unit |
||
307 | * @param int $tpAmb |
||
308 | * @return string xml soap response |
||
309 | */ |
||
310 | public function sefazStatus($uf = '', $tpAmb = null) |
||
311 | { |
||
312 | if (empty($tpAmb)) { |
||
313 | $tpAmb = $this->tpAmb; |
||
314 | } |
||
315 | $ignoreContingency = true; |
||
316 | if (empty($uf)) { |
||
317 | $uf = $this->config->siglaUF; |
||
318 | $ignoreContingency = false; |
||
319 | } |
||
320 | $servico = 'NfeStatusServico'; |
||
321 | $this->checkContingencyForWebServices($servico); |
||
322 | $this->servico($servico, $uf, $tpAmb, $ignoreContingency); |
||
323 | $request = "<consStatServ xmlns=\"$this->urlPortal\" versao=\"$this->urlVersion\">" |
||
324 | . "<tpAmb>$tpAmb</tpAmb>" |
||
325 | . "<cUF>$this->urlcUF</cUF>" |
||
326 | . "<xServ>STATUS</xServ>" |
||
327 | . "</consStatServ>"; |
||
328 | $this->isValid($this->urlVersion, $request, 'consStatServ'); |
||
329 | $this->lastRequest = $request; |
||
330 | $parameters = ['nfeDadosMsg' => $request]; |
||
331 | $body = "<nfeDadosMsg xmlns=\"$this->urlNamespace\">$request</nfeDadosMsg>"; |
||
332 | $this->lastResponse = $this->sendRequest($body, $parameters); |
||
333 | return $this->lastResponse; |
||
334 | } |
||
335 | |||
336 | /** |
||
337 | * Service for the distribution of summary information and |
||
338 | * electronic tax documents of interest to an actor. |
||
339 | * @param integer $ultNSU last NSU number recived |
||
340 | * @param integer $numNSU NSU number you wish to consult |
||
341 | * @param string $fonte data source 'AN' and for some cases it may be 'RS' |
||
342 | * @return string |
||
343 | */ |
||
344 | public function sefazDistDFe($ultNSU = 0, $numNSU = 0, $fonte = 'AN') |
||
345 | { |
||
346 | //carrega serviço |
||
347 | $servico = 'NfeDistribuicaoDFe'; |
||
348 | $this->checkContingencyForWebServices($servico); |
||
349 | $this->servico($servico, $fonte, $this->tpAmb, true); |
||
350 | $cUF = UFList::getCodeByUF($this->config->siglaUF); |
||
351 | $cnpj = $this->config->cnpj; |
||
352 | $ultNSU = str_pad($ultNSU, 15, '0', STR_PAD_LEFT); |
||
353 | $tagNSU = "<distNSU><ultNSU>$ultNSU</ultNSU></distNSU>"; |
||
354 | if ($numNSU != 0) { |
||
355 | $numNSU = str_pad($numNSU, 15, '0', STR_PAD_LEFT); |
||
356 | $tagNSU = "<consNSU><NSU>$numNSU</NSU></consNSU>"; |
||
357 | } |
||
358 | //monta a consulta |
||
359 | $consulta = "<distDFeInt xmlns=\"$this->urlPortal\" versao=\"$this->urlVersion\">" |
||
360 | . "<tpAmb>".$this->tpAmb."</tpAmb>" |
||
361 | . "<cUFAutor>$cUF</cUFAutor>"; |
||
362 | if ($this->typePerson === 'J') { |
||
363 | $consulta .= "<CNPJ>$cnpj</CNPJ>"; |
||
364 | } else { |
||
365 | $consulta .= "<CPF>$cnpj</CPF>"; |
||
366 | } |
||
367 | $consulta .= "$tagNSU" |
||
368 | . "</distDFeInt>"; |
||
369 | //valida o xml da requisição |
||
370 | $this->isValid($this->urlVersion, $consulta, 'distDFeInt'); |
||
371 | $this->lastRequest = $consulta; |
||
372 | //montagem dos dados da mensagem SOAP |
||
373 | $request = "<nfeDadosMsg xmlns=\"$this->urlNamespace\">$consulta</nfeDadosMsg>"; |
||
374 | $parameters = ['nfeDistDFeInteresse' => $request]; |
||
375 | $body = "<nfeDistDFeInteresse xmlns=\"$this->urlNamespace\">" |
||
376 | . $request |
||
377 | . "</nfeDistDFeInteresse>"; |
||
378 | //este webservice não requer cabeçalho |
||
379 | $this->objHeader = null; |
||
380 | $this->lastResponse = $this->sendRequest($body, $parameters); |
||
381 | return $this->lastResponse; |
||
382 | } |
||
383 | |||
384 | /** |
||
385 | * Request authorization for Letter of Correction |
||
386 | * @param string $chave |
||
387 | * @param string $xCorrecao |
||
388 | * @param int $nSeqEvento |
||
389 | * @return string |
||
390 | * @throws InvalidArgumentException |
||
391 | */ |
||
392 | public function sefazCCe($chave, $xCorrecao, $nSeqEvento = 1) |
||
393 | { |
||
394 | if (empty($chave) || empty($xCorrecao)) { |
||
395 | throw new InvalidArgumentException('CC-e: chave ou motivo da correcao vazio!'); |
||
396 | } |
||
397 | $uf = $this->validKeyByUF($chave); |
||
398 | $xCorrecao = Strings::replaceUnacceptableCharacters(substr(trim($xCorrecao), 0, 1000)); |
||
399 | $xCondUso = 'A Carta de Correcao e disciplinada pelo paragrafo ' |
||
400 | . '1o-A do art. 7o do Convenio S/N, de 15 de dezembro de 1970 ' |
||
401 | . 'e pode ser utilizada para regularizacao de erro ocorrido ' |
||
402 | . 'na emissao de documento fiscal, desde que o erro nao esteja ' |
||
403 | . 'relacionado com: I - as variaveis que determinam o valor ' |
||
404 | . 'do imposto tais como: base de calculo, aliquota, ' |
||
405 | . 'diferenca de preco, quantidade, valor da operacao ou da ' |
||
406 | . 'prestacao; II - a correcao de dados cadastrais que implique ' |
||
407 | . 'mudanca do remetente ou do destinatario; III - a data de ' |
||
408 | . 'emissao ou de saida.'; |
||
409 | $tagAdic = "<xCorrecao>" |
||
410 | . $xCorrecao |
||
411 | . "</xCorrecao><xCondUso>$xCondUso</xCondUso>"; |
||
412 | return $this->sefazEvento($uf, $chave, self::EVT_CCE, $nSeqEvento, $tagAdic); |
||
413 | } |
||
414 | |||
415 | /** |
||
416 | * Evento do Ator Interessado |
||
417 | * NOTA: NT2020.007_v1.00a |
||
418 | * @param \stdClass $std |
||
419 | * @return string |
||
420 | */ |
||
421 | public function sefazAtorInteressado($std) |
||
422 | { |
||
423 | $xCondUso = 'O emitente ou destinatário da NF-e, declara que permite o ' |
||
424 | . 'transportador declarado no campo CNPJ/CPF deste evento a ' |
||
425 | . 'autorizar os transportadores subcontratados ou redespachados ' |
||
426 | . 'a terem acesso ao download da NFe'; |
||
427 | $cUF = UFList::getCodeByUF($this->config->siglaUF); |
||
428 | $tagAdic = "<cOrgaoAutor>{$cUF}</cOrgaoAutor>" |
||
429 | . "<tpAutor>{$std->tpAutor}</tpAutor>" |
||
430 | . "<verAplic>{$std->verAplic}</verAplic>" |
||
431 | . "<autXML>"; |
||
432 | $tagAdic .= !empty($std->CNPJ) |
||
433 | ? "<CNPJ>{$std->CNPJ}</CNPJ>" |
||
434 | : "<CPF>{$std->CPF}</CPF>"; |
||
435 | $tagAdic .= "<tpAutorizacao>{$std->tpAutorizacao}</tpAutorizacao>" |
||
436 | . "</autXML>"; |
||
437 | $tagAdic .= "<xCondUso>$xCondUso</xCondUso>"; |
||
438 | return $this->sefazEvento($uf, $std->chNFe, self::EVT_ATORINTERESSADO, $nSeqEvento, $tagAdic); |
||
0 ignored issues
–
show
|
|||
439 | } |
||
440 | |||
441 | /** |
||
442 | * Request extension of the term of return of products of an NF-e of |
||
443 | * consignment for industrialization to order with suspension of ICMS |
||
444 | * in interstate operations |
||
445 | * @param string $chNFe |
||
446 | * @param string $nProt |
||
447 | * @param integer $tipo 1-primerio prazo, 2-segundo prazo |
||
448 | * @param array $itens |
||
449 | * @param integer $nSeqEvento |
||
450 | * @return string |
||
451 | */ |
||
452 | public function sefazEPP( |
||
453 | $chNFe, |
||
454 | $nProt, |
||
455 | $itens = array(), |
||
456 | $tipo = 1, |
||
457 | $nSeqEvento = 1 |
||
458 | ) { |
||
459 | $uf = UFList::getUFByCode(substr($chNFe, 0, 2)); |
||
460 | $tpEvento = 111500; |
||
461 | if ($tipo == 2) { |
||
462 | $tpEvento = 111501; |
||
463 | } |
||
464 | $tagAdic = "<nProt>$nProt</nProt>"; |
||
465 | foreach ($itens as $item) { |
||
466 | $tagAdic .= "<itemPedido numItem=\"" |
||
467 | . $item[0] |
||
468 | . "\"><qtdeItem>" |
||
469 | . $item[1] |
||
470 | ."</qtdeItem></itemPedido>"; |
||
471 | } |
||
472 | return $this->sefazEvento( |
||
473 | $uf, |
||
474 | $chNFe, |
||
475 | $tpEvento, |
||
476 | $nSeqEvento, |
||
477 | $tagAdic |
||
478 | ); |
||
479 | } |
||
480 | |||
481 | /** |
||
482 | * Request the cancellation of the request for an extension of the term |
||
483 | * of return of products of an NF-e of consignment for industrialization |
||
484 | * by order with suspension of ICMS in interstate operations |
||
485 | * @param string $chave |
||
486 | * @param string $nProt |
||
487 | * @param integer $nSeqEvento |
||
488 | * @return string |
||
489 | * @throws InvalidArgumentException |
||
490 | */ |
||
491 | public function sefazECPP($chave, $nProt, $nSeqEvento = 1) |
||
492 | { |
||
493 | if (empty($chave) || empty($nProt)) { |
||
494 | throw new InvalidArgumentException('A chave ou o numero do protocolo estao vazios!'); |
||
495 | } |
||
496 | $uf = UFList::getUFByCode(substr($chave, 0, 2)); |
||
497 | $tpEvento = 111502; |
||
498 | $origEvent = 111500; |
||
499 | if ($nSeqEvento == 2) { |
||
500 | $tpEvento = 111503; |
||
501 | $origEvent = 111501; |
||
502 | } |
||
503 | $sSeqEvento = str_pad($nSeqEvento, 2, "0", STR_PAD_LEFT); |
||
504 | $idPedidoCancelado = "ID$origEvent$chave$sSeqEvento"; |
||
505 | $tagAdic = "<idPedidoCancelado>" |
||
506 | . "$idPedidoCancelado" |
||
507 | . "</idPedidoCancelado>" |
||
508 | . "<nProt>$nProt</nProt>"; |
||
509 | return $this->sefazEvento($uf, $chave, $tpEvento, $nSeqEvento, $tagAdic); |
||
510 | } |
||
511 | |||
512 | /** |
||
513 | * Requires nfe cancellation |
||
514 | * @param string $chave key of NFe |
||
515 | * @param string $xJust justificative 255 characters max |
||
516 | * @param string $nProt protocol number |
||
517 | * @return string |
||
518 | * @throws InvalidArgumentException |
||
519 | */ |
||
520 | public function sefazCancela($chave, $xJust, $nProt) |
||
521 | { |
||
522 | if (empty($chave) || empty($xJust) || empty($nProt)) { |
||
523 | throw new InvalidArgumentException('Cancelamento: chave, just ou numprot vazio!'); |
||
524 | } |
||
525 | $uf = $this->validKeyByUF($chave); |
||
526 | $xJust = Strings::replaceUnacceptableCharacters(substr(trim($xJust), 0, 255)); |
||
527 | $nSeqEvento = 1; |
||
528 | $tagAdic = "<nProt>$nProt</nProt><xJust>$xJust</xJust>"; |
||
529 | return $this->sefazEvento($uf, $chave, self::EVT_CANCELA, $nSeqEvento, $tagAdic); |
||
530 | } |
||
531 | |||
532 | /** |
||
533 | * Requires nfe cancellation by substitution |
||
534 | * @param string $chave key of NFe |
||
535 | * @param string $xJust justificative 255 characters max |
||
536 | * @param string $nProt protocol number |
||
537 | * @param string $chNFeRef key of New NFe |
||
538 | * @param string $verAplic version of applicative |
||
539 | * @return string |
||
540 | * @throws InvalidArgumentException |
||
541 | */ |
||
542 | public function sefazCancelaPorSubstituicao($chave, $xJust, $nProt, $chNFeRef, $verAplic) |
||
543 | { |
||
544 | if ($this->modelo != 65) { |
||
545 | throw new InvalidArgumentException( |
||
546 | 'Cancelamento pro Substituição deve ser usado apenas para ' |
||
547 | . 'operações com modelo 65 NFCe' |
||
548 | ); |
||
549 | } |
||
550 | if (empty($chave) || empty($xJust) || empty($nProt) |
||
551 | || empty($chNFeRef) || empty($verAplic)) { |
||
552 | throw new InvalidArgumentException( |
||
553 | 'CancelamentoPorSubs: chave da NFCe cancelada, justificativa, ' |
||
554 | . 'protocolo, chave da NFCe substituta, ou versão do aplicativo ' |
||
555 | . 'emissor não podem ser vazios!' |
||
556 | ); |
||
557 | } |
||
558 | $uf = $this->validKeyByUF($chave); |
||
559 | $xJust = Strings::replaceUnacceptableCharacters(substr(trim($xJust), 0, 255)); |
||
560 | $nSeqEvento = 1; |
||
561 | $cOrgao = substr($chave, 0, 2); |
||
562 | $tagAdic = "<cOrgaoAutor>$cOrgao</cOrgaoAutor>" |
||
563 | . "<tpAutor>1</tpAutor>" |
||
564 | . "<verAplic>$verAplic</verAplic>" |
||
565 | . "<nProt>$nProt</nProt>" |
||
566 | . "<xJust>$xJust</xJust>" |
||
567 | . "<chNFeRef>$chNFeRef</chNFeRef>"; |
||
568 | return $this->sefazEvento($uf, $chave, self::EVT_CANCELASUBSTITUICAO, $nSeqEvento, $tagAdic); |
||
569 | } |
||
570 | |||
571 | /** |
||
572 | * Request the registration of the manifestation of recipient |
||
573 | * @param string $chave |
||
574 | * @param int $tpEvento |
||
575 | * @param string $xJust Justification for not carrying out the operation |
||
576 | * @param int $nSeqEvento |
||
577 | * @return string |
||
578 | * @throws InvalidArgumentException |
||
579 | */ |
||
580 | public function sefazManifesta($chave, $tpEvento, $xJust = '', $nSeqEvento = 1) |
||
581 | { |
||
582 | if (empty($chave) || empty($tpEvento)) { |
||
583 | throw new InvalidArgumentException('Manifestacao: chave ou tipo de evento vazio!'); |
||
584 | } |
||
585 | $tagAdic = ''; |
||
586 | if ($tpEvento == self::EVT_NAO_REALIZADA) { |
||
587 | $xJust = Strings::replaceUnacceptableCharacters(substr(trim($xJust), 0, 255)); |
||
588 | $tagAdic = "<xJust>$xJust</xJust>"; |
||
589 | } |
||
590 | return $this->sefazEvento('AN', $chave, $tpEvento, $nSeqEvento, $tagAdic); |
||
591 | } |
||
592 | |||
593 | /** |
||
594 | * Request the registration of the manifestation of recipient in batch |
||
595 | * @param \stdClass $std |
||
596 | * @return string |
||
597 | * @throws InvalidArgumentException |
||
598 | * @throws RuntimeException |
||
599 | */ |
||
600 | public function sefazManifestaLote(\stdClass $std) |
||
601 | { |
||
602 | $allowed = [ |
||
603 | self::EVT_CONFIRMACAO, |
||
604 | self::EVT_CIENCIA, |
||
605 | self::EVT_DESCONHECIMENTO, |
||
606 | self::EVT_NAO_REALIZADA, |
||
607 | ]; |
||
608 | if (empty($std) || empty($std->evento)) { |
||
609 | throw new InvalidArgumentException('Manifestacao: parametro "std" ou evento estao vazios!'); |
||
610 | } |
||
611 | if (count($std->evento) > 20) { |
||
612 | throw new RuntimeException('Manifestacao: o lote de eventos esta limitado a 20!'); |
||
613 | } |
||
614 | $evt = new \stdClass(); |
||
615 | $i = 0; |
||
616 | foreach ($std->evento as $s) { |
||
617 | if (!in_array($s->tpEvento, $allowed)) { // se o evento não estiver entre os permitidos ignore |
||
618 | continue; |
||
619 | } |
||
620 | $tagAdic = ''; |
||
621 | if ($s->tpEvento == self::EVT_NAO_REALIZADA) { |
||
622 | $xJust = Strings::replaceUnacceptableCharacters(substr(trim($s->xJust), 0, 255)); |
||
623 | $tagAdic = "<xJust>$xJust</xJust>"; |
||
624 | } |
||
625 | $evt->evento[$i] = new \stdClass(); |
||
626 | $evt->evento[$i]->chave = $s->chNFe; |
||
627 | $evt->evento[$i]->tpEvento = $s->tpEvento; |
||
628 | $evt->evento[$i]->nSeqEvento = $s->nSeqEvento; |
||
629 | $evt->evento[$i]->tagAdic = $tagAdic; |
||
630 | $i++; |
||
631 | } |
||
632 | return $this->sefazEventoLote('AN', $evt); |
||
633 | } |
||
634 | |||
635 | /** |
||
636 | * Send event for delivery receipt |
||
637 | * @param \stdClass $std |
||
638 | * @return string |
||
639 | */ |
||
640 | public function sefazComprovanteEntrega(\stdClass $std) |
||
641 | { |
||
642 | $hash = sha1($std->chave . $std->imagem); |
||
643 | $datahash = date('Y-m-d\TH:i:sP'); |
||
644 | $cod = UFList::getCodeByUF($this->config->siglaUF); |
||
645 | $tagAdic = "<cOrgaoAutor>{$cod}</cOrgaoAutor>" |
||
646 | . "<tpAutor>1</tpAutor>" |
||
647 | . "<verAplic>{$std->verAplic}</verAplic>" |
||
648 | . "<dhEntrega>{$std->data_recebimento}</dhEntrega>" |
||
649 | . "<nDoc>{$std->documento_recebedor}</nDoc>" |
||
650 | . "<xNome>{$std->nome_recebedor}</xNome>"; |
||
651 | if (!empty($std->latitude) && !empty($std->longitude)) { |
||
652 | $tagAdic .= "<latGPS>{$std->latitude}</latGPS>" |
||
653 | . "<longGPS>{$std->longitude}</longGPS>"; |
||
654 | } |
||
655 | $tagAdic .= "<hashComprovante>{$hash}</hashComprovante>" |
||
656 | . "<dhHashComprovante>{$datahash}</dhHashComprovante>"; |
||
657 | $tpEvento = self::EVT_COMPROVANTE_ENTREGA; |
||
658 | if ($std->cancelar == true) { |
||
659 | $tpEvento = self::EVT_CANCELAMENTO_COMPROVANTE_ENTREGA; |
||
660 | } |
||
661 | $chave = $std->chave; |
||
662 | $nSeqEvento = 1; |
||
663 | return $this->sefazEvento('AN', $chave, $tpEvento, $nSeqEvento, $tagAdic); |
||
664 | } |
||
665 | |||
666 | /** |
||
667 | * Send event to SEFAZ in batch |
||
668 | * @param string $uf |
||
669 | * @param \stdClass $std |
||
670 | * @return string |
||
671 | * @throws RuntimeException |
||
672 | * @throws InvalidArgumentException |
||
673 | */ |
||
674 | public function sefazEventoLote($uf, \stdClass $std) |
||
675 | { |
||
676 | if (empty($uf) || empty($std)) { |
||
677 | throw new InvalidArgumentException('Evento Lote: UF ou parametro "std" vazio!'); |
||
678 | } |
||
679 | if (count($std->evento) > 20) { |
||
680 | throw new RuntimeException('Evento Lote: o lote de eventos esta limitado a 20!'); |
||
681 | } |
||
682 | $servico = 'RecepcaoEvento'; |
||
683 | $this->checkContingencyForWebServices($servico); |
||
684 | $this->servico($servico, $uf, $this->tpAmb, false); |
||
685 | $batchRequest = ''; |
||
686 | foreach ($std->evento as $evt) { |
||
687 | if ($evt->tpEvento == self::EVT_EPEC) { |
||
688 | continue; //não é possivel enviar EPEC com outros eventos |
||
689 | } |
||
690 | $ev = $this->tpEv($evt->tpEvento); |
||
691 | $descEvento = $ev->desc; |
||
692 | $cnpj = $this->config->cnpj; |
||
693 | $dt = new \DateTime('now', new \DateTimeZone($this->timezone)); |
||
694 | $dhEvento = $dt->format('Y-m-d\TH:i:sP'); |
||
695 | $sSeqEvento = str_pad($evt->nSeqEvento, 2, "0", STR_PAD_LEFT); |
||
696 | $eventId = "ID".$evt->tpEvento.$evt->chave.$sSeqEvento; |
||
697 | $cOrgao = UFList::getCodeByUF($uf); |
||
698 | $request = "<evento xmlns=\"$this->urlPortal\" versao=\"$this->urlVersion\">" |
||
699 | . "<infEvento Id=\"$eventId\">" |
||
700 | . "<cOrgao>$cOrgao</cOrgao>" |
||
701 | . "<tpAmb>$this->tpAmb</tpAmb>"; |
||
702 | if ($this->typePerson === 'J') { |
||
703 | $request .= "<CNPJ>$cnpj</CNPJ>"; |
||
704 | } else { |
||
705 | $request .= "<CPF>$cnpj</CPF>"; |
||
706 | } |
||
707 | $request .= "<chNFe>$evt->chave</chNFe>" |
||
708 | . "<dhEvento>$dhEvento</dhEvento>" |
||
709 | . "<tpEvento>$evt->tpEvento</tpEvento>" |
||
710 | . "<nSeqEvento>$evt->nSeqEvento</nSeqEvento>" |
||
711 | . "<verEvento>$this->urlVersion</verEvento>" |
||
712 | . "<detEvento versao=\"$this->urlVersion\">" |
||
713 | . "<descEvento>$descEvento</descEvento>" |
||
714 | . "$evt->tagAdic" |
||
715 | . "</detEvento>" |
||
716 | . "</infEvento>" |
||
717 | . "</evento>"; |
||
718 | //assinatura dos dados |
||
719 | $request = Signer::sign( |
||
720 | $this->certificate, |
||
721 | $request, |
||
722 | 'infEvento', |
||
723 | 'Id', |
||
724 | $this->algorithm, |
||
725 | $this->canonical |
||
726 | ); |
||
727 | $batchRequest .= Strings::clearXmlString($request, true); |
||
728 | } |
||
729 | $dt = new \DateTime('now', new \DateTimeZone($this->timezone)); |
||
730 | $lote = $dt->format('YmdHis') . rand(0, 9); |
||
731 | $request = "<envEvento xmlns=\"$this->urlPortal\" versao=\"$this->urlVersion\">" |
||
732 | . "<idLote>$lote</idLote>" |
||
733 | . $batchRequest |
||
734 | . "</envEvento>"; |
||
735 | $this->isValid($this->urlVersion, $request, 'envEvento'); |
||
736 | $this->lastRequest = $request; |
||
737 | $parameters = ['nfeDadosMsg' => $request]; |
||
738 | $body = "<nfeDadosMsg xmlns=\"$this->urlNamespace\">$request</nfeDadosMsg>"; |
||
739 | $this->lastResponse = $this->sendRequest($body, $parameters); |
||
740 | return $this->lastResponse; |
||
741 | } |
||
742 | |||
743 | /** |
||
744 | * Request authorization for issuance in contingency EPEC |
||
745 | * @param string $xml |
||
746 | * @return string |
||
747 | * @throws InvalidArgumentException |
||
748 | * @throws RuntimeException |
||
749 | */ |
||
750 | public function sefazEPEC(&$xml) |
||
751 | { |
||
752 | if (empty($xml)) { |
||
753 | throw new InvalidArgumentException('EPEC: parametro xml esta vazio!'); |
||
754 | } |
||
755 | $nSeqEvento = 1; |
||
756 | if ($this->contingency->type !== 'EPEC') { |
||
757 | throw new RuntimeException('A contingencia EPEC deve estar ativada!'); |
||
758 | } |
||
759 | $xml = $this->correctNFeForContingencyMode($xml); |
||
760 | $dom = new \DOMDocument('1.0', 'UTF-8'); |
||
761 | $dom->preserveWhiteSpace = false; |
||
762 | $dom->formatOutput = false; |
||
763 | $dom->loadXML($xml); |
||
764 | $infNFe = $dom->getElementsByTagName('infNFe')->item(0); |
||
765 | $emit = $dom->getElementsByTagName('emit')->item(0); |
||
766 | $dest = $dom->getElementsByTagName('dest')->item(0); |
||
767 | $cOrgaoAutor = UFList::getCodeByUF($this->config->siglaUF); |
||
768 | $chNFe = substr($infNFe->getAttribute('Id'), 3, 44); |
||
769 | // EPEC |
||
770 | $dhEmi = $dom->getElementsByTagName('dhEmi')->item(0)->nodeValue; |
||
771 | $tpNF = $dom->getElementsByTagName('tpNF')->item(0)->nodeValue; |
||
772 | $emitIE = $emit->getElementsByTagName('IE')->item(0)->nodeValue; |
||
773 | $destUF = $dest->getElementsByTagName('UF')->item(0)->nodeValue; |
||
774 | $total = $dom->getElementsByTagName('total')->item(0); |
||
775 | $vNF = $total->getElementsByTagName('vNF')->item(0)->nodeValue; |
||
776 | $vICMS = $total->getElementsByTagName('vICMS')->item(0)->nodeValue; |
||
777 | $vST = $total->getElementsByTagName('vST')->item(0)->nodeValue; |
||
778 | $dID = !empty($dest->getElementsByTagName('CNPJ')->item(0)) ? |
||
779 | $dest->getElementsByTagName('CNPJ')->item(0)->nodeValue : null; |
||
780 | if (!empty($dID)) { |
||
781 | $destID = "<CNPJ>$dID</CNPJ>"; |
||
782 | } else { |
||
783 | $dID = $dest->getElementsByTagName('CPF')->item(0)->nodeValue; |
||
784 | if (!empty($dID)) { |
||
785 | $destID = "<CPF>$dID</CPF>"; |
||
786 | } else { |
||
787 | $dID = $dest->getElementsByTagName('idEstrangeiro') |
||
788 | ->item(0) |
||
789 | ->nodeValue; |
||
790 | $destID = "<idEstrangeiro>$dID</idEstrangeiro>"; |
||
791 | } |
||
792 | } |
||
793 | $dIE = !empty($dest->getElementsByTagName('IE')->item(0)->nodeValue) ? |
||
794 | $dest->getElementsByTagName('IE')->item(0)->nodeValue : ''; |
||
795 | $destIE = ''; |
||
796 | if (!empty($dIE)) { |
||
797 | $destIE = "<IE>$dIE</IE>"; |
||
798 | } |
||
799 | $tagAdic = "<cOrgaoAutor>$cOrgaoAutor</cOrgaoAutor>" |
||
800 | . "<tpAutor>1</tpAutor>" |
||
801 | . "<verAplic>$this->verAplic</verAplic>" |
||
802 | . "<dhEmi>$dhEmi</dhEmi>" |
||
803 | . "<tpNF>$tpNF</tpNF>" |
||
804 | . "<IE>$emitIE</IE>" |
||
805 | . "<dest>" |
||
806 | . "<UF>$destUF</UF>" |
||
807 | . $destID |
||
808 | . $destIE |
||
809 | . "<vNF>$vNF</vNF>" |
||
810 | . "<vICMS>$vICMS</vICMS>" |
||
811 | . "<vST>$vST</vST>" |
||
812 | . "</dest>"; |
||
813 | |||
814 | return $this->sefazEvento('AN', $chNFe, self::EVT_EPEC, $nSeqEvento, $tagAdic); |
||
815 | } |
||
816 | |||
817 | /** |
||
818 | * Send event to SEFAZ |
||
819 | * @param string $uf |
||
820 | * @param string $chave |
||
821 | * @param int $tpEvento |
||
822 | * @param int $nSeqEvento |
||
823 | * @param string $tagAdic |
||
824 | * @return string |
||
825 | */ |
||
826 | public function sefazEvento( |
||
827 | $uf, |
||
828 | $chave, |
||
829 | $tpEvento, |
||
830 | $nSeqEvento = 1, |
||
831 | $tagAdic = '' |
||
832 | ) { |
||
833 | $ignore = $tpEvento == self::EVT_EPEC; |
||
834 | $servico = 'RecepcaoEvento'; |
||
835 | $this->checkContingencyForWebServices($servico); |
||
836 | $this->servico($servico, $uf, $this->tpAmb, $ignore); |
||
837 | $ev = $this->tpEv($tpEvento); |
||
838 | $descEvento = $ev->desc; |
||
839 | $cnpj = isset($this->config->cnpj) ? $this->config->cnpj : ''; |
||
840 | $dt = new \DateTime(date("Y-m-d H:i:sP"), new \DateTimeZone($this->timezone)); |
||
841 | $dhEvento = $dt->format('Y-m-d\TH:i:sP'); |
||
842 | $sSeqEvento = str_pad($nSeqEvento, 2, "0", STR_PAD_LEFT); |
||
843 | $eventId = "ID".$tpEvento.$chave.$sSeqEvento; |
||
844 | $cOrgao = UFList::getCodeByUF($uf); |
||
845 | $request = "<evento xmlns=\"$this->urlPortal\" versao=\"$this->urlVersion\">" |
||
846 | . "<infEvento Id=\"$eventId\">" |
||
847 | . "<cOrgao>$cOrgao</cOrgao>" |
||
848 | . "<tpAmb>$this->tpAmb</tpAmb>"; |
||
849 | if ($this->typePerson === 'J') { |
||
850 | $request .= "<CNPJ>$cnpj</CNPJ>"; |
||
851 | } else { |
||
852 | $request .= "<CPF>$cnpj</CPF>"; |
||
853 | } |
||
854 | $request .= "<chNFe>$chave</chNFe>" |
||
855 | . "<dhEvento>$dhEvento</dhEvento>" |
||
856 | . "<tpEvento>$tpEvento</tpEvento>" |
||
857 | . "<nSeqEvento>$nSeqEvento</nSeqEvento>" |
||
858 | . "<verEvento>$this->urlVersion</verEvento>" |
||
859 | . "<detEvento versao=\"$this->urlVersion\">" |
||
860 | . "<descEvento>$descEvento</descEvento>" |
||
861 | . "$tagAdic" |
||
862 | . "</detEvento>" |
||
863 | . "</infEvento>" |
||
864 | . "</evento>"; |
||
865 | //assinatura dos dados |
||
866 | $request = Signer::sign( |
||
867 | $this->certificate, |
||
868 | $request, |
||
869 | 'infEvento', |
||
870 | 'Id', |
||
871 | $this->algorithm, |
||
872 | $this->canonical |
||
873 | ); |
||
874 | $request = Strings::clearXmlString($request, true); |
||
875 | $lote = $dt->format('YmdHis').rand(0, 9); |
||
876 | $request = "<envEvento xmlns=\"$this->urlPortal\" versao=\"$this->urlVersion\">" |
||
877 | . "<idLote>$lote</idLote>" |
||
878 | . $request |
||
879 | . "</envEvento>"; |
||
880 | $this->isValid($this->urlVersion, $request, 'envEvento'); |
||
881 | $this->lastRequest = $request; |
||
882 | //return $request; |
||
883 | $parameters = ['nfeDadosMsg' => $request]; |
||
884 | $body = "<nfeDadosMsg xmlns=\"$this->urlNamespace\">$request</nfeDadosMsg>"; |
||
885 | $this->lastResponse = $this->sendRequest($body, $parameters); |
||
886 | return $this->lastResponse; |
||
887 | } |
||
888 | |||
889 | /** |
||
890 | * Request the NFe download already manifested by its recipient, by the key |
||
891 | * using new service in NfeDistribuicaoDFe |
||
892 | * NOTA: NfeDownloadNF is deactivated |
||
893 | * @param string $chave |
||
894 | * @return string |
||
895 | * @throws InvalidArgumentException |
||
896 | */ |
||
897 | public function sefazDownload($chave) |
||
898 | { |
||
899 | if (empty($chave)) { |
||
900 | throw new InvalidArgumentException('Download: chave esta vazia!'); |
||
901 | } |
||
902 | //carrega serviço |
||
903 | $servico = 'NfeDistribuicaoDFe'; |
||
904 | $this->checkContingencyForWebServices($servico); |
||
905 | $this->servico($servico, 'AN', $this->tpAmb, true); |
||
906 | $cUF = UFList::getCodeByUF($this->config->siglaUF); |
||
907 | $tagChave = "<consChNFe><chNFe>$chave</chNFe></consChNFe>"; |
||
908 | $cnpj = $this->config->cnpj; |
||
909 | //monta a consulta |
||
910 | $request = "<distDFeInt xmlns=\"$this->urlPortal\" versao=\"$this->urlVersion\">" |
||
911 | . "<tpAmb>".$this->tpAmb."</tpAmb>" |
||
912 | . "<cUFAutor>$cUF</cUFAutor>"; |
||
913 | if ($this->typePerson === 'J') { |
||
914 | $request .= "<CNPJ>$cnpj</CNPJ>"; |
||
915 | } else { |
||
916 | $request .= "<CPF>$cnpj</CPF>"; |
||
917 | } |
||
918 | $request .= "$tagChave" |
||
919 | . "</distDFeInt>"; |
||
920 | //valida o xml da requisição |
||
921 | $this->isValid($this->urlVersion, $request, 'distDFeInt'); |
||
922 | $this->lastRequest = $request; |
||
923 | //montagem dos dados da mensagem SOAP |
||
924 | $request = "<nfeDadosMsg xmlns=\"$this->urlNamespace\">$request</nfeDadosMsg>"; |
||
925 | $parameters = ['nfeDistDFeInteresse' => $request]; |
||
926 | $body = "<nfeDistDFeInteresse xmlns=\"$this->urlNamespace\">" |
||
927 | . $request |
||
928 | . "</nfeDistDFeInteresse>"; |
||
929 | //este webservice não requer cabeçalho |
||
930 | $this->objHeader = null; |
||
931 | $this->lastResponse = $this->sendRequest($body, $parameters); |
||
932 | return $this->lastResponse; |
||
933 | } |
||
934 | |||
935 | /** |
||
936 | * Maintenance of the Taxpayer Security Code - CSC (Old Token) |
||
937 | * @param int $indOp Identificador do tipo de operação: |
||
938 | * 1 - Consulta CSC Ativos; |
||
939 | * 2 - Solicita novo CSC; |
||
940 | * 3 - Revoga CSC Ativo |
||
941 | * @return string |
||
942 | * @throws InvalidArgumentException |
||
943 | * @throws RuntimeException |
||
944 | */ |
||
945 | public function sefazCsc($indOp) |
||
946 | { |
||
947 | if (empty($indOp) || $indOp < 1 || $indOp > 3) { |
||
948 | throw new InvalidArgumentException('CSC: identificador operacao invalido!'); |
||
949 | } |
||
950 | if ($this->modelo != 65) { |
||
951 | throw new RuntimeException('CSC: modelo diferente de 65!'); |
||
952 | } |
||
953 | $raizCNPJ = substr($this->config->cnpj, 0, -6); |
||
954 | //carrega serviço |
||
955 | $servico = 'CscNFCe'; |
||
956 | $this->checkContingencyForWebServices($servico); |
||
957 | $this->servico($servico, $this->config->siglaUF, $this->tpAmb); |
||
958 | $request = "<admCscNFCe versao=\"$this->urlVersion\" xmlns=\"$this->urlPortal\">" |
||
959 | . "<tpAmb>$this->tpAmb</tpAmb>" |
||
960 | . "<indOp>$indOp</indOp>" |
||
961 | . "<raizCNPJ>$raizCNPJ</raizCNPJ>" |
||
962 | . "</admCscNFCe>"; |
||
963 | if ($indOp == 3) { |
||
964 | $request = "<admCscNFCe versao=\"$this->urlVersion\" xmlns=\"$this->urlPortal\">" |
||
965 | . "<tpAmb>$this->tpAmb</tpAmb>" |
||
966 | . "<indOp>$indOp</indOp>" |
||
967 | . "<raizCNPJ>$raizCNPJ</raizCNPJ>" |
||
968 | . "<dadosCsc>" |
||
969 | . "<idCsc>".$this->config->CSCid."</idCsc>" |
||
970 | . "<codigoCsc>".$this->config->CSC."</codigoCsc>" |
||
971 | . "</dadosCsc>" |
||
972 | . "</admCscNFCe>"; |
||
973 | } |
||
974 | //o xsd não está disponivel |
||
975 | //$this->isValid($this->urlVersion, $request, 'cscNFCe'); |
||
976 | $this->lastRequest = $request; |
||
977 | $parameters = ['nfeDadosMsg' => $request]; |
||
978 | $body = "<nfeDadosMsg xmlns=\"$this->urlNamespace\">$request</nfeDadosMsg>"; |
||
979 | $this->lastResponse = $this->sendRequest($body, $parameters); |
||
980 | return $this->lastResponse; |
||
981 | } |
||
982 | |||
983 | /** |
||
984 | * Checks the validity of an NFe, normally used for received NFe |
||
985 | * @param string $nfe |
||
986 | * @return bool |
||
987 | * @throws InvalidArgumentException |
||
988 | */ |
||
989 | public function sefazValidate($nfe) |
||
990 | { |
||
991 | if (empty($nfe)) { |
||
992 | throw new InvalidArgumentException('Validacao NF-e: a string da NF-e esta vazia!'); |
||
993 | } |
||
994 | //verifica a assinatura da NFe, exception caso de falha |
||
995 | Signer::isSigned($nfe); |
||
996 | $dom = new \DOMDocument('1.0', 'utf-8'); |
||
997 | $dom->formatOutput = false; |
||
998 | $dom->preserveWhiteSpace = false; |
||
999 | $dom->loadXML($nfe); |
||
1000 | //verifica a validade no webservice da SEFAZ |
||
1001 | $tpAmb = $dom->getElementsByTagName('tpAmb')->item(0)->nodeValue; |
||
1002 | $infNFe = $dom->getElementsByTagName('infNFe')->item(0); |
||
1003 | $chNFe = preg_replace('/[^0-9]/', '', $infNFe->getAttribute("Id")); |
||
1004 | $protocol = $dom->getElementsByTagName('nProt')->item(0)->nodeValue; |
||
1005 | $digval = $dom->getElementsByTagName('DigestValue')->item(0)->nodeValue; |
||
1006 | //consulta a NFe |
||
1007 | $response = $this->sefazConsultaChave($chNFe, $tpAmb); |
||
1008 | $ret = new \DOMDocument('1.0', 'UTF-8'); |
||
1009 | $ret->preserveWhiteSpace = false; |
||
1010 | $ret->formatOutput = false; |
||
1011 | $ret->loadXML($response); |
||
1012 | $retProt = $ret->getElementsByTagName('protNFe')->item(0); |
||
1013 | if (!isset($retProt)) { |
||
1014 | $xMotivo = $ret->getElementsByTagName('xMotivo')->item(0); |
||
1015 | if (isset($xMotivo)) { |
||
1016 | throw new InvalidArgumentException('Validacao NF-e: ' . $xMotivo->nodeValue); |
||
1017 | } else { |
||
1018 | throw new InvalidArgumentException('O documento de resposta nao contem o node "protNFe".'); |
||
1019 | } |
||
1020 | } |
||
1021 | $infProt = $ret->getElementsByTagName('infProt')->item(0); |
||
1022 | $dig = $infProt->getElementsByTagName("digVal")->item(0); |
||
1023 | $digProt = '000'; |
||
1024 | if (isset($dig)) { |
||
1025 | $digProt = $dig->nodeValue; |
||
1026 | } |
||
1027 | $chProt = $infProt->getElementsByTagName("chNFe")->item(0)->nodeValue; |
||
1028 | $nProt = $infProt->getElementsByTagName("nProt")->item(0)->nodeValue; |
||
1029 | if ($protocol == $nProt && $digval == $digProt && $chNFe == $chProt) { |
||
1030 | return true; |
||
1031 | } |
||
1032 | return false; |
||
1033 | } |
||
1034 | |||
1035 | /** |
||
1036 | * Returns alias and description event from event code. |
||
1037 | * @param int $tpEvento |
||
1038 | * @return \stdClass |
||
1039 | * @throws \RuntimeException |
||
1040 | */ |
||
1041 | private function tpEv($tpEvento) |
||
1042 | { |
||
1043 | $std = new \stdClass(); |
||
1044 | $std->alias = ''; |
||
1045 | $std->desc = ''; |
||
1046 | switch ($tpEvento) { |
||
1047 | case self::EVT_CCE: |
||
1048 | $std->alias = 'CCe'; |
||
1049 | $std->desc = 'Carta de Correcao'; |
||
1050 | break; |
||
1051 | case self::EVT_CANCELA: |
||
1052 | $std->alias = 'CancNFe'; |
||
1053 | $std->desc = 'Cancelamento'; |
||
1054 | break; |
||
1055 | case self::EVT_CANCELASUBSTITUICAO: |
||
1056 | $std->alias = 'CancNFe'; |
||
1057 | $std->desc = 'Cancelamento por substituicao'; |
||
1058 | break; |
||
1059 | case self::EVT_EPEC: // Emissão em contingência EPEC |
||
1060 | $std->alias = 'EPEC'; |
||
1061 | $std->desc = 'EPEC'; |
||
1062 | break; |
||
1063 | case self::EVT_COMPROVANTE_ENTREGA: |
||
1064 | $std->alias = 'CompEntrega'; |
||
1065 | $std->desc = 'Comprovante de Entrega'; |
||
1066 | break; |
||
1067 | case self::EVT_CANCELAMENTO_COMPROVANTE_ENTREGA: |
||
1068 | $std->alias = 'CancCompEntrega'; |
||
1069 | $std->desc = 'Cancelamento do Comprovante de Entrega'; |
||
1070 | break; |
||
1071 | case 111500: |
||
1072 | case 111501: |
||
1073 | //EPP |
||
1074 | //Pedido de prorrogação |
||
1075 | $std->alias = 'EPP'; |
||
1076 | $std->desc = 'Pedido de Prorrogacao'; |
||
1077 | break; |
||
1078 | case 111502: |
||
1079 | case 111503: |
||
1080 | //ECPP |
||
1081 | //Cancelamento do Pedido de prorrogação |
||
1082 | $std->alias = 'ECPP'; |
||
1083 | $std->desc = 'Cancelamento de Pedido de Prorrogacao'; |
||
1084 | break; |
||
1085 | case self::EVT_CONFIRMACAO: // Manifestação Confirmacao da Operação |
||
1086 | $std->alias = 'EvConfirma'; |
||
1087 | $std->desc = 'Confirmacao da Operacao'; |
||
1088 | break; |
||
1089 | case self::EVT_CIENCIA: // Manifestação Ciencia da Operação |
||
1090 | $std->alias = 'EvCiencia'; |
||
1091 | $std->desc = 'Ciencia da Operacao'; |
||
1092 | $std->tpAutor = 2; |
||
1093 | break; |
||
1094 | case self::EVT_DESCONHECIMENTO: // Manifestação Desconhecimento da Operação |
||
1095 | $std->alias = 'EvDesconh'; |
||
1096 | $std->desc = 'Desconhecimento da Operacao'; |
||
1097 | break; |
||
1098 | case self::EVT_NAO_REALIZADA: // Manifestação Operacao não Realizada |
||
1099 | $std->alias = 'EvNaoRealizada'; |
||
1100 | $std->desc = 'Operacao nao Realizada'; |
||
1101 | break; |
||
1102 | case self::EVT_ATORINTERESSADO: //ator interessado |
||
1103 | $std->alias = 'EvAtorInteressado'; |
||
1104 | $std->desc = 'Ator interessado na NF-e'; |
||
1105 | break; |
||
1106 | default: |
||
1107 | $msg = "O código do tipo de evento informado não corresponde a " |
||
1108 | . "nenhum evento estabelecido."; |
||
1109 | throw new RuntimeException($msg); |
||
1110 | } |
||
1111 | return $std; |
||
1112 | } |
||
1113 | } |
||
1114 |
This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.