Passed
Push — master ( d4f5be...652757 )
by
unknown
02:22 queued 14s
created

Tools::sefazCE()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 43

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 43
ccs 0
cts 40
cp 0
rs 9.232
c 0
b 0
f 0
cc 2
nc 2
nop 10
crap 6

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace NFePHP\CTe;
4
5
/**
6
 * Class responsible for communication with SEFAZ extends
7
 * NFePHP\CTe\Common\Tools
8
 *
9
 * @category  NFePHP
10
 * @package   NFePHP\CTe\Tools
11
 * @copyright NFePHP Copyright (c) 2008-2017
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-cte 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\CTe\Factories\Events;
23
use NFePHP\CTe\Common\Tools as ToolsCommon;
24
use RuntimeException;
25
use InvalidArgumentException;
26
27
class Tools extends ToolsCommon
28
{
29
    const EVT_CONFIRMACAO = 210200;
30
    const EVT_CIENCIA = 210210;
31
    const EVT_DESCONHECIMENTO = 210220;
32
    const EVT_NAO_REALIZADA = 210240;
33
34
    /**
35
     * Request authorization to issue CTe in batch with one or more documents
36
     * @param array $aXml array of cte's xml
37
     * @param string $idLote lote number
38
     * @param bool $compactar flag to compress data with gzip
39
     * @return string soap response xml
40
     */
41
    public function sefazEnviaLote(
42
        $aXml,
43
        $idLote = '',
44
        $compactar = false,
45
        &$xmls = []
46
    ) {
47
        if (!is_array($aXml)) {
48
            throw new \InvalidArgumentException('Os XML das CTe devem ser passados em um array.');
49
        }
50
        $servico = 'CteRecepcao';
51
        $this->checkContingencyForWebServices($servico);
52
        if ($this->contingency->type != '') {
53
            //em modo de contingencia
54
            //esses xml deverão ser modificados e re-assinados e retornados
55
            //no parametro $xmls para serem armazenados pelo aplicativo
56
            //pois serão alterados
57
            foreach ($aXml as $doc) {
58
                //corrigir o xml para o tipo de contigência setado
59
                $xmls[] = $this->correctCTeForContingencyMode($doc);
60
            }
61
            $aXml = $xmls;
62
        }
63
64
        $sxml = implode("", $aXml);
65
        $sxml = preg_replace("/<\?xml.*?\?>/", "", $sxml);
66
        $this->servico(
67
            $servico,
68
            $this->config->siglaUF,
69
            $this->tpAmb
70
        );
71
        $request = "<enviCTe xmlns=\"$this->urlPortal\" versao=\"$this->urlVersion\">"
72
            . "<idLote>$idLote</idLote>"
73
            . "$sxml"
74
            . "</enviCTe>";
75
        $this->isValid($this->urlVersion, $request, 'enviCTe');
76
        $this->lastRequest = $request;
77
        //montagem dos dados da mensagem SOAP
78
        $parameters = ['cteDadosMsg' => $request];
79
        $body = "<cteDadosMsg xmlns=\"$this->urlNamespace\">$request</cteDadosMsg>";
80
        $method = $this->urlMethod;
81
        if ($compactar) {
82
            $gzdata = base64_encode(gzencode($cons, 9, FORCE_GZIP));
83
            $body = "<cteDadosMsgZip xmlns=\"$this->urlNamespace\">$gzdata</cteDadosMsgZip>";
84
            $method = $this->urlMethod."Zip";
85
            $parameters = ['cteDadosMsgZip' => $gzdata];
86
            $body = "<cteDadosMsgZip xmlns=\"$this->urlNamespace\">$gzdata</cteDadosMsgZip>";
87
        }
88
        $this->lastResponse = $this->sendRequest($body, $parameters);
89
        return $this->lastResponse;
90
    }
91
    
92
    /**
93
     * Request authorization to issue CTe OS with one document only
94
     * @param type $xml
95
     * @return type
96
     */
97
    public function sefazEnviaCTeOS($xml)
98
    {
99
        //carrega serviço
100
        $servico = 'CteRecepcaoOS';
101
        $this->checkContingencyForWebServices($servico);
102
        $this->servico(
103
            $servico,
104
            $this->config->siglaUF,
105
            $this->tpAmb
106
        );
107
        $request = preg_replace("/<\?xml.*\?>/", "", $xml);
108
        $this->isValid($this->urlVersion, $request, 'cteOS');
109
        $this->lastRequest = $request;
110
        $body = "<cteDadosMsg xmlns=\"$this->urlNamespace\">$request</cteDadosMsg>";
111
        $this->lastResponse = $this->sendRequest($body);
112
        return $this->lastResponse;
113
    }
114
115
    /**
116
     * Check status of Batch of CTe sent by receipt of this shipment
117
     * @param string $recibo
118
     * @param int $tpAmb
119
     * @return string
120
     */
121
    public function sefazConsultaRecibo($recibo, $tpAmb = null)
122
    {
123
        if (empty($tpAmb)) {
124
            $tpAmb = $this->tpAmb;
125
        }
126
        //carrega serviço
127
        $servico = 'CteRetRecepcao';
128
        $this->checkContingencyForWebServices($servico);
129
        $this->servico(
130
            $servico,
131
            $this->config->siglaUF,
132
            $tpAmb
133
        );
134
        if ($this->urlService == '') {
135
            $msg = "A consulta de CTe não está disponível na SEFAZ {$this->config->siglaUF}!!!";
136
            throw new RuntimeException($msg);
137
        }
138
        $request = "<consReciCTe xmlns=\"$this->urlPortal\" versao=\"$this->urlVersion\">"
139
            . "<tpAmb>$tpAmb</tpAmb>"
140
            . "<nRec>$recibo</nRec>"
141
            . "</consReciCTe>";
142
        $this->isValid($this->urlVersion, $request, 'consReciCTe');
143
        $this->lastRequest = $request;
144
        $parameters = ['cteDadosMsg' => $request];
145
        $body = "<cteDadosMsg xmlns=\"$this->urlNamespace\">$request</cteDadosMsg>";
146
        $this->lastResponse = $this->sendRequest($body, $parameters);
147
        return $this->lastResponse;
148
    }
149
150
    /**
151
     * Check the CTe status for the 44-digit key and retrieve the protocol
152
     * @param string $chave
153
     * @param int $tpAmb
154
     * @return string
155
     */
156
    public function sefazConsultaChave($chave, $tpAmb = null)
157
    {
158
        $uf = UFList::getUFByCode(substr($chave, 0, 2));
159
        if (empty($tpAmb)) {
160
            $tpAmb = $this->tpAmb;
161
        }
162
        //carrega serviço
163
        $servico = 'CteConsultaProtocolo';
164
        $this->checkContingencyForWebServices($servico);
165
        $this->servico(
166
            $servico,
167
            $uf,
168
            $tpAmb
169
        );
170
        $request = "<consSitCTe xmlns=\"$this->urlPortal\" versao=\"$this->urlVersion\">"
171
            . "<tpAmb>$tpAmb</tpAmb>"
172
            . "<xServ>CONSULTAR</xServ>"
173
            . "<chCTe>$chave</chCTe>"
174
            . "</consSitCTe>";
175
        $this->isValid($this->urlVersion, $request, 'consSitCTe');
176
        $this->lastRequest = $request;
177
        $parameters = ['cteDadosMsg' => $request];
178
        $body = "<cteDadosMsg xmlns=\"$this->urlNamespace\">$request</cteDadosMsg>";
179
        $this->lastResponse = $this->sendRequest($body, $parameters);
180
        return $this->lastResponse;
181
    }
182
183
    /**
184
     * Request to disable one or an NFe sequence of a given series
185
     * @param int $nSerie
186
     * @param int $nIni
187
     * @param int $nFin
188
     * @param string $xJust
189
     * @param int $tpAmb
190
     * @return string
191
     */
192
    public function sefazInutiliza(
193
        $nSerie,
194
        $nIni,
195
        $nFin,
196
        $xJust,
197
        $tpAmb = null
198
    ) {
199
        if (empty($tpAmb)) {
200
            $tpAmb = $this->tpAmb;
201
        }
202
        $xJust = Strings::replaceSpecialsChars($xJust);
203
        $nSerie = (integer) $nSerie;
204
        $nIni = (integer) $nIni;
205
        $nFin = (integer) $nFin;
206
        $servico = 'CteInutilizacao';
207
        $this->checkContingencyForWebServices($servico);
208
        //carrega serviço
209
        $this->servico(
210
            $servico,
211
            $this->config->siglaUF,
212
            $tpAmb
213
        );
214
        $cnpj = $this->config->cnpj;
215
        $strAno = (string) date('y');
216
        $strSerie = str_pad($nSerie, 3, '0', STR_PAD_LEFT);
217
        $strInicio = str_pad($nIni, 9, '0', STR_PAD_LEFT);
218
        $strFinal = str_pad($nFin, 9, '0', STR_PAD_LEFT);
219
        $idInut = "ID"
220
            . $this->urlcUF
221
            . $cnpj
222
            . $this->modelo
223
            . $strSerie
224
            . $strInicio
225
            . $strFinal;
226
        //limpa os caracteres indesejados da justificativa
227
        $xJust = Strings::replaceSpecialsChars($xJust);
228
        //montagem do corpo da mensagem
229
        $msg = "<inutCTe xmlns=\"$this->urlPortal\" versao=\"$this->urlVersion\">" .
230
            "<infInut Id=\"$idInut\">" .
231
            "<tpAmb>$tpAmb</tpAmb>" .
232
            "<xServ>INUTILIZAR</xServ>" .
233
            "<cUF>$this->urlcUF</cUF>" .
234
            "<ano>$strAno</ano>" .
235
            "<CNPJ>$cnpj</CNPJ>" .
236
            "<mod>$this->modelo</mod>" .
237
            "<serie>$nSerie</serie>" .
238
            "<nCTIni>$nIni</nCTIni>" .
239
            "<nCTFin>$nFin</nCTFin>" .
240
            "<xJust>$xJust</xJust>" .
241
            "</infInut></inutCTe>";
242
        //assina a solicitação
243
        $request = Signer::sign(
244
            $this->certificate,
245
            $msg,
246
            'infInut',
247
            'Id',
248
            $this->algorithm,
249
            $this->canonical
250
        );
251
        $request = Strings::clearXmlString($request, true);
252
        $this->isValid($this->urlVersion, $request, 'inutCTe');
253
        $this->lastRequest = $request;
254
        $parameters = ['cteDadosMsg' => $request];
255
        $body = "<cteDadosMsg xmlns=\"$this->urlNamespace\">$request</cteDadosMsg>";
256
        $this->lastResponse = $this->sendRequest($body, $parameters);
257
        return $this->lastResponse;
258
    }
259
260
    /**
261
     * Search for the registration data of an NFe issuer,
262
     * if in contingency mode this service will cause a
263
     * Exception and remember not all Sefaz have this service available,
264
     * so it will not work in some cases.
265
     * @param string $uf  federation unit
266
     * @param string $cnpj CNPJ number (optional)
267
     * @param string $iest IE number (optional)
268
     * @param string $cpf  CPF number (optional)
269
     * @return string xml soap response
270
     */
271
    public function sefazCadastro(
272
        $uf,
273
        $cnpj = '',
274
        $iest = '',
275
        $cpf = ''
276
    ) {
277
        if ($cnpj != '') {
278
            $filter = "<CNPJ>$cnpj</CNPJ>";
279
            $txtFile = "CNPJ_$cnpj";
280
        } elseif ($iest != '') {
281
            $filter = "<IE>$iest</IE>";
282
            $txtFile = "IE_$iest";
283
        } else {
284
            $filter = "<CPF>$cpf</CPF>";
285
            $txtFile = "CPF_$cpf";
286
        }
287
        //carrega serviço
288
        $servico = 'CteConsultaCadastro';
289
        $this->checkContingencyForWebServices($servico);
290
        $this->servico(
291
            $servico,
292
            $uf,
293
            $this->tpAmb,
294
            true
295
        );
296
        $request = "<ConsCad xmlns=\"$this->urlPortal\" versao=\"$this->urlVersion\">"
297
            . "<infCons>"
298
            . "<xServ>CONS-CAD</xServ>"
299
            . "<UF>$uf</UF>"
300
            . "$filter</infCons></ConsCad>";
301
        $this->isValid($this->urlVersion, $request, 'consCad');
302
        $this->lastRequest = $request;
303
        $parameters = ['cteDadosMsg' => $request];
304
        $body = "<cteDadosMsg xmlns=\"$this->urlNamespace\">$request</cteDadosMsg>";
305
        $this->lastResponse = $this->sendRequest($body, $parameters);
306
        return $this->lastResponse;
307
    }
308
309
    /**
310
     * Check services status SEFAZ/SVC
311
     * If $uf is empty use normal check with contingency
312
     * If $uf is NOT empty ignore contingency mode
313
     * @param string $uf  initials of federation unit
314
     * @param int $tpAmb
315
     * @return string xml soap response
316
     */
317
    public function sefazStatus($uf = '', $tpAmb = null)
318
    {
319
        if (empty($tpAmb)) {
320
            $tpAmb = $this->tpAmb;
321
        }
322
        $ignoreContingency = true;
323
        if (empty($uf)) {
324
            $uf = $this->config->siglaUF;
325
            $ignoreContingency = false;
326
        }
327
        $servico = 'CteStatusServico';
328
        $this->checkContingencyForWebServices($servico);
329
        $this->servico(
330
            $servico,
331
            $uf,
332
            $tpAmb,
333
            $ignoreContingency
334
        );
335
        $request = "<consStatServCte xmlns=\"$this->urlPortal\" versao=\"$this->urlVersion\">"
336
            . "<tpAmb>$tpAmb</tpAmb>"
337
            . "<xServ>STATUS</xServ></consStatServCte>";
338
        $this->isValid($this->urlVersion, $request, 'consStatServCte');
339
        $this->lastRequest = $request;
340
        $parameters = ['cteDadosMsg' => $request];
341
        $body = "<cteDadosMsg xmlns=\"$this->urlNamespace\">$request</cteDadosMsg>";
342
        $this->lastResponse = $this->sendRequest($body, $parameters);
343
        return $this->lastResponse;
344
    }
345
346
    /**
347
     * Service for the distribution of summary information and
348
     * electronic tax documents of interest to an actor.
349
     * @param integer $ultNSU  last NSU number recived
350
     * @param integer $numNSU  NSU number you wish to consult
351
     * @param string $fonte data source 'AN' and for some cases it may be 'RS'
352
     * @return string
353
     */
354
    public function sefazDistDFe(
355
        $ultNSU = 0,
356
        $numNSU = 0,
357
        $fonte = 'AN'
358
    ) {
359
        //carrega serviço
360
        $servico = 'CTeDistribuicaoDFe';
361
        $this->checkContingencyForWebServices($servico);
362
        $this->servico(
363
            $servico,
364
            $fonte,
365
            $this->tpAmb,
366
            true
367
        );
368
        $cUF = UFList::getCodeByUF($this->config->siglaUF);
369
        $ultNSU = str_pad($ultNSU, 15, '0', STR_PAD_LEFT);
370
        $tagNSU = "<distNSU><ultNSU>$ultNSU</ultNSU></distNSU>";
371
        if ($numNSU != 0) {
372
            $numNSU = str_pad($numNSU, 15, '0', STR_PAD_LEFT);
373
            $tagNSU = "<consNSU><NSU>$numNSU</NSU></consNSU>";
374
        }
375
        //monta a consulta
376
        $consulta = "<distDFeInt xmlns=\"$this->urlPortal\" versao=\"$this->urlVersion\">"
377
            . "<tpAmb>".$this->tpAmb."</tpAmb>"
378
            . "<cUFAutor>$cUF</cUFAutor>"
379
            . ((strlen($this->config->cnpj)==14) ? 
380
                "<CNPJ>".$this->config->cnpj."</CNPJ>" : 
381
                "<CPF>".$this->config->cnpj."</CPF>"
382
              )
383
            . $tagNSU."</distDFeInt>";
384
        //valida o xml da requisição
385
        $this->isValid($this->urlVersion, $consulta, 'distDFeInt');
386
        $this->lastRequest = $consulta;
387
        //montagem dos dados da mensagem SOAP
388
        $request = "<cteDadosMsg xmlns=\"$this->urlNamespace\">$consulta</cteDadosMsg>";
389
        $parameters = ['cteDistDFeInteresse' => $request];
390
        $body = "<cteDistDFeInteresse xmlns=\"$this->urlNamespace\">"
391
            . $request
392
            . "</cteDistDFeInteresse>";
393
        //este webservice não requer cabeçalho
394
        $this->objHeader = null;
395
        $this->lastResponse = $this->sendRequest($body, $parameters);
396
        return $this->lastResponse;
397
    }
398
399
    /**
400
     * Request authorization for Letter of Correction
401
     * @param  string $chave
402
     * @param  array $infCorrecao
403
     * @param  int $nSeqEvento
404
     * @return string
405
     */
406
    public function sefazCCe($chave, $infCorrecao = [], $nSeqEvento = 1)
407
    {
408
        $uf = $this->validKeyByUF($chave);
409
        $tpEvento = 110110;
410
        $tagAdic = self::serializerCCe($infCorrecao);
411
        return $this->sefazEvento(
412
            $uf,
413
            $chave,
414
            $tpEvento,
415
            $nSeqEvento,
416
            $tagAdic
417
        );
418
    }
419
420
    /**
421
     * Request extension of the term of return of products of an NF-e of
422
     * consignment for industrialization to order with suspension of ICMS
423
     * in interstate operations
424
     * @param  string  $chNFe
425
     * @param  string  $nProt
426
     * @param  integer $tipo 1-primerio prazo, 2-segundo prazo
427
     * @param  array   $itens
428
     * @param  integer $nSeqEvento
429
     * @return string
430
     */
431
    public function sefazEPP(
432
        $chNFe,
433
        $nProt,
434
        $itens = array(),
435
        $tipo = 1,
436
        $nSeqEvento = 1
437
    ) {
438
        $uf = UFList::getUFByCode(substr($chNFe, 0, 2));
439
        $tpEvento = 111500;
440
        if ($tipo == 2) {
441
            $tpEvento = 111501;
442
        }
443
        $tagAdic = "<nProt>$nProt</nProt>";
444
        foreach ($itens as $item) {
445
            $tagAdic .= "<itemPedido numItem=\""
446
                . $item[0]
447
                . "\"><qtdeItem>"
448
                . $item[1]
449
                ."</qtdeItem></itemPedido>";
450
        }
451
        return $this->sefazEvento(
452
            $uf,
453
            $chNFe,
454
            $tpEvento,
455
            $nSeqEvento,
456
            $tagAdic
457
        );
458
    }
459
460
    /**
461
     * Request the cancellation of the request for an extension of the term
462
     * of return of products of an NF-e of consignment for industrialization
463
     * by order with suspension of ICMS in interstate operations
464
     * @param  string  $chNFe
465
     * @param  string  $nProt
466
     * @param  integer $nSeqEvento
467
     * @return string
468
     */
469
    public function sefazECPP(
470
        $chNFe,
471
        $nProt,
472
        $nSeqEvento = 1
473
    ) {
474
        $uf = UFList::getUFByCode(substr($chNFe, 0, 2));
475
        $tpEvento = 111502;
476
        $origEvent = 111500;
477
        if ($nSeqEvento == 2) {
478
            $tpEvento = 111503;
479
            $origEvent = 111501;
480
        }
481
        $sSeqEvento = str_pad($nSeqEvento, 2, "0", STR_PAD_LEFT);
482
        $idPedidoCancelado = "ID$origEvent$chNFe$sSeqEvento";
483
        $tagAdic = "<idPedidoCancelado>"
484
                . "$idPedidoCancelado"
485
                . "</idPedidoCancelado>"
486
                . "<nProt>$nProt</nProt>";
487
        return $this->sefazEvento(
488
            $uf,
489
            $chNFe,
490
            $tpEvento,
491
            $nSeqEvento,
492
            $tagAdic
493
        );
494
    }
495
496
    /**
497
     * Requires cte cancellation
498
     * @param  string $chave key of CTe
499
     * @param  string $xJust justificative 255 characters max
500
     * @param  string $nProt protocol number
501
     * @return string
502
     */
503
    public function sefazCancela($chave, $xJust, $nProt)
504
    {
505
        $uf = $this->validKeyByUF($chave);
506
        $xJust = Strings::replaceSpecialsChars(
507
            substr(trim($xJust), 0, 255)
508
        );
509
        $tpEvento = 110111;
510
        $nSeqEvento = 1;
511
        $tagAdic = "<evCancCTe>"
512
            . "<descEvento>Cancelamento</descEvento>"
513
            . "<nProt>$nProt</nProt>"
514
            . "<xJust>$xJust</xJust>"
515
            . "</evCancCTe>";
516
        return $this->sefazEvento(
517
            $uf,
518
            $chave,
519
            $tpEvento,
520
            $nSeqEvento,
521
            $tagAdic
522
        );
523
    }
524
525
    /**
526
     * Request the registration of the manifestation of recipient
527
     * @param string $chNFe
528
     * @param int $tpEvento
529
     * @param string $xJust Justification for not carrying out the operation
530
     * @param int $nSeqEvento
531
     * @return string
532
     */
533
    public function sefazManifesta(
534
        $chNFe,
535
        $tpEvento,
536
        $xJust = '',
537
        $nSeqEvento = 1,
538
        $ufEvento = 'RS'
539
    ) {
540
        $tagAdic = '';
541
        if ($tpEvento == 610110) {
542
            $xJust = Strings::replaceSpecialsChars(substr(trim($xJust), 0, 255));
543
            $tagAdic = "<evPrestDesacordo>"
544
                . "<descEvento>Prestacao do Servico em Desacordo</descEvento>"
545
                . "<indDesacordoOper>1</indDesacordoOper>"
546
                . "<xObs>$xJust</xObs>"
547
                . "</evPrestDesacordo>";
548
        }
549
        return $this->sefazEvento(
550
            $ufEvento,
551
            $chNFe,
552
            $tpEvento,
553
            $nSeqEvento,
554
            $tagAdic
555
        );
556
    }
557
558
    /**
559
     * Request authorization for issuance in contingency EPEC
560
     * @param  string $xml
561
     * @return string
562
     */
563
    public function sefazEPEC(&$xml)
564
    {
565
        $tagAdic = '';
566
        $tpEvento = 110140;
567
        $nSeqEvento = 1;
568
        if ($this->contingency->type !== 'EPEC') {
569
            throw new \RuntimeException('A contingência EPEC deve estar ativada.');
570
        }
571
        $xml = $this->correctCTeForContingencyMode($xml);
572
        $dom = new \DOMDocument('1.0', 'UTF-8');
573
        $dom->preserveWhiteSpace = false;
574
        $dom->formatOutput = false;
575
        $dom->loadXML($xml);
576
        $infNFe = $dom->getElementsByTagName('infNFe')->item(0);
577
        $emit = $dom->getElementsByTagName('emit')->item(0);
578
        $dest = $dom->getElementsByTagName('dest')->item(0);
579
        $cOrgaoAutor = UFList::getCodeByUF($this->config->siglaUF);
580
        $chNFe = substr($infNFe->getAttribute('Id'), 3, 44);
581
        // EPEC
582
        $dhEmi = $dom->getElementsByTagName('dhEmi')->item(0)->nodeValue;
583
        $tpNF = $dom->getElementsByTagName('tpNF')->item(0)->nodeValue;
584
        $emitIE = $emit->getElementsByTagName('IE')->item(0)->nodeValue;
585
        $destUF = $dest->getElementsByTagName('UF')->item(0)->nodeValue;
586
        $total = $dom->getElementsByTagName('total')->item(0);
587
        $vNF = $total->getElementsByTagName('vNF')->item(0)->nodeValue;
588
        $vICMS = $total->getElementsByTagName('vICMS')->item(0)->nodeValue;
589
        $vST = $total->getElementsByTagName('vST')->item(0)->nodeValue;
590
        $dID = $dest->getElementsByTagName('CNPJ')->item(0)->nodeValue;
591
        if (!empty($dID)) {
592
            $destID = "<CNPJ>$dID</CNPJ>";
593
        } else {
594
            $dID = $dest->getElementsByTagName('CPF')->item(0)->nodeValue;
595
            if (!empty($dID)) {
596
                $destID = "<CPF>$dID</CPF>";
597
            } else {
598
                $dID = $dest->getElementsByTagName('idEstrangeiro')
599
                    ->item(0)
600
                    ->nodeValue;
601
                $destID = "<idEstrangeiro>$dID</idEstrangeiro>";
602
            }
603
        }
604
        $dIE = !empty($dest->getElementsByTagName('IE')->item(0)->nodeValue) ?
605
                $dest->getElementsByTagName('IE')->item(0)->nodeValue : '';
606
        $destIE = '';
607
        if (!empty($dIE)) {
608
            $destIE = "<IE>$dIE</IE>";
609
        }
610
        $tagAdic = "<cOrgaoAutor>$cOrgaoAutor</cOrgaoAutor>"
611
            . "<tpAutor>1</tpAutor>"
612
            . "<verAplic>$this->verAplic</verAplic>"
613
            . "<dhEmi>$dhEmi</dhEmi>"
614
            . "<tpNF>$tpNF</tpNF>"
615
            . "<IE>$emitIE</IE>"
616
            . "<dest>"
617
            . "<UF>$destUF</UF>"
618
            . $destID
619
            . $destIE
620
            . "<vNF>$vNF</vNF>"
621
            . "<vICMS>$vICMS</vICMS>"
622
            . "<vST>$vST</vST>"
623
            . "</dest>";
624
625
        return $this->sefazEvento(
626
            'AN',
627
            $chNFe,
628
            $tpEvento,
629
            $nSeqEvento,
630
            $tagAdic
631
        );
632
    }
633
634
    /**
635
     * Send event to SEFAZ
636
     * @param string $uf
637
     * @param string $chave
638
     * @param int $tpEvento
639
     * @param int $nSeqEvento
640
     * @param string $tagAdic
641
     * @return string
642
     */
643
    public function sefazEvento(
644
        $uf,
645
        $chave,
646
        $tpEvento,
647
        $nSeqEvento = 1,
648
        $tagAdic = ''
649
    ) {
650
        $ignore = false;
651
        if ($tpEvento == 110140) {
652
            $ignore = true;
653
        }
654
        $servico = 'CteRecepcaoEvento';
655
        $this->checkContingencyForWebServices($servico);
656
        $this->servico(
657
            $servico,
658
            $uf,
659
            $this->tpAmb,
660
            $ignore
661
        );
662
        $ev = $this->tpEv($tpEvento);
663
        $aliasEvento = $ev->alias;
664
        $descEvento = $ev->desc;
665
        $cnpj = $this->config->cnpj;
666
        $dt = new \DateTime();
667
        $dhEvento = $dt->format('Y-m-d\TH:i:sP');
668
        $sSeqEvento = str_pad($nSeqEvento, 2, "0", STR_PAD_LEFT);
669
        $eventId = "ID".$tpEvento.$chave.$sSeqEvento;
670
        $cOrgao = UFList::getCodeByUF($uf);
671
672
        $request = "<eventoCTe xmlns=\"$this->urlPortal\" versao=\"$this->urlVersion\">"
673
            . "<infEvento Id=\"$eventId\">"
674
            . "<cOrgao>$cOrgao</cOrgao>"
675
            . "<tpAmb>$this->tpAmb</tpAmb>"
676
            . "<CNPJ>$cnpj</CNPJ>"
677
            . "<chCTe>$chave</chCTe>"
678
            . "<dhEvento>$dhEvento</dhEvento>"
679
            . "<tpEvento>$tpEvento</tpEvento>"
680
            . "<nSeqEvento>$nSeqEvento</nSeqEvento>"
681
            . "<detEvento versaoEvento=\"$this->urlVersion\">"
682
            . "$tagAdic"
683
            . "</detEvento>"
684
            . "</infEvento>"
685
            . "</eventoCTe>";
686
687
        //assinatura dos dados
688
        $request = Signer::sign(
689
            $this->certificate,
690
            $request,
691
            'infEvento',
692
            'Id',
693
            $this->algorithm,
694
            $this->canonical
695
        );
696
697
        $request = Strings::clearXmlString($request, true);
698
        $this->isValid($this->urlVersion, $request, 'eventoCTe');
699
        $this->lastRequest = $request;
700
        $parameters = ['cteDadosMsg' => $request];
701
        $body = "<cteDadosMsg xmlns=\"$this->urlNamespace\">$request</cteDadosMsg>";
702
        $this->lastResponse = $this->sendRequest($body, $parameters);
703
        return $this->lastResponse;
704
    }
705
706
    /**
707
     * Request the NFe download already manifested by its recipient, by the key
708
     * using new service in CTeDistribuicaoDFe
709
     * @param  string $chave
710
     * @return string
711
     */
712
    public function sefazDownload($chave)
713
    {
714
        //carrega serviço
715
        $servico = 'CteDistribuicaoDFe';
716
        $this->checkContingencyForWebServices($servico);
717
        $this->servico(
718
            $servico,
719
            'AN',
720
            $this->tpAmb,
721
            true
722
        );
723
        $cUF = UFList::getCodeByUF($this->config->siglaUF);
724
        $tagChave = "<consChNFe><chNFe>$chave</chNFe></consChNFe>";
725
        //monta a consulta
726
            . ((strlen($this->config->cnpj)==14) ? 
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected '.'
Loading history...
727
                "<CNPJ>".$this->config->cnpj."</CNPJ>" : 
728
                "<CPF>".$this->config->cnpj."</CPF>"
729
              )
730
            . $tagChave."</distDFeInt>";
731
        //valida o xml da requisição
732
        $this->isValid($this->urlVersion, $consulta, 'distDFeInt');
733
        $this->lastRequest = $consulta;
734
        //montagem dos dados da mensagem SOAP
735
        $request = "<cteDadosMsg xmlns=\"$this->urlNamespace\">$consulta</cteDadosMsg>";
736
        $parameters = ['cteDistDFeInteresse' => $request];
737
        $body = "<cteDistDFeInteresse xmlns=\"$this->urlNamespace\">"
738
            . $request
739
            . "</cteDistDFeInteresse>";
740
        //este webservice não requer cabeçalho
741
        $this->objHeader = null;
742
        $this->lastResponse = $this->sendRequest($body, $parameters);
743
        return $this->lastResponse;
744
    }
745
746
    /**
747
     * Maintenance of the Taxpayer Security Code - CSC (Old Token)
748
     * @param int $indOp Identificador do tipo de operação:
749
     *                   1 - Consulta CSC Ativos;
750
     *                   2 - Solicita novo CSC;
751
     *                   3 - Revoga CSC Ativo
752
     * @return string
753
     */
754
    public function sefazCsc($indOp)
755
    {
756
        if ($this->modelo != 65) {
757
            throw new RuntimeException(
758
                "Esta operação é exclusiva de NFCe modelo [65], "
759
                . "você está usando modelo [55]."
760
            );
761
        }
762
        $raizCNPJ = substr($this->config->cnpj, 0, -6);
763
        //carrega serviço
764
        $servico = 'CscNFCe';
765
        $this->checkContingencyForWebServices($servico);
766
        $this->servico(
767
            $servico,
768
            $this->config->siglaUF,
769
            $this->tpAmb
770
        );
771
        $request = "<admCscNFCe versao=\"$this->urlVersion\" xmlns=\"$this->urlPortal\">"
772
            . "<tpAmb>$this->tpAmb</tpAmb>"
773
            . "<indOp>$indOp</indOp>"
774
            . "<raizCNPJ>$raizCNPJ</raizCNPJ>"
775
            . "</admCscNFCe>";
776
        if ($indOp == 3) {
777
            $request = "<admCscNFCe versao=\"$this->urlVersion\" xmlns=\"$this->urlPortal\">"
778
            . "<tpAmb>$this->tpAmb</tpAmb>"
779
            . "<indOp>$indOp</indOp>"
780
            . "<raizCNPJ>$raizCNPJ</raizCNPJ>"
781
            . "<dadosCsc>"
782
            . "<idCsc>".$this->config->CSCid."</idCsc>"
783
            . "<codigoCsc>".$this->config->CSC."</codigoCsc>"
784
            . "</dadosCsc>"
785
            . "</admCscNFCe>";
786
        }
787
        //o xsd não está disponivel
788
        //$this->isValid($this->urlVersion, $request, 'cscNFCe');
789
        $this->lastRequest = $request;
790
        $parameters = ['cteDadosMsg' => $request];
791
        $body = "<cteDadosMsg xmlns=\"$this->urlNamespace\">$request</cteDadosMsg>";
792
        $this->lastResponse = $this->sendRequest($body, $parameters);
793
        return $this->lastResponse;
794
    }
795
796
    /**
797
     * Checks the validity of an CTe, normally used for received CTe
798
     * @param  string $cte
799
     * @return boolean
800
     */
801
    public function sefazValidate($cte)
802
    {
803
        if (empty($cte)) {
804
            throw new InvalidArgumentException('Validacao CT-e: a string do CT-e esta vazio!');
805
        }
806
        //verifica a assinatura do CTe, exception caso de falha
807
        Signer::isSigned($cte, 'infCte');
808
        $dom = new \DOMDocument('1.0', 'utf-8');
809
        $dom->formatOutput = false;
810
        $dom->preserveWhiteSpace = false;
811
        $dom->loadXML($cte);
812
        //verifica a validade no webservice da SEFAZ
813
        $tpAmb = $dom->getElementsByTagName('tpAmb')->item(0)->nodeValue;
814
        $infCTe  = $dom->getElementsByTagName('infCte')->item(0);
815
        $chCTe = preg_replace('/[^0-9]/', '', $infCTe->getAttribute("Id"));
816
        $protocol = $dom->getElementsByTagName('nProt')->item(0)->nodeValue;
817
        $digval = $dom->getElementsByTagName('DigestValue')->item(0)->nodeValue;
818
        //consulta o CTe
819
        $response = $this->sefazConsultaChave($chCTe, $tpAmb);
820
        $ret = new \DOMDocument('1.0', 'UTF-8');
821
        $ret->preserveWhiteSpace = false;
822
        $ret->formatOutput = false;
823
        $ret->loadXML($response);
824
        $retProt = $ret->getElementsByTagName('protCTe')->item(0);
825
        if (!isset($retProt)) {
826
            $xMotivo = $ret->getElementsByTagName('xMotivo')->item(0);
827
            if (isset($xMotivo)) {
828
                throw new InvalidArgumentException('Validacao CT-e: ' . $xMotivo->nodeValue);
829
            } else {
830
                throw new InvalidArgumentException('O documento de resposta nao contem o node "protCTe".');
831
            }
832
        }
833
        $infProt = $ret->getElementsByTagName('infProt')->item(0);
834
        $dig = $infProt->getElementsByTagName("digVal")->item(0);
835
        $digProt = '000';
836
        if (isset($dig)) {
837
            $digProt = $dig->nodeValue;
838
        }
839
        $chProt = $infProt->getElementsByTagName("chCTe")->item(0)->nodeValue;
840
        $nProt = $infProt->getElementsByTagName("nProt")->item(0)->nodeValue;
841
        if ($protocol == $nProt && $digval == $digProt && $chCTe == $chProt) {
842
            return true;
843
        }
844
        return false;
845
    }
846
847
    /**
848
     * Requires CE
849
     * @param  string $chave key of CTe
850
     * @param  string $nProt Protocolo do CTe
851
     * @param  string $xNome Nome de quem recebeu a entrega
852
     * @param  string $nDoc  Documento de quem recebeu a entrega
853
     * @param  string $hash  Hash da Chave de acesso do CT-e + Imagem da assinatura no formato Base64
854
     * @param  int    $latitude  Latitude do ponto da entrega
855
     * @param  int    $longitude  Longitude do ponto da entrega
856
     * @param  int    $nSeqEvento No. sequencial do evento
857
     * @param  string $dhEventoEntrega Data e hora da geração do hash da entrega
858
     * @param  array  $aNFes Chave das NFes entregues
859
     * @return string
860
     */
861
    public function sefazCE(
862
        $chave,
863
        $nProt,
864
        $xNome,
865
        $nDoc,
866
        $hash,
867
        $latitude,
868
        $longitude,
869
        $nSeqEvento,
870
        $dhEventoEntrega,
871
        $aNFes = []
872
    ) {
873
        $uf = $this->validKeyByUF($chave);
874
        $tpEvento = 110180;
875
        
876
        /* relaciona as chaves das NFes */
877
        $infEntrega = '';
878
        foreach ($aNFes as $NFe) {
879
            $infEntrega .= "<infEntrega>"
880
                . "<chNFe>$NFe</chNFe>"
881
                . "</infEntrega>";
882
        }
883
884
        $tagAdic = "<evCECTe>"
885
            . "<descEvento>Comprovante de Entrega do CT-e</descEvento>"
886
            . "<nProt>$nProt</nProt>"
887
            . "<dhEntrega>$dhEventoEntrega</dhEntrega>"
888
            . "<nDoc>$nDoc</nDoc>"
889
            . "<xNome>$xNome</xNome>"
890
            . "<latitude>$latitude</latitude>"
891
            . "<longitude>$longitude</longitude>"
892
            . "<hashEntrega>$hash</hashEntrega>"
893
            . "<dhHashEntrega>$dhEventoEntrega</dhHashEntrega>"
894
            . $infEntrega
895
            . "</evCECTe>";
896
        return $this->sefazEvento(
897
            $uf,
898
            $chave,
899
            $tpEvento,
900
            $nSeqEvento,
901
            $tagAdic
902
        );
903
    }
904
905
    /**
906
     * Requires CE cancellation
907
     * @param  string $chave key of CTe
908
     * @param  string $nProt protocolo do CTe
909
     * @param  string $nProtCE protocolo do CE
910
     * @param  int    $nSeqEvento No. sequencial do evento
911
     * @return string
912
     */
913
    public function sefazCancelaCE($chave, $nProt, $nProtCE, $nSeqEvento)
914
    {
915
        $uf = $this->validKeyByUF($chave);
916
        $tpEvento = 110181;
917
        $tagAdic = "<evCancCECTe>"
918
            . "<descEvento>Cancelamento do Comprovante de Entrega do CT-e</descEvento>"
919
            . "<nProt>$nProt</nProt>"
920
            . "<nProtCE>$nProtCE</nProtCE>"
921
            . "</evCancCECTe>";
922
        return $this->sefazEvento(
923
            $uf,
924
            $chave,
925
            $tpEvento,
926
            $nSeqEvento,
927
            $tagAdic
928
        );
929
    }
930
931
    /**
932
     *
933
     * @param  int $tpEvento
934
     * @return \stdClass
935
     * @throws Exception
936
     */
937
    private function tpEv($tpEvento)
938
    {
939
        $std = new \stdClass();
940
        $std->alias = '';
941
        $std->desc = '';
942
        switch ($tpEvento) {
943
            case 110110:
944
                //CCe
945
                $std->alias = 'CCe';
946
                $std->desc = 'Carta de Correcao';
947
                break;
948
            case 110111:
949
                //cancelamento
950
                $std->alias = 'CancCTe';
951
                $std->desc = 'Cancelamento';
952
                break;
953
            case 110113:
954
                //EPEC
955
                //emissão em contingência EPEC
956
                $std->alias = 'EPEC';
957
                $std->desc = 'EPEC';
958
                break;
959
            case 110180:
960
                //comprovante de entrega
961
                $std->alias = 'evCECTe';
962
                $std->desc = 'Comprovante de Entrega';
963
                break;
964
            case 110181:
965
                //cancelamento do comprovante de entrega
966
                $std->alias = 'evCancCECTe';
967
                $std->desc = 'Cancelamento do Comprovante de Entrega';
968
                break;
969
            case 610110:
970
                //Serviço em desacordo
971
                $std->alias = 'EvPrestDesacordo';
972
                $std->desc = 'Servico em desacordo';
973
                break;
974
            default:
975
                $msg = "O código do tipo de evento informado não corresponde a "
976
                . "nenhum evento estabelecido.";
977
                throw new RuntimeException($msg);
978
        }
979
        return $std;
980
    }
981
982
    private static function serializerCCe(array $infCorrecoes)
983
    {
984
        // Grupo de Informações de Correção
985
        $correcoes = '';
986
        foreach ($infCorrecoes as $info) {
987
            $nroItemAlteradoOptionalElement = '';
988
            if (key_exists('nroItemAlterado', $info)) {
989
                $nroItemAlteradoOptionalElement = "<nroItemAlterado>{$info['nroItemAlterado']}</nroItemAlterado>";
990
            }
991
            $correcoes .= "<infCorrecao>" .
992
                "<grupoAlterado>{$info['grupoAlterado']}</grupoAlterado>" .
993
                "<campoAlterado>{$info['campoAlterado']}</campoAlterado>" .
994
                "<valorAlterado>{$info['valorAlterado']}</valorAlterado>" .
995
                "{$nroItemAlteradoOptionalElement}" .
996
                "</infCorrecao>";
997
        }
998
        //monta mensagem
999
        return "<evCCeCTe>" .
1000
            "<descEvento>Carta de Correcao</descEvento>" .
1001
            "{$correcoes}" .
1002
            "<xCondUso>" .
1003
            "A Carta de Correcao e disciplinada pelo Art. 58-B do " .
1004
            "CONVENIO/SINIEF 06/89: Fica permitida a utilizacao de carta de " .
1005
            "correcao, para regularizacao de erro ocorrido na emissao de " .
1006
            "documentos fiscais relativos a prestacao de servico de transporte, " .
1007
            "desde que o erro nao esteja relacionado com: I - as variaveis que " .
1008
            "determinam o valor do imposto tais como: base de calculo, " .
1009
            "aliquota, diferenca de preco, quantidade, valor da prestacao;II - " .
1010
            "a correcao de dados cadastrais que implique mudanca do emitente, " .
1011
            "tomador, remetente ou do destinatario;III - a data de emissao ou " .
1012
            "de saida." .
1013
            "</xCondUso>" .
1014
        "</evCCeCTe>";
1015
    }
1016
}
1017