Passed
Push — master ( c81c33...3c7bec )
by Roberto
02:13 queued 11s
created

src/Tools.php (1 issue)

Labels
Severity

Upgrade to new PHP Analysis Engine

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
The variable $nSeqEvento 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...
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