Completed
Push — master ( 87e5e7...0e505d )
by Roberto
02:54
created

BaseTools::setSSLProtocol()   C

Complexity

Conditions 8
Paths 8

Size

Total Lines 28
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 72

Importance

Changes 0
Metric Value
dl 0
loc 28
ccs 0
cts 22
cp 0
rs 5.3846
c 0
b 0
f 0
cc 8
eloc 24
nc 8
nop 1
crap 72
1
<?php
2
namespace NFePHP\CTe;
3
4
/**
5
 * Classe base das classes principais para a comunicação com a SEFAZ
6
 *
7
 * @category   NFePHP
8
 * @package    NFePHP\Common\Base
9
 * @copyright  Copyright (c) 2008-2015
10
 * @license    http://www.gnu.org/licenses/lesser.html LGPL v3
11
 * @author     Roberto L. Machado <linux.rlm at gmail dot com>
12
 * @link       http://github.com/nfephp-org/nfephp for the canonical source repository
13
 *
14
 *        CONTRIBUIDORES (em ordem alfabetica):
15
 *
16
 *          Maison K. Sakamoto <maison.sakamoto at gmail do com>
17
 */
18
19
use NFePHP\Common\Certificate\Pkcs12;
20
use NFePHP\Common\DateTime\DateTime;
21
use NFePHP\Common\Dom\Dom;
22
use NFePHP\Common\Soap\CurlSoap;
23
use NFePHP\Common\Files;
24
use NFePHP\Common\Exception;
25
26
if (!defined('NFEPHP_ROOT')) {
27
    define('NFEPHP_ROOT', dirname(dirname(dirname(__FILE__))));
28
}
29
30
class BaseTools
31
{
32
    /**
33
     * enableSVCRS
34
     * Habilita contingência ao serviço SVC-RS: Sefaz Virtual de Contingência Rio Grande do Sul
35
     * @var boolean
36
     */
37
    public $enableSVCRS = false;
38
    /**
39
     * enableSVCAN
40
     * Habilita contingência ao serviço SVC-AN: Sefaz Virtual de Contingência Ambiente Nacional
41
     * @var boolean
42
     */
43
    public $enableSVCAN = false;
44
    /**
45
     * enableSVCAN
46
     * Habilita contingência ao serviço SVC-AN: Sefaz Virtual de Contingência Ambiente Nacional
47
     * @var boolean
48
     */
49
    public $enableEPEC = false;
50
    /**
51
     * motivoContingencia
52
     * Motivo por ter entrado em Contingencia
53
     * @var string
54
     */
55
    public $motivoContingencia = '';
56
    /**
57
     * tsContingencia
58
     * Timestamp UNIX da data e hora de entrada em contingência
59
     * @var int
60
     */
61
    public $tsContingencia = '';
62
    /**
63
     * verAplic
64
     * Versão da aplicação
65
     * @var string
66
     */
67
    public $verAplic = '';
68
    /**
69
     * certExpireTimestamp
70
     * TimeStamp com a data de vencimento do certificado
71
     * @var double
72
     */
73
    public $certExpireTimestamp = 0;
74
    /**
75
     * ambiente
76
     * @var string
77
     */
78
    public $ambiente = 'homologacao';
79
    /**
80
     * aConfig
81
     * @var array
82
     */
83
    public $aConfig = array();
84
    /**
85
     * sslProtocol
86
     * @var int
87
     */
88
    public $sslProtocol = 0;
89
    /**
90
     * soapTimeout
91
     * @var int
92
     */
93
    public $soapTimeout = 10;
94
    
95
    /**
96
     * oCertificate
97
     * @var Object Class
98
     */
99
    protected $oCertificate;
100
    /**
101
     * oSoap
102
     * @var Object Class
103
     */
104
    protected $oSoap;
105
    /**
106
     * aDocFormat
107
     * @var array
108
     */
109
    protected $aDocFormat = array();
110
    /**
111
     * aProxyConf
112
     * @var array
113
     */
114
    protected $aProxyConf = array();
115
    /**
116
     * aMailConf
117
     * @var array
118
     */
119
    protected $aMailConf = array();
120
    /**
121
     * urlPortal
122
     * Instância do WebService
123
     * @var string
124
     */
125
    protected $urlPortal = '';
126
    /**
127
     * urlcUF
128
     * @var string
129
     */
130
    protected $urlcUF = '';
131
    /**
132
     * urlVersion
133
     * @var string
134
     */
135
    protected $urlVersion = '';
136
    /**
137
     * urlService
138
     * @var string
139
     */
140
    protected $urlService = '';
141
    /**
142
     * urlMethod
143
     * @var string
144
     */
145
    protected $urlMethod = '';
146
    /**
147
     * urlOperation
148
     * @var string
149
     */
150
    protected $urlOperation = 'cte';
151
    /**
152
     * urlNamespace
153
     * @var string
154
     */
155
    protected $urlNamespace = '';
156
    /**
157
     * urlHeader
158
     * @var string
159
     */
160
    protected $urlHeader = '';
161
    /**
162
     * modelo da NFe 55 ou 65
163
     * @var string
164
     */
165
    protected $modelo = '55';
166
    
167
    /**
168
     * cUFlist
169
     * @var array
170
     */
171
    protected $cUFlist = array(
172
        'AC'=>'12',
173
        'AL'=>'27',
174
        'AM'=>'13',
175
        'AN'=>'91',
176
        'AP'=>'16',
177
        'BA'=>'29',
178
        'CE'=>'23',
179
        'DF'=>'53',
180
        'ES'=>'32',
181
        'GO'=>'52',
182
        'MA'=>'21',
183
        'MG'=>'31',
184
        'MS'=>'50',
185
        'MT'=>'51',
186
        'PA'=>'15',
187
        'PB'=>'25',
188
        'PE'=>'26',
189
        'PI'=>'22',
190
        'PR'=>'41',
191
        'RJ'=>'33',
192
        'RN'=>'24',
193
        'RO'=>'11',
194
        'RR'=>'14',
195
        'RS'=>'43',
196
        'SC'=>'42',
197
        'SE'=>'28',
198
        'SP'=>'35',
199
        'TO'=>'17',
200
        'SVAN' => '91'
201
    );
202
    
203
    /**
204
     * __construct
205
     * @param string $configJson
206
     * @throws Exception\InvalidArgumentException
207
     * @throws Exception\RuntimeException
208
     */
209
    public function __construct($configJson = '')
210
    {
211
        if ($configJson == '') {
212
            $msg = 'O arquivo de configuração no formato JSON deve ser passado para a classe.';
213
            throw new Exception\InvalidArgumentException($msg);
214
        }
215
        if (is_file($configJson)) {
216
            $configJson = Files\FilesFolders::readFile($configJson);
217
        }
218
        //carrega os dados de configuração
219
        $this->aConfig    = (array) json_decode($configJson);
220
        if (key_exists('aDocFormat', $this->aConfig)) {
221
            $this->aDocFormat = (array) $this->aConfig['aDocFormat'];
222
        }
223
        if (key_exists('aProxyConf', $this->aConfig)) {
224
            $this->aProxyConf = (array) $this->aConfig['aProxyConf'];
225
        }
226
        if (key_exists('aMailConf', $this->aConfig)) {
227
            $this->aMailConf  = (array) $this->aConfig['aMailConf'];
228
        }
229
        
230
        //seta o timezone
231
        DateTime::tzdBR($this->aConfig['siglaUF']);
232
        //carrega os certificados
233
        $this->oCertificate = new Pkcs12(
234
            $this->aConfig['pathCertsFiles'],
235
            $this->aConfig['cnpj']
236
        );
237
        if ($this->oCertificate->priKey == '') {
238
            //tentar carregar novo certificado
239
            $this->atualizaCertificado(
240
                $this->aConfig['pathCertsFiles'].$this->aConfig['certPfxName'],
241
                $this->aConfig['certPassword']
242
            );
243
            if ($this->oCertificate->expireTimestamp == 0) {
244
                $msg = 'Não existe certificado válido disponível. Atualize o Certificado.';
245
                throw new Exception\RuntimeException($msg);
246
            }
247
        }
248
        $this->setAmbiente($this->aConfig['tpAmb']);
249
        $this->certExpireTimestamp = $this->oCertificate->expireTimestamp;
250
        $this->zLoadSoapClass();
251
        //verifica se a contingência está ativada
252
        $pathContingencia = NFEPHP_ROOT.DIRECTORY_SEPARATOR.'config'.
253
            DIRECTORY_SEPARATOR.$this->aConfig['cnpj'].'_contingencia.json';
254
        if (is_file($pathContingencia)) {
255
            $contJson = Files\FilesFolders::readFile($pathContingencia);
256
            if (! empty($contJson)) {
257
                 $aCont = (array) json_decode($contJson);
258
                 $this->motivoContingencia = $aCont['motivo'];
259
                 $this->tsContingencia = $aCont['ts'];
260
                 $this->enableSVCAN = $aCont['SVCAN'];
261
                 $this->enableSVCRS = $aCont['SVCRS'];
262
            }
263
        }
264
    }
265
    
266
    /**
267
     * setSSLProtocol
268
     * Força o uso de um determinado protocolo de encriptação
269
     * na comunicação https com a SEFAZ usando cURL
270
     * Apenas é necessário quando a versão do PHP e do libssl não
271
     * consegue estabelecer o protocolo correto durante o handshake
272
     * @param string $protocol
273
     */
274
    public function setSSLProtocol($protocol = '')
275
    {
276
        if (! empty($protocol)) {
277
            switch ($protocol) {
278
                case 'TLSv1':
279
                    $this->sslProtocol = 1;
280
                    break;
281
                case 'SSLv2':
282
                    $this->sslProtocol = 2;
283
                    break;
284
                case 'SSLv3':
285
                    $this->sslProtocol = 3;
286
                    break;
287
                case 'TLSv1.0':
288
                    $this->sslProtocol = 4;
289
                    break;
290
                case 'TLSv1.1':
291
                    $this->sslProtocol = 5;
292
                    break;
293
                case 'TLSv1.2':
294
                    $this->sslProtocol = 6;
295
                    break;
296
                default:
297
                    $this->sslProtocol = 0;
298
            }
299
            $this->zLoadSoapClass();
300
        }
301
    }
302
    
303
    /**
304
     * getSSLProtocol
305
     * Retrona o protocolo que está setado
306
     * @return string
307
     */
308
    public function getSSLProtocol()
309
    {
310
        $aPr = array('default','TLSv1','SSLv2','SSLv3','TLSv1.0','TLSv1.1','TLSv1.2');
311
        return $aPr[$this->sslProtocol];
312
    }
313
    
314
    /**
315
     * setSoapTimeOut
316
     * @param integer $segundos
317
     */
318
    public function setSoapTimeOut($segundos = 10)
319
    {
320
        if (! empty($segundos)) {
321
            $this->soapTimeout = $segundos;
322
            $this->zLoadSoapClass();
323
        }
324
    }
325
    
326
    /**
327
     * getSoapTimeOut
328
     * @return integer
329
     */
330
    public function getSoapTimeOut()
331
    {
332
        return $this->soapTimeout;
333
    }
334
    
335
    /**
336
     * setAmbiente
337
     * Seta a varável de ambiente
338
     * @param string $tpAmb
339
     */
340
    protected function setAmbiente($tpAmb = '2')
341
    {
342
        $this->ambiente = 'homologacao';
343
        if ($tpAmb == '1') {
344
            $this->ambiente = 'producao';
345
        }
346
    }
347
    
348
    /**
349
     * atualizaCertificado
350
     * @param string $certpfx certificado pfx em string ou o path para o certificado
351
     * @param string $senha senha para abrir o certificado
352
     * @return boolean
353
     */
354
    public function atualizaCertificado($certpfx = '', $senha = '')
355
    {
356
        if ($certpfx == '' && $senha != '') {
357
            return false;
358
        }
359
        if (is_file($certpfx)) {
360
            $this->oCertificate->loadPfxFile($certpfx, $senha);
361
            return true;
362
        }
363
        $this->oCertificate->loadPfx($certpfx, $senha);
364
        $this->zLoadSoapClass();
365
        return true;
366
    }
367
    
368
    /**
369
     * assinaDoc
370
     * @param string $xml
371
     * @param string $tipo nfe, cte, ou mdfe
372
     * @param string $tag Nome da tag a ser assinada
373
     * @param boolean $saveFile APENAS para salvar NFe, CTe ou MDFe
374
     * @return string
375
     * @throws Exception\InvalidArgumentException
376
     * @throws Exception\RuntimeException
377
     */
378
    public function assinaDoc($xml = '', $tipo = '', $tag = '', $saveFile = false)
379
    {
380
        if ($tag == '') {
381
            $msg = 'Deve ser indicada uma tag a ser assinada';
382
            throw new Exception\InvalidArgumentException($msg);
383
        }
384
        if (is_file($xml)) {
385
            $xml = Files\FilesFolders::readFile($xml);
386
        }
387
        $sxml = $this->oCertificate->signXML($xml, $tag);
388
        $dom = new Dom();
389
        $dom->loadXMLString($sxml);
390
        //$versao = $dom->getElementsByTagName($tag)->item(0)->getAttribute('versao');
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
391
        //if (! $this->zValidMessage($sxml, $tipo, $versao)) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
70% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
392
        //$msg = "Falha na validação do $tipo. ".$this->error;
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
393
        //  throw new Exception\RuntimeException($msg);
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
394
        //}
395
        if ($saveFile && $tipo != '') {
396
            $dom = new Dom();
397
            $dom->loadXMLString($sxml);
398
            $tpAmb = $dom->getElementsByTagName('tpAmb')->item(0)->nodeValue;
399
            $anomes = date(
400
                'Ym',
401
                DateTime::convertSefazTimeToTimestamp($dom->getElementsByTagName('dhEmi')->item(0)->nodeValue)
402
            );
403
            $chave = $dom->getChave($tag);
404
            $filename = "$chave-$tipo.xml";
405
            $this->zGravaFile($tipo, $tpAmb, $filename, $sxml, 'assinadas', $anomes);
406
        }
407
        return $sxml;
408
    }
409
    
410
    /**
411
     * setVerAplic
412
     * @param string $versao
413
     */
414
    public function setVerAplic($versao = '')
415
    {
416
        $this->verAplic = $versao;
417
    }
418
419
    /**
420
     * Carrega a classe SOAP e os certificados
421
     */
422
    protected function zLoadSoapClass()
423
    {
424
        $this->oSoap = null;
425
        $this->oSoap = new CurlSoap(
426
            $this->oCertificate->priKeyFile,
427
            $this->oCertificate->pubKeyFile,
428
            $this->oCertificate->certKeyFile,
429
            $this->soapTimeout,
430
            $this->sslProtocol
431
        );
432
    }
433
    
434
    /**
435
     * zLoadServico
436
     * Monta o namespace e o cabecalho da comunicação SOAP
437
     * @param string $service
438
     * @param string $siglaUF
439
     * @param string $tpAmb
440
     * @param string $tipo
441
     * @return bool
442
     * @internal param string $servico Identificação do Servico
443
     * @internal param array $aURL Dados das Urls do SEFAZ
444
     */
445
    protected function zLoadServico(
446
        $tipo,
447
        $service,
448
        $siglaUF,
449
        $tpAmb
450
    ) {
451
        if (empty($tipo) || empty($service) || empty($siglaUF)) {
452
            $this->urlVersion = '';
453
            $this->urlService = '';
454
            $this->urlMethod = '';
455
            $this->urlOperation = '';
456
            $this->urlNamespace = '';
457
            $this->urlHeader = '';
458
            return false;
459
        }
460
        $this->urlcUF = $this->getcUF($siglaUF);
461
        $pathXmlUrlFile = $this->zGetXmlUrlPath($tipo);
462
        
463
        if ($this->enableSVCAN) {
464
            $aURL = self::zLoadSEFAZ($pathXmlUrlFile, $tpAmb, 'SVCAN');
465
        } elseif ($this->enableSVCRS) {
466
            $aURL = self::zLoadSEFAZ($pathXmlUrlFile, $tpAmb, 'SVCRS');
467
        } else {
468
            $aURL = self::zLoadSEFAZ($pathXmlUrlFile, $tpAmb, $siglaUF, $tipo);
469
        }
470
        //recuperação da versão
471
        $this->urlVersion = $aURL[$service]['version'];
472
        //recuperação da url do serviço
473
        $this->urlService = $aURL[$service]['URL'];
474
        //recuperação do método
475
        $this->urlMethod = $aURL[$service]['method'];
476
        //montagem do namespace do serviço
477
        $this->urlOperation = $aURL[$service]['operation'];
478
        //montagem do namespace do serviço
479
        $this->urlNamespace = sprintf("%s/wsdl/%s", $this->urlPortal, $this->urlOperation);
480
        
481
        //montagem do cabeçalho da comunicação SOAP
482
        $this->urlHeader = $this->zMountHeader($tipo, $this->urlNamespace, $this->urlcUF, $this->urlVersion);
483
       
484
        return true;
485
    }
486
    
487
    /**
488
     * zGetXmlUrlPath
489
     * @param string $tipo
490
     * @return string
491
     */
492
    private function zGetXmlUrlPath($tipo)
493
    {
494
        $path = '';
495
        if ($tipo == 'nfe') {
496
            $path = $this->aConfig['pathXmlUrlFileNFe'];
497
            if ($this->modelo == '65') {
498
                $path = str_replace('55', '65', $path);
499
            } else {
500
                $path = str_replace('65', '55', $path);
501
            }
502
        } elseif ($tipo == 'cte') {
503
            $path = $this->aConfig['pathXmlUrlFileCTe'];
504
        } elseif ($tipo == 'mdfe') {
505
            $path = $this->aConfig['pathXmlUrlFileMDFe'];
506
        } elseif ($tipo == 'cle') {
507
            $path = $this->aConfig['pathXmlUrlFileCLe'];
508
        }
509
        
510
        $pathXmlUrlFile = NFEPHP_ROOT
511
            . DIRECTORY_SEPARATOR
512
            . 'config'
513
            . DIRECTORY_SEPARATOR
514
            . $path;
515
        
516
        return $pathXmlUrlFile;
517
    }
518
    
519
    /**
520
     * zMountHeader
521
     * @param string $tipo
522
     * @param string $namespace
523
     * @param string $cUF
524
     * @param string $version
525
     * @return string
526
     */
527
    private function zMountHeader($tipo, $namespace, $cUF, $version)
528
    {
529
        $header = '';
530
        if ($tipo == 'nfe') {
531
            $header = "<nfeCabecMsg "
532
                . "xmlns=\"$namespace\">"
533
                . "<cUF>$cUF</cUF>"
534
                . "<versaoDados>$version</versaoDados>"
535
                . "</nfeCabecMsg>";
536
        } elseif ($tipo == 'cte') {
537
            $header = "<cteCabecMsg "
538
                . "xmlns=\"$namespace\">"
539
                . "<cUF>$cUF</cUF>"
540
                . "<versaoDados>$version</versaoDados>"
541
                . "</cteCabecMsg>";
542
        } elseif ($tipo == 'mdfe') {
543
            $header = "<mdfeCabecMsg "
544
                . "xmlns=\"$namespace\">"
545
                . "<cUF>$cUF</cUF>"
546
                . "<versaoDados>$version</versaoDados>"
547
                . "</mdfeCabecMsg>";
548
        }
549
        return $header;
550
    }
551
    
552
    /**
553
     * zLoadSEFAZ
554
     * Extrai o URL, nome do serviço e versão dos webservices das SEFAZ de
555
     * todos os Estados da Federação, a partir do arquivo XML de configurações,
556
     * onde este é estruturado para os modelos 55 (NF-e) e 65 (NFC-e) já que
557
     * os endereços dos webservices podem ser diferentes.
558
     * @param string $pathXmlUrlFile
559
     * @param  string $tpAmb Pode ser "2-homologacao" ou "1-producao"
560
     * @param string $siglaUF
561
     * @param strign $tipo nfe, mdfe ou cte
562
     * @return mixed false se houve erro ou array com os dados dos URLs da SEFAZ
563
     * @internal param string $sUF Sigla da Unidade da Federação (ex. SP, RS, SVRS, etc..)
564
     * @see /config/nfe_ws3_modXX.xml
565
     */
566
    protected function zLoadSEFAZ($pathXmlUrlFile = '', $tpAmb = '2', $siglaUF = 'SP', $tipo = 'nfe')
567
    {
568
        //verifica se o arquivo xml pode ser encontrado no caminho indicado
569
        if (! file_exists($pathXmlUrlFile)) {
570
            throw new Exception\RuntimeException(
571
                "Arquivo $pathXmlUrlFile não encontrado."
572
            );
573
        }
574
        //carrega o xml
575
        if (!$xmlWS = simplexml_load_file($pathXmlUrlFile)) {
576
            throw new Exception\RuntimeException(
577
                "Arquivo $pathXmlUrlFile parece ser invalido ou está corrompido."
578
            );
579
        }
580
        $autorizadores = array();
581
        $autorizadores['65'] = array(
582
            'AC'=>'SVRS',
583
            'AL'=>'SVRS',
584
            'AM'=>'AM',
585
            'AN'=>'AN',
586
            'AP'=>'SVRS',
587
            'BA'=>'SVRS',
588
            'CE'=>'CE',
589
            'DF'=>'SVRS',
590
            'ES'=>'SVRS',
591
            'GO'=>'SVRS',
592
            'MA'=>'SVRS',
593
            'MG'=>'MG',
594
            'MS'=>'MS',
595
            'MT'=>'MT',
596
            'PA'=>'SVRS',
597
            'PB'=>'SVRS',
598
            'PE'=>'PE',
599
            'PI'=>'SVRS',
600
            'PR'=>'PR',
601
            'RJ'=>'SVRS',
602
            'RN'=>'SVRS',
603
            'RO'=>'SVRS',
604
            'RR'=>'SVRS',
605
            'RS'=>'RS',
606
            'SC'=>'SVRS',
607
            'SE'=>'SVRS',
608
            'SP'=>'SP',
609
            'TO'=>'SVRS',
610
            'SVAN'=>'SVAN',
611
            'SVRS'=>'SVRS',
612
            'SVCAN'=>'SVCAN',
613
        );
614
        
615
        $autorizadores['55'] = array(
616
            'AC'=>'SVRS',
617
            'AL'=>'SVRS',
618
            'AM'=>'AM',
619
            'AN'=>'AN',
620
            'AP'=>'SVRS',
621
            'BA'=>'BA',
622
            'CE'=>'CE',
623
            'DF'=>'SVRS',
624
            'ES'=>'SVRS',
625
            'GO'=>'GO',
626
            'MA'=>'SVAN',
627
            'MG'=>'MG',
628
            'MS'=>'MS',
629
            'MT'=>'MT',
630
            'PA'=>'SVAN',
631
            'PB'=>'SVRS',
632
            'PE'=>'PE',
633
            'PI'=>'SVAN',
634
            'PR'=>'PR',
635
            'RJ'=>'SVRS',
636
            'RN'=>'SVRS',
637
            'RO'=>'SVRS',
638
            'RR'=>'SVRS',
639
            'RS'=>'RS',
640
            'SC'=>'SVRS',
641
            'SE'=>'SVRS',
642
            'SP'=>'SP',
643
            'TO'=>'SVRS',
644
            'SVAN'=>'SVAN',
645
            'SVRS'=>'SVRS',
646
            'SVCAN'=>'SVCAN',
647
            'SVCRS'=>'SVCRS'
648
        );
649
        
650
        //Estados que utilizam a SVSP - Sefaz Virtual de São Paulo: AP, PE, RR
651
        //Estados que utilizam a SVRS - Sefaz Virtual do RS:
652
        //AC, AL, AM, BA, CE, DF, ES, GO, MA,
653
        //PA, PB, PI, RJ, RN, RO, SC, SE, TO
654
        //Autorizadores: MT - MS - MG - PR - RS - SP - SVRS - SVSP
655
        $autorizadores['57'] = array(
656
            'AC'=>'SVRS',
657
            'AL'=>'SVRS',
658
            'AM'=>'SVRS',
659
            'AN'=>'AN',
660
            'AP'=>'SVSP',
661
            'BA'=>'SVRS',
662
            'CE'=>'SVRS',
663
            'DF'=>'SVRS',
664
            'ES'=>'SVRS',
665
            'GO'=>'SVRS',
666
            'MA'=>'SVRS',
667
            'MG'=>'MG',
668
            'MS'=>'MS',
669
            'MT'=>'MT',
670
            'PA'=>'SVSP',
671
            'PB'=>'SVRS',
672
            'PE'=>'PE',
673
            'PI'=>'SVRS',
674
            'PR'=>'PR',
675
            'RJ'=>'SVRS',
676
            'RN'=>'SVRS',
677
            'RO'=>'SVRS',
678
            'RR'=>'SVSP',
679
            'RS'=>'RS',
680
            'SC'=>'SVRS',
681
            'SE'=>'SVRS',
682
            'SP'=>'SP',
683
            'TO'=>'SVRS',
684
            'SVAN'=>'SVAN',
685
            'SVRS'=>'SVRS',
686
            'SVCAN'=>'SVCAN',
687
        );
688
        //variável de retorno do método
689
        $aUrl = array();
690
        //testa parametro tpAmb
691
        $sAmbiente = 'homologacao';
692
        if ($tpAmb == '1') {
693
            $sAmbiente = 'producao';
694
        }
695
        $alias = $autorizadores[$this->modelo][$siglaUF];
696
        if ($tipo == 'mdfe') {
697
            $alias = 'RS';
698
        }
699
        //estabelece a expressão xpath de busca
700
        $xpathExpression = "/WS/UF[sigla='$alias']/$sAmbiente";
701
        $aUrl = $this->zExtractUrl($xmlWS, $aUrl, $xpathExpression);
702
        //verifica se existem outros serviços exclusivos para esse estado
703
        if ($alias == 'SVAN' || $alias == 'SVRS') {
704
            $xpathExpression = "/WS/UF[sigla='$siglaUF']/$sAmbiente";
705
            $aUrl = $this->zExtractUrl($xmlWS, $aUrl, $xpathExpression);
706
        }
707
        return $aUrl;
708
    }
709
    
710
    /**
711
     * zExtractUrl
712
     * @param \SimpleXMLElement $xmlWS
713
     * @param array $aUrl
714
     * @param string $expression
715
     * @return array
716
     */
717
    protected function zExtractUrl($xmlWS, $aUrl = array(), $expression = '')
718
    {
719
        //para cada "nó" no xml que atenda aos critérios estabelecidos
720
        foreach ($xmlWS->xpath($expression) as $gUF) {
721
            //para cada "nó filho" retonado
722
            foreach ($gUF->children() as $child) {
723
                $u = (string) $child[0];
724
                $aUrl[$child->getName()]['URL'] = $u;
725
                // em cada um desses nós pode haver atributos como a identificação
726
                // do nome do webservice e a sua versão
727
                foreach ($child->attributes() as $a => $b) {
728
                    $aUrl[$child->getName()][$a] = (string) $b;
729
                }
730
            }
731
        }
732
        return $aUrl;
733
    }
734
    
735
    /**
736
     * zGravaFile
737
     * Grava os dados no diretorio das NFe
738
     * @param string $tpAmb ambiente
739
     * @param string $filename nome do arquivo
740
     * @param string $data dados a serem salvos
741
     * @param string $subFolder
742
     * @param string $anomes
743
     * @throws Exception\RuntimeException
744
     */
745
    protected function zGravaFile(
746
        $tipo = '',
747
        $tpAmb = '2',
748
        $filename = '',
749
        $data = '',
750
        $subFolder = 'temporarias',
751
        $anomes = ''
752
    ) {
753
        if ($anomes == '') {
754
            $anomes = date('Ym');
755
        }
756
        $path = '';
757
        if ($tipo == 'nfe') {
758
            $path = $this->aConfig['pathNFeFiles'];
759
        } elseif ($tipo == 'cte') {
760
            $path = $this->aConfig['pathCTeFiles'];
761
        } elseif ($tipo == 'mdfe') {
762
            $path = $this->aConfig['pathMDFeFiles'];
763
        }
764
        $pathTemp = Files\FilesFolders::getFilePath($tpAmb, $path, $subFolder)
765
            . DIRECTORY_SEPARATOR.$anomes;
766
        if (! Files\FilesFolders::saveFile($pathTemp, $filename, $data)) {
767
            $msg = 'Falha na gravação no diretório. '.$pathTemp;
768
            throw new Exception\RuntimeException($msg);
769
        }
770
    }
771
772
    /**
773
     * getcUF
774
     * @param string $siglaUF
775
     * @return string numero cUF
776
     */
777
    public function getcUF($siglaUF = '')
778
    {
779
        return $this->cUFlist[$siglaUF];
780
    }
781
    
782
    /**
783
     * zGetSigla
784
     * @param string $cUF
785
     * @return string
786
     */
787
    protected function zGetSigla($cUF = '')
788
    {
789
        return array_search($cUF, $this->cUFlist);
790
    }
791
}
792