Passed
Pull Request — master (#829)
by Roberto
02:32
created

Tools::sefazECPP()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
dl 0
loc 20
ccs 0
cts 15
cp 0
rs 9.6
c 0
b 0
f 0
cc 4
nc 3
nop 3
crap 20
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
418
     * @param string $chave
419
     * @param int $tpAutor
420
     * @param string $verAplic
421
     * @param int $nSeqEvento
422
     * @param array $interessados
423
     * @return string
424
     */
425
    public function sefazAtorInteressado(
426
        $chave,
427
        $tpAutor,
428
        $verAplic,
429
        $nSeqEvento = 1,
430
        $interessados = []
431
    ) {
432
        $xCondUso = 'O emitente ou destinatário da NF-e, declara que permite o '
433
            . 'transportador declarado no campo CNPJ/CPF deste evento a '
434
            . 'autorizar os transportadores subcontratados ou redespachados '
435
            . 'a terem acesso ao download da NFe';
436
        $tagAdic = "<cOrgaoAutor>{$this->urlcUF}</cOrgaoAutor>"
437
            . "<tpAutor>{$tpAutor}</tpAutor>"
438
            . "<verAplic>{$verAplic}</verAplic>";
439
        foreach ($interessados as $aut) {
440
            $obj = (object) $aut;
441
            $tagAdic .= "<autXML>";
442
            $tagAdic .=  !empty($obj->CNPJ)
443
                ? "<CNPJ>{$obj->CNPJ}</CNPJ>"
444
                : "<CPF>{$obj->CPF}</CPF>";
445
            $tagAdic .= "<tpAutorizacao>{$obj->tpAutorizacao}</tpAutorizacao>"
446
                . "</autXML>";
447
        }
448
        $tagAdic .= "<xCondUso>$xCondUso</xCondUso>";
449
        return $this->sefazEvento($uf, $chave, self::EVT_ATORINTERESSADO, $nSeqEvento, $tagAdic);
0 ignored issues
show
Bug introduced by
The variable $uf does not exist. Did you forget to declare it?

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.

Loading history...
450
    }
451
452
    /**
453
     * Request extension of the term of return of products of an NF-e of
454
     * consignment for industrialization to order with suspension of ICMS
455
     * in interstate operations
456
     * @param  string  $chNFe
457
     * @param  string  $nProt
458
     * @param  integer $tipo 1-primerio prazo, 2-segundo prazo
459
     * @param  array   $itens
460
     * @param  integer $nSeqEvento
461
     * @return string
462
     */
463
    public function sefazEPP(
464
        $chNFe,
465
        $nProt,
466
        $itens = array(),
467
        $tipo = 1,
468
        $nSeqEvento = 1
469
    ) {
470
        $uf = UFList::getUFByCode(substr($chNFe, 0, 2));
471
        $tpEvento = 111500;
472
        if ($tipo == 2) {
473
            $tpEvento = 111501;
474
        }
475
        $tagAdic = "<nProt>$nProt</nProt>";
476
        foreach ($itens as $item) {
477
            $tagAdic .= "<itemPedido numItem=\""
478
                . $item[0]
479
                . "\"><qtdeItem>"
480
                . $item[1]
481
                ."</qtdeItem></itemPedido>";
482
        }
483
        return $this->sefazEvento(
484
            $uf,
485
            $chNFe,
486
            $tpEvento,
487
            $nSeqEvento,
488
            $tagAdic
489
        );
490
    }
491
492
    /**
493
     * Request the cancellation of the request for an extension of the term
494
     * of return of products of an NF-e of consignment for industrialization
495
     * by order with suspension of ICMS in interstate operations
496
     * @param string $chave
497
     * @param string $nProt
498
     * @param integer $nSeqEvento
499
     * @return string
500
     * @throws InvalidArgumentException
501
     */
502
    public function sefazECPP($chave, $nProt, $nSeqEvento = 1)
503
    {
504
        if (empty($chave) || empty($nProt)) {
505
            throw new InvalidArgumentException('A chave ou o numero do protocolo estao vazios!');
506
        }
507
        $uf = UFList::getUFByCode(substr($chave, 0, 2));
508
        $tpEvento = 111502;
509
        $origEvent = 111500;
510
        if ($nSeqEvento == 2) {
511
            $tpEvento = 111503;
512
            $origEvent = 111501;
513
        }
514
        $sSeqEvento = str_pad($nSeqEvento, 2, "0", STR_PAD_LEFT);
515
        $idPedidoCancelado = "ID$origEvent$chave$sSeqEvento";
516
        $tagAdic = "<idPedidoCancelado>"
517
                . "$idPedidoCancelado"
518
                . "</idPedidoCancelado>"
519
                . "<nProt>$nProt</nProt>";
520
        return $this->sefazEvento($uf, $chave, $tpEvento, $nSeqEvento, $tagAdic);
521
    }
522
523
    /**
524
     * Requires nfe cancellation
525
     * @param  string $chave key of NFe
526
     * @param  string $xJust justificative 255 characters max
527
     * @param  string $nProt protocol number
528
     * @return string
529
     * @throws InvalidArgumentException
530
     */
531
    public function sefazCancela($chave, $xJust, $nProt)
532
    {
533
        if (empty($chave) || empty($xJust) || empty($nProt)) {
534
            throw new InvalidArgumentException('Cancelamento: chave, just ou numprot vazio!');
535
        }
536
        $uf = $this->validKeyByUF($chave);
537
        $xJust = Strings::replaceUnacceptableCharacters(substr(trim($xJust), 0, 255));
538
        $nSeqEvento = 1;
539
        $tagAdic = "<nProt>$nProt</nProt><xJust>$xJust</xJust>";
540
        return $this->sefazEvento($uf, $chave, self::EVT_CANCELA, $nSeqEvento, $tagAdic);
541
    }
542
543
    /**
544
     * Requires nfe cancellation by substitution
545
     * @param  string $chave key of NFe
546
     * @param  string $xJust justificative 255 characters max
547
     * @param  string $nProt protocol number
548
     * @param  string $chNFeRef key of New NFe
549
     * @param  string $verAplic version of applicative
550
     * @return string
551
     * @throws InvalidArgumentException
552
     */
553
    public function sefazCancelaPorSubstituicao($chave, $xJust, $nProt, $chNFeRef, $verAplic)
554
    {
555
        if ($this->modelo != 65) {
556
            throw new InvalidArgumentException(
557
                'Cancelamento pro Substituição deve ser usado apenas para '
558
                . 'operações com modelo 65 NFCe'
559
            );
560
        }
561
        if (empty($chave) || empty($xJust) || empty($nProt)
562
            || empty($chNFeRef) || empty($verAplic)) {
563
            throw new InvalidArgumentException(
564
                'CancelamentoPorSubs: chave da NFCe cancelada, justificativa, '
565
                . 'protocolo, chave da NFCe substituta, ou versão do aplicativo '
566
                . 'emissor não podem ser vazios!'
567
            );
568
        }
569
        $uf = $this->validKeyByUF($chave);
570
        $xJust = Strings::replaceUnacceptableCharacters(substr(trim($xJust), 0, 255));
571
        $nSeqEvento = 1;
572
        $cOrgao = substr($chave, 0, 2);
573
        $tagAdic = "<cOrgaoAutor>$cOrgao</cOrgaoAutor>"
574
            . "<tpAutor>1</tpAutor>"
575
            . "<verAplic>$verAplic</verAplic>"
576
            . "<nProt>$nProt</nProt>"
577
            . "<xJust>$xJust</xJust>"
578
            . "<chNFeRef>$chNFeRef</chNFeRef>";
579
        return $this->sefazEvento($uf, $chave, self::EVT_CANCELASUBSTITUICAO, $nSeqEvento, $tagAdic);
580
    }
581
582
    /**
583
     * Request the registration of the manifestation of recipient
584
     * @param string $chave
585
     * @param int $tpEvento
586
     * @param string $xJust Justification for not carrying out the operation
587
     * @param int $nSeqEvento
588
     * @return string
589
     * @throws InvalidArgumentException
590
     */
591
    public function sefazManifesta($chave, $tpEvento, $xJust = '', $nSeqEvento = 1)
592
    {
593
        if (empty($chave) || empty($tpEvento)) {
594
            throw new InvalidArgumentException('Manifestacao: chave ou tipo de evento vazio!');
595
        }
596
        $tagAdic = '';
597
        if ($tpEvento == self::EVT_NAO_REALIZADA) {
598
            $xJust = Strings::replaceUnacceptableCharacters(substr(trim($xJust), 0, 255));
599
            $tagAdic = "<xJust>$xJust</xJust>";
600
        }
601
        return $this->sefazEvento('AN', $chave, $tpEvento, $nSeqEvento, $tagAdic);
602
    }
603
604
    /**
605
     * Request the registration of the manifestation of recipient in batch
606
     * @param \stdClass $std
607
     * @return string
608
     * @throws InvalidArgumentException
609
     * @throws RuntimeException
610
     */
611
    public function sefazManifestaLote(\stdClass $std)
612
    {
613
        $allowed = [
614
            self::EVT_CONFIRMACAO,
615
            self::EVT_CIENCIA,
616
            self::EVT_DESCONHECIMENTO,
617
            self::EVT_NAO_REALIZADA,
618
        ];
619
        if (empty($std) || empty($std->evento)) {
620
            throw new InvalidArgumentException('Manifestacao: parametro "std" ou evento estao vazios!');
621
        }
622
        if (count($std->evento) > 20) {
623
            throw new RuntimeException('Manifestacao: o lote de eventos esta limitado a 20!');
624
        }
625
        $evt = new \stdClass();
626
        $i = 0;
627
        foreach ($std->evento as $s) {
628
            if (!in_array($s->tpEvento, $allowed)) { // se o evento não estiver entre os permitidos ignore
629
                continue;
630
            }
631
            $tagAdic = '';
632
            if ($s->tpEvento == self::EVT_NAO_REALIZADA) {
633
                $xJust = Strings::replaceUnacceptableCharacters(substr(trim($s->xJust), 0, 255));
634
                $tagAdic = "<xJust>$xJust</xJust>";
635
            }
636
            $evt->evento[$i] = new \stdClass();
637
            $evt->evento[$i]->chave = $s->chNFe;
638
            $evt->evento[$i]->tpEvento = $s->tpEvento;
639
            $evt->evento[$i]->nSeqEvento = $s->nSeqEvento;
640
            $evt->evento[$i]->tagAdic = $tagAdic;
641
            $i++;
642
        }
643
        return $this->sefazEventoLote('AN', $evt);
644
    }
645
    
646
    /**
647
     * Send event for delivery receipt
648
     * @param \stdClass $std
649
     * @return string
650
     */
651
    public function sefazComprovanteEntrega(\stdClass $std)
652
    {
653
        $hash = sha1($std->chave . $std->imagem);
654
        $datahash = date('Y-m-d\TH:i:sP');
655
        $cod = UFList::getCodeByUF($this->config->siglaUF);
656
        $tagAdic = "<cOrgaoAutor>{$cod}</cOrgaoAutor>"
657
            . "<tpAutor>1</tpAutor>"
658
            . "<verAplic>{$std->verAplic}</verAplic>"
659
            . "<dhEntrega>{$std->data_recebimento}</dhEntrega>"
660
            . "<nDoc>{$std->documento_recebedor}</nDoc>"
661
            . "<xNome>{$std->nome_recebedor}</xNome>";
662
        if (!empty($std->latitude) && !empty($std->longitude)) {
663
            $tagAdic .= "<latGPS>{$std->latitude}</latGPS>"
664
            . "<longGPS>{$std->longitude}</longGPS>";
665
        }
666
        $tagAdic .= "<hashComprovante>{$hash}</hashComprovante>"
667
            . "<dhHashComprovante>{$datahash}</dhHashComprovante>";
668
        $tpEvento = self::EVT_COMPROVANTE_ENTREGA;    
669
        if ($std->cancelar == true) {
670
            $tpEvento = self::EVT_CANCELAMENTO_COMPROVANTE_ENTREGA;
671
        }
672
        $chave = $std->chave;
673
        $nSeqEvento = 1;
674
        return $this->sefazEvento('AN', $chave, $tpEvento, $nSeqEvento, $tagAdic);
675
    }
676
    
677
    /**
678
     * Send event to SEFAZ in batch
679
     * @param string $uf
680
     * @param \stdClass $std
681
     * @return string
682
     * @throws RuntimeException
683
     * @throws InvalidArgumentException
684
     */
685
    public function sefazEventoLote($uf, \stdClass $std)
686
    {
687
        if (empty($uf) || empty($std)) {
688
            throw new InvalidArgumentException('Evento Lote: UF ou parametro "std" vazio!');
689
        }
690
        if (count($std->evento) > 20) {
691
            throw new RuntimeException('Evento Lote: o lote de eventos esta limitado a 20!');
692
        }
693
        $servico = 'RecepcaoEvento';
694
        $this->checkContingencyForWebServices($servico);
695
        $this->servico($servico, $uf, $this->tpAmb, false);
696
        $batchRequest = '';
697
        foreach ($std->evento as $evt) {
698
            if ($evt->tpEvento == self::EVT_EPEC) {
699
                continue; //não é possivel enviar EPEC com outros eventos
700
            }
701
            $ev = $this->tpEv($evt->tpEvento);
702
            $descEvento = $ev->desc;
703
            $cnpj = $this->config->cnpj;
704
            $dt = new \DateTime('now', new \DateTimeZone($this->timezone));
705
            $dhEvento = $dt->format('Y-m-d\TH:i:sP');
706
            $sSeqEvento = str_pad($evt->nSeqEvento, 2, "0", STR_PAD_LEFT);
707
            $eventId = "ID".$evt->tpEvento.$evt->chave.$sSeqEvento;
708
            $cOrgao = UFList::getCodeByUF($uf);
709
            $request = "<evento xmlns=\"$this->urlPortal\" versao=\"$this->urlVersion\">"
710
                . "<infEvento Id=\"$eventId\">"
711
                . "<cOrgao>$cOrgao</cOrgao>"
712
                . "<tpAmb>$this->tpAmb</tpAmb>";
713
            if ($this->typePerson === 'J') {
714
                $request .= "<CNPJ>$cnpj</CNPJ>";
715
            } else {
716
                $request .= "<CPF>$cnpj</CPF>";
717
            }
718
            $request .= "<chNFe>$evt->chave</chNFe>"
719
                . "<dhEvento>$dhEvento</dhEvento>"
720
                . "<tpEvento>$evt->tpEvento</tpEvento>"
721
                . "<nSeqEvento>$evt->nSeqEvento</nSeqEvento>"
722
                . "<verEvento>$this->urlVersion</verEvento>"
723
                . "<detEvento versao=\"$this->urlVersion\">"
724
                . "<descEvento>$descEvento</descEvento>"
725
                . "$evt->tagAdic"
726
                . "</detEvento>"
727
                . "</infEvento>"
728
                . "</evento>";
729
            //assinatura dos dados
730
            $request = Signer::sign(
731
                $this->certificate,
732
                $request,
733
                'infEvento',
734
                'Id',
735
                $this->algorithm,
736
                $this->canonical
737
            );
738
            $batchRequest .= Strings::clearXmlString($request, true);
739
        }
740
        $dt = new \DateTime('now', new \DateTimeZone($this->timezone));
741
        $lote = $dt->format('YmdHis') . rand(0, 9);
742
        $request = "<envEvento xmlns=\"$this->urlPortal\" versao=\"$this->urlVersion\">"
743
            . "<idLote>$lote</idLote>"
744
            . $batchRequest
745
            . "</envEvento>";
746
        $this->isValid($this->urlVersion, $request, 'envEvento');
747
        $this->lastRequest = $request;
748
        $parameters = ['nfeDadosMsg' => $request];
749
        $body = "<nfeDadosMsg xmlns=\"$this->urlNamespace\">$request</nfeDadosMsg>";
750
        $this->lastResponse = $this->sendRequest($body, $parameters);
751
        return $this->lastResponse;
752
    }
753
754
    /**
755
     * Request authorization for issuance in contingency EPEC
756
     * @param  string $xml
757
     * @return string
758
     * @throws InvalidArgumentException
759
     * @throws RuntimeException
760
     */
761
    public function sefazEPEC(&$xml)
762
    {
763
        if (empty($xml)) {
764
            throw new InvalidArgumentException('EPEC: parametro xml esta vazio!');
765
        }
766
        $nSeqEvento = 1;
767
        if ($this->contingency->type !== 'EPEC') {
768
            throw new RuntimeException('A contingencia EPEC deve estar ativada!');
769
        }
770
        $xml = $this->correctNFeForContingencyMode($xml);
771
        $dom = new \DOMDocument('1.0', 'UTF-8');
772
        $dom->preserveWhiteSpace = false;
773
        $dom->formatOutput = false;
774
        $dom->loadXML($xml);
775
        $infNFe = $dom->getElementsByTagName('infNFe')->item(0);
776
        $emit = $dom->getElementsByTagName('emit')->item(0);
777
        $dest = $dom->getElementsByTagName('dest')->item(0);
778
        $cOrgaoAutor = UFList::getCodeByUF($this->config->siglaUF);
779
        $chNFe = substr($infNFe->getAttribute('Id'), 3, 44);
780
        // EPEC
781
        $dhEmi = $dom->getElementsByTagName('dhEmi')->item(0)->nodeValue;
782
        $tpNF = $dom->getElementsByTagName('tpNF')->item(0)->nodeValue;
783
        $emitIE = $emit->getElementsByTagName('IE')->item(0)->nodeValue;
784
        $destUF = $dest->getElementsByTagName('UF')->item(0)->nodeValue;
785
        $total = $dom->getElementsByTagName('total')->item(0);
786
        $vNF = $total->getElementsByTagName('vNF')->item(0)->nodeValue;
787
        $vICMS = $total->getElementsByTagName('vICMS')->item(0)->nodeValue;
788
        $vST = $total->getElementsByTagName('vST')->item(0)->nodeValue;
789
        $dID = !empty($dest->getElementsByTagName('CNPJ')->item(0)) ?
790
                $dest->getElementsByTagName('CNPJ')->item(0)->nodeValue : null;
791
        if (!empty($dID)) {
792
            $destID = "<CNPJ>$dID</CNPJ>";
793
        } else {
794
            $dID = $dest->getElementsByTagName('CPF')->item(0)->nodeValue;
795
            if (!empty($dID)) {
796
                $destID = "<CPF>$dID</CPF>";
797
            } else {
798
                $dID = $dest->getElementsByTagName('idEstrangeiro')
799
                    ->item(0)
800
                    ->nodeValue;
801
                $destID = "<idEstrangeiro>$dID</idEstrangeiro>";
802
            }
803
        }
804
        $dIE = !empty($dest->getElementsByTagName('IE')->item(0)->nodeValue) ?
805
                $dest->getElementsByTagName('IE')->item(0)->nodeValue : '';
806
        $destIE = '';
807
        if (!empty($dIE)) {
808
            $destIE = "<IE>$dIE</IE>";
809
        }
810
        $tagAdic = "<cOrgaoAutor>$cOrgaoAutor</cOrgaoAutor>"
811
            . "<tpAutor>1</tpAutor>"
812
            . "<verAplic>$this->verAplic</verAplic>"
813
            . "<dhEmi>$dhEmi</dhEmi>"
814
            . "<tpNF>$tpNF</tpNF>"
815
            . "<IE>$emitIE</IE>"
816
            . "<dest>"
817
            . "<UF>$destUF</UF>"
818
            . $destID
819
            . $destIE
820
            . "<vNF>$vNF</vNF>"
821
            . "<vICMS>$vICMS</vICMS>"
822
            . "<vST>$vST</vST>"
823
            . "</dest>";
824
825
        return $this->sefazEvento('AN', $chNFe, self::EVT_EPEC, $nSeqEvento, $tagAdic);
826
    }
827
828
    /**
829
     * Send event to SEFAZ
830
     * @param string $uf
831
     * @param string $chave
832
     * @param int $tpEvento
833
     * @param int $nSeqEvento
834
     * @param string $tagAdic
835
     * @return string
836
     */
837
    public function sefazEvento(
838
        $uf,
839
        $chave,
840
        $tpEvento,
841
        $nSeqEvento = 1,
842
        $tagAdic = ''
843
    ) {
844
        $ignore = $tpEvento == self::EVT_EPEC;
845
        $servico = 'RecepcaoEvento';
846
        $this->checkContingencyForWebServices($servico);
847
        $this->servico($servico, $uf, $this->tpAmb, $ignore);
848
        $ev = $this->tpEv($tpEvento);
849
        $descEvento = $ev->desc;
850
        $cnpj = isset($this->config->cnpj) ? $this->config->cnpj : '';
851
        $dt = new \DateTime(date("Y-m-d H:i:sP"), new \DateTimeZone($this->timezone));
852
        $dhEvento = $dt->format('Y-m-d\TH:i:sP');
853
        $sSeqEvento = str_pad($nSeqEvento, 2, "0", STR_PAD_LEFT);
854
        $eventId = "ID".$tpEvento.$chave.$sSeqEvento;
855
        $cOrgao = UFList::getCodeByUF($uf);
856
        $request = "<evento xmlns=\"$this->urlPortal\" versao=\"$this->urlVersion\">"
857
            . "<infEvento Id=\"$eventId\">"
858
            . "<cOrgao>$cOrgao</cOrgao>"
859
            . "<tpAmb>$this->tpAmb</tpAmb>";
860
        if ($this->typePerson === 'J') {
861
            $request .= "<CNPJ>$cnpj</CNPJ>";
862
        } else {
863
            $request .= "<CPF>$cnpj</CPF>";
864
        }
865
        $request .= "<chNFe>$chave</chNFe>"
866
            . "<dhEvento>$dhEvento</dhEvento>"
867
            . "<tpEvento>$tpEvento</tpEvento>"
868
            . "<nSeqEvento>$nSeqEvento</nSeqEvento>"
869
            . "<verEvento>$this->urlVersion</verEvento>"
870
            . "<detEvento versao=\"$this->urlVersion\">"
871
            . "<descEvento>$descEvento</descEvento>"
872
            . "$tagAdic"
873
            . "</detEvento>"
874
            . "</infEvento>"
875
            . "</evento>";
876
        //assinatura dos dados
877
        $request = Signer::sign(
878
            $this->certificate,
879
            $request,
880
            'infEvento',
881
            'Id',
882
            $this->algorithm,
883
            $this->canonical
884
        );
885
        $request = Strings::clearXmlString($request, true);
886
        $lote = $dt->format('YmdHis').rand(0, 9);
887
        $request = "<envEvento xmlns=\"$this->urlPortal\" versao=\"$this->urlVersion\">"
888
            . "<idLote>$lote</idLote>"
889
            . $request
890
            . "</envEvento>";
891
        $this->isValid($this->urlVersion, $request, 'envEvento');
892
        $this->lastRequest = $request;
893
        //return $request;
894
        $parameters = ['nfeDadosMsg' => $request];
895
        $body = "<nfeDadosMsg xmlns=\"$this->urlNamespace\">$request</nfeDadosMsg>";
896
        $this->lastResponse = $this->sendRequest($body, $parameters);
897
        return $this->lastResponse;
898
    }
899
900
    /**
901
     * Request the NFe download already manifested by its recipient, by the key
902
     * using new service in NfeDistribuicaoDFe
903
     * NOTA: NfeDownloadNF is deactivated
904
     * @param  string $chave
905
     * @return string
906
     * @throws InvalidArgumentException
907
     */
908
    public function sefazDownload($chave)
909
    {
910
        if (empty($chave)) {
911
            throw new InvalidArgumentException('Download: chave esta vazia!');
912
        }
913
        //carrega serviço
914
        $servico = 'NfeDistribuicaoDFe';
915
        $this->checkContingencyForWebServices($servico);
916
        $this->servico($servico, 'AN', $this->tpAmb, true);
917
        $cUF = UFList::getCodeByUF($this->config->siglaUF);
918
        $tagChave = "<consChNFe><chNFe>$chave</chNFe></consChNFe>";
919
        $cnpj = $this->config->cnpj;
920
        //monta a consulta
921
        $request = "<distDFeInt xmlns=\"$this->urlPortal\" versao=\"$this->urlVersion\">"
922
            . "<tpAmb>".$this->tpAmb."</tpAmb>"
923
            . "<cUFAutor>$cUF</cUFAutor>";
924
        if ($this->typePerson === 'J') {
925
            $request .= "<CNPJ>$cnpj</CNPJ>";
926
        } else {
927
            $request .= "<CPF>$cnpj</CPF>";
928
        }
929
        $request .= "$tagChave"
930
            . "</distDFeInt>";
931
        //valida o xml da requisição
932
        $this->isValid($this->urlVersion, $request, 'distDFeInt');
933
        $this->lastRequest = $request;
934
        //montagem dos dados da mensagem SOAP
935
        $request = "<nfeDadosMsg xmlns=\"$this->urlNamespace\">$request</nfeDadosMsg>";
936
        $parameters = ['nfeDistDFeInteresse' => $request];
937
        $body = "<nfeDistDFeInteresse xmlns=\"$this->urlNamespace\">"
938
            . $request
939
            . "</nfeDistDFeInteresse>";
940
        //este webservice não requer cabeçalho
941
        $this->objHeader = null;
942
        $this->lastResponse = $this->sendRequest($body, $parameters);
943
        return $this->lastResponse;
944
    }
945
946
    /**
947
     * Maintenance of the Taxpayer Security Code - CSC (Old Token)
948
     * @param int $indOp Identificador do tipo de operação:
949
     *                   1 - Consulta CSC Ativos;
950
     *                   2 - Solicita novo CSC;
951
     *                   3 - Revoga CSC Ativo
952
     * @return string
953
     * @throws InvalidArgumentException
954
     * @throws RuntimeException
955
     */
956
    public function sefazCsc($indOp)
957
    {
958
        if (empty($indOp) || $indOp < 1 || $indOp > 3) {
959
            throw new InvalidArgumentException('CSC: identificador operacao invalido!');
960
        }
961
        if ($this->modelo != 65) {
962
            throw new RuntimeException('CSC: modelo diferente de 65!');
963
        }
964
        $raizCNPJ = substr($this->config->cnpj, 0, -6);
965
        //carrega serviço
966
        $servico = 'CscNFCe';
967
        $this->checkContingencyForWebServices($servico);
968
        $this->servico($servico, $this->config->siglaUF, $this->tpAmb);
969
        $request = "<admCscNFCe versao=\"$this->urlVersion\" xmlns=\"$this->urlPortal\">"
970
            . "<tpAmb>$this->tpAmb</tpAmb>"
971
            . "<indOp>$indOp</indOp>"
972
            . "<raizCNPJ>$raizCNPJ</raizCNPJ>"
973
            . "</admCscNFCe>";
974
        if ($indOp == 3) {
975
            $request = "<admCscNFCe versao=\"$this->urlVersion\" xmlns=\"$this->urlPortal\">"
976
            . "<tpAmb>$this->tpAmb</tpAmb>"
977
            . "<indOp>$indOp</indOp>"
978
            . "<raizCNPJ>$raizCNPJ</raizCNPJ>"
979
            . "<dadosCsc>"
980
            . "<idCsc>".$this->config->CSCid."</idCsc>"
981
            . "<codigoCsc>".$this->config->CSC."</codigoCsc>"
982
            . "</dadosCsc>"
983
            . "</admCscNFCe>";
984
        }
985
        //o xsd não está disponivel
986
        //$this->isValid($this->urlVersion, $request, 'cscNFCe');
987
        $this->lastRequest = $request;
988
        $parameters = ['nfeDadosMsg' => $request];
989
        $body = "<nfeDadosMsg xmlns=\"$this->urlNamespace\">$request</nfeDadosMsg>";
990
        $this->lastResponse = $this->sendRequest($body, $parameters);
991
        return $this->lastResponse;
992
    }
993
994
    /**
995
     * Checks the validity of an NFe, normally used for received NFe
996
     * @param string $nfe
997
     * @return bool
998
     * @throws InvalidArgumentException
999
     */
1000
    public function sefazValidate($nfe)
1001
    {
1002
        if (empty($nfe)) {
1003
            throw new InvalidArgumentException('Validacao NF-e: a string da NF-e esta vazia!');
1004
        }
1005
        //verifica a assinatura da NFe, exception caso de falha
1006
        Signer::isSigned($nfe);
1007
        $dom = new \DOMDocument('1.0', 'utf-8');
1008
        $dom->formatOutput = false;
1009
        $dom->preserveWhiteSpace = false;
1010
        $dom->loadXML($nfe);
1011
        //verifica a validade no webservice da SEFAZ
1012
        $tpAmb = $dom->getElementsByTagName('tpAmb')->item(0)->nodeValue;
1013
        $infNFe  = $dom->getElementsByTagName('infNFe')->item(0);
1014
        $chNFe = preg_replace('/[^0-9]/', '', $infNFe->getAttribute("Id"));
1015
        $protocol = $dom->getElementsByTagName('nProt')->item(0)->nodeValue;
1016
        $digval = $dom->getElementsByTagName('DigestValue')->item(0)->nodeValue;
1017
        //consulta a NFe
1018
        $response = $this->sefazConsultaChave($chNFe, $tpAmb);
1019
        $ret = new \DOMDocument('1.0', 'UTF-8');
1020
        $ret->preserveWhiteSpace = false;
1021
        $ret->formatOutput = false;
1022
        $ret->loadXML($response);
1023
        $retProt = $ret->getElementsByTagName('protNFe')->item(0);
1024
        if (!isset($retProt)) {
1025
            $xMotivo = $ret->getElementsByTagName('xMotivo')->item(0);
1026
            if (isset($xMotivo)) {
1027
                throw new InvalidArgumentException('Validacao NF-e: ' . $xMotivo->nodeValue);
1028
            } else {
1029
                throw new InvalidArgumentException('O documento de resposta nao contem o node "protNFe".');
1030
            }
1031
        }
1032
        $infProt = $ret->getElementsByTagName('infProt')->item(0);
1033
        $dig = $infProt->getElementsByTagName("digVal")->item(0);
1034
        $digProt = '000';
1035
        if (isset($dig)) {
1036
            $digProt = $dig->nodeValue;
1037
        }
1038
        $chProt = $infProt->getElementsByTagName("chNFe")->item(0)->nodeValue;
1039
        $nProt = $infProt->getElementsByTagName("nProt")->item(0)->nodeValue;
1040
        if ($protocol == $nProt && $digval == $digProt && $chNFe == $chProt) {
1041
            return true;
1042
        }
1043
        return false;
1044
    }
1045
1046
    /**
1047
     * Returns alias and description event from event code.
1048
     * @param  int $tpEvento
1049
     * @return \stdClass
1050
     * @throws \RuntimeException
1051
     */
1052
    private function tpEv($tpEvento)
1053
    {
1054
        $std = new \stdClass();
1055
        $std->alias = '';
1056
        $std->desc = '';
1057
        switch ($tpEvento) {
1058
            case self::EVT_CCE:
1059
                $std->alias = 'CCe';
1060
                $std->desc = 'Carta de Correcao';
1061
                break;
1062
            case self::EVT_CANCELA:
1063
                $std->alias = 'CancNFe';
1064
                $std->desc = 'Cancelamento';
1065
                break;
1066
            case self::EVT_CANCELASUBSTITUICAO:
1067
                $std->alias = 'CancNFe';
1068
                $std->desc = 'Cancelamento por substituicao';
1069
                break;
1070
            case self::EVT_EPEC: // Emissão em contingência EPEC
1071
                $std->alias = 'EPEC';
1072
                $std->desc = 'EPEC';
1073
                break;
1074
            case self::EVT_COMPROVANTE_ENTREGA:
1075
                $std->alias = 'CompEntrega';
1076
                $std->desc = 'Comprovante de Entrega';
1077
                break;
1078
            case self::EVT_CANCELAMENTO_COMPROVANTE_ENTREGA:
1079
                $std->alias = 'CancCompEntrega';
1080
                $std->desc = 'Cancelamento do Comprovante de Entrega';
1081
                break;
1082
            case 111500:
1083
            case 111501:
1084
                //EPP
1085
                //Pedido de prorrogação
1086
                $std->alias = 'EPP';
1087
                $std->desc = 'Pedido de Prorrogacao';
1088
                break;
1089
            case 111502:
1090
            case 111503:
1091
                //ECPP
1092
                //Cancelamento do Pedido de prorrogação
1093
                $std->alias = 'ECPP';
1094
                $std->desc = 'Cancelamento de Pedido de Prorrogacao';
1095
                break;
1096
            case self::EVT_CONFIRMACAO: // Manifestação Confirmacao da Operação
1097
                $std->alias = 'EvConfirma';
1098
                $std->desc = 'Confirmacao da Operacao';
1099
                break;
1100
            case self::EVT_CIENCIA: // Manifestação Ciencia da Operação
1101
                $std->alias = 'EvCiencia';
1102
                $std->desc = 'Ciencia da Operacao';
1103
                $std->tpAutor = 2;
1104
                break;
1105
            case self::EVT_DESCONHECIMENTO: // Manifestação Desconhecimento da Operação
1106
                $std->alias = 'EvDesconh';
1107
                $std->desc = 'Desconhecimento da Operacao';
1108
                break;
1109
            case self::EVT_NAO_REALIZADA: // Manifestação Operacao não Realizada
1110
                $std->alias = 'EvNaoRealizada';
1111
                $std->desc = 'Operacao nao Realizada';
1112
                break;
1113
            case self::EVT_ATORINTERESSADO: //ator interessado
1114
                $std->alias = 'EvAtorInteressado';
1115
                $std->desc = 'Ator interessado na NF-e';
1116
                break;
1117
            default:
1118
                $msg = "O código do tipo de evento informado não corresponde a "
1119
                . "nenhum evento estabelecido.";
1120
                throw new RuntimeException($msg);
1121
        }
1122
        return $std;
1123
    }
1124
}
1125