Completed
Pull Request — master (#46)
by Antonio Oertel
04:53
created

CurlSoap::setProxy()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 7
ccs 6
cts 6
cp 1
rs 9.4285
cc 1
eloc 5
nc 1
nop 4
crap 1
1
<?php
2
3
namespace NFePHP\Common\Soap;
4
5
/**
6
 * Classe auxiliar para envio das mensagens SOAP usando cURL
7
 * @category   NFePHP
8
 * @package    NFePHP\Common\Soap
9
 * @copyright  Copyright (c) 2008-2015
10
 * @license    http://www.gnu.org/licenses/lesser.html LGPL v3
11
 * @author     Roberto L. Machado <linux dot rlm at gmail dot com>
12
 * @link       http://github.com/nfephp-org/nfephp for the canonical source repository
13
 */
14
15
use NFePHP\Common\Strings\Strings;
16
use NFePHP\Common\Exception;
17
18
class CurlSoap
19
{
20
    /**
21
     * soapDebug
22
     * @var string
23
     */
24
    public $soapDebug = '';
25
    /**
26
     * soapTimeout
27
     * @var integer
28
     */
29
    public $soapTimeout = 10;
30
    /**
31
     * lastMsg
32
     * @var string
33
     */
34
    public $lastMsg = '';
35
36
    /**
37
     * errorCurl
38
     * @var string
39
     */
40
    public $errorCurl = '';
41
    /**
42
     * infoCurl
43
     * @var array
44
     */
45
    public $infoCurl = array();
46
    /**
47
     * pubKeyPath
48
     * @var string
49
     */
50
    private $pubKeyPath = '';
51
    /**
52
     * priKeyPath
53
     * @var string
54
     */
55
    private $priKeyPath = '';
56
    /**
57
     * certKeyPath
58
     * @var string
59
     */
60
    private $certKeyPath = '';
61
    /**
62
     * proxyIP
63
     * @var string
64
     */
65
    private $proxyIP = '';
66
    /**
67
     * proxyPORT
68
     * @var string
69
     */
70
    private $proxyPORT = '';
71
    /**
72
     * proxyUSER
73
     * @var string
74
     */
75
    private $proxyUSER = '';
76
    /**
77
     * proxyPASS
78
     * @var string
79
     */
80
    private $proxyPASS = '';
81
    /**
82
     * sslProtocol
83
     * @var integer
84
     */
85
    private $sslProtocol = 0;
86
    
87
    /**
88
     * __construct
89
     *
90
     * @param string $priKeyPath path para a chave privada
91
     * @param string $pubKeyPath path para a chave publica
92
     * @param string $certKeyPath path para o certificado
93
     * @param string $timeout tempo de espera da resposta do webservice
94
     * @param integer $sslProtocol
95
     */
96 9
    public function __construct($priKeyPath = '', $pubKeyPath = '', $certKeyPath = '', $timeout = 10, $sslProtocol = 0)
97
    {
98 9
        $this->priKeyPath = $priKeyPath;
99 9
        $this->pubKeyPath = $pubKeyPath;
100 9
        $this->certKeyPath = $certKeyPath;
101 9
        $this->soapTimeout = $timeout;
102 9
        if ($sslProtocol < 0 || $sslProtocol > 6) {
103 2
            $msg = "O protocolo SSL pode estar entre 0 e seis, inclusive, mas não além desses números.";
104 2
            throw new Exception\InvalidArgumentException($msg);
105
        }
106 7
        $this->sslProtocol = $sslProtocol;
107 7
        if (! is_file($priKeyPath) || ! is_file($pubKeyPath) || ! is_file($certKeyPath) || ! is_numeric($timeout)) {
108 1
            $msg = "Alguns dos certificados não foram encontrados ou o timeout pode não ser numérico.";
109 1
            throw new Exception\InvalidArgumentException($msg);
110
        }
111 6
    }
112
    
113
    /**
114
     * setProxy
115
     * Seta o uso do proxy
116
     * @param string $ipNumber numero IP do proxy server
117
     * @param string $port numero da porta usada pelo proxy
118
     * @param string $user nome do usuário do proxy
119
     * @param string $pass senha de acesso ao proxy
120
     * @return boolean
121
     */
122 1
    public function setProxy($ipNumber, $port, $user = '', $pass = '')
123
    {
124 1
        $this->proxyIP = $ipNumber;
125 1
        $this->proxyPORT = $port;
126 1
        $this->proxyUSER = $user;
127 1
        $this->proxyPASS = $pass;
128 1
    }//fim setProxy
129
    
130
    /**
131
     * getProxy
132
     * Retorna os dados de configuração do Proxy em um array
133
     * @return array
134
     */
135 1
    public function getProxy()
136
    {
137 1
        $aProxy['ip'] = $this->proxyIP;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$aProxy was never initialized. Although not strictly required by PHP, it is generally a good practice to add $aProxy = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
138 1
        $aProxy['port'] = $this->proxyPORT;
139 1
        $aProxy['username'] = $this->proxyUSER;
140 1
        $aProxy['password'] = $this->proxyPASS;
141 1
        return $aProxy;
142
    }
143
    
144
    /**
145
     * Envia mensagem ao webservice
146
     * @param string $urlsevice
0 ignored issues
show
Documentation introduced by
There is no parameter named $urlsevice. Did you maybe mean $urlservice?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
147
     * @param string $namespace
148
     * @param string $header
149
     * @param string $body
150
     * @param string $method
151
     * @return boolean|string
152
     */
153 3
    public function send($urlservice, $namespace, $header, $body, $method)
0 ignored issues
show
Unused Code introduced by
The parameter $namespace is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
154
    {
155
        //monta a mensagem ao webservice
156 3
        $data = '<?xml version="1.0" encoding="utf-8"?>'.'<soap12:Envelope ';
157 3
        $data .= 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ';
158 3
        $data .= 'xmlns:xsd="http://www.w3.org/2001/XMLSchema" ';
159 3
        $data .= 'xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">';
160 3
        $data .= '<soap12:Header>'.$header.'</soap12:Header>';
161 3
        $data .= '<soap12:Body>'.$body.'</soap12:Body>';
162 3
        $data .= '</soap12:Envelope>';
163 3
        $data = Strings::clearMsg($data);
164 3
        $this->lastMsg = $data;
165
        //tamanho da mensagem
166 3
        $tamanho = strlen($data);
167
        //estabelecimento dos parametros da mensagem
168
        //$parametros = array(
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...
169
        //    'Content-Type: application/soap+xml;charset=utf-8;action="'.$namespace."/".$method.'"',
0 ignored issues
show
Unused Code Comprehensibility introduced by
55% 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...
170
        //    'SOAPAction: "'.$method.'"',
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% 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...
171
        //    "Content-length: $tamanho");
172
        $parametros = array(
173 3
            'Content-Type: application/soap+xml;charset=utf-8',
174 3
            'SOAPAction: "'.$method.'"',
175 3
            "Content-length: $tamanho");
176
        //solicita comunicação via cURL
177 3
        $resposta = $this->zCommCurl($urlservice, $data, $parametros);
178 3
        if (empty($resposta)) {
179 1
            $msg = "Não houve retorno do Curl.\n $this->errorCurl";
180 1
            throw new Exception\RuntimeException($msg);
181
        }
182
        //obtem o bloco html da resposta
183 2
        $xPos = stripos($resposta, "<");
184 2
        $blocoHtml = substr($resposta, 0, $xPos);
185 2
        if ($this->infoCurl["http_code"] != '200') {
186
            //se não é igual a 200 houve erro
187 1
            $msg = $blocoHtml;
188 1
            throw new Exception\RuntimeException($msg);
189
        }
190
        //obtem o tamanho da resposta
191 1
        $lenresp = strlen($resposta);
192
        //localiza a primeira marca de tag
193 1
        $xPos = stripos($resposta, "<");
194
        //se não existir não é um xml nem um html
195 1
        if ($xPos !== false) {
196 1
            $xml = substr($resposta, $xPos, $lenresp-$xPos);
197
        } else {
198
            $xml = '';
199
        }
200
        //testa para saber se é um xml mesmo ou é um html
201 1
        $result = simplexml_load_string($xml, 'SimpleXmlElement', LIBXML_NOERROR+LIBXML_ERR_FATAL+LIBXML_ERR_NONE);
202 1
        if ($result === false) {
203
            //não é um xml então pode limpar
204
            $xml = '';
205
        }
206 1
        if ($xml == '') {
207
            $msg = "Não houve retorno de um xml verifique soapDebug!!";
208
            throw new Exception\RuntimeException($msg);
209
        }
210 1
        if ($xml != '' && substr($xml, 0, 5) != '<?xml') {
211
            $xml = '<?xml version="1.0" encoding="utf-8"?>'.$xml;
212
        }
213 1
        return $xml;
214
    } //fim send
215
216
    /**
217
     * getWsdl
218
     * Baixa o arquivo wsdl do webservice
219
     * @param string $urlsefaz
0 ignored issues
show
Bug introduced by
There is no parameter named $urlsefaz. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
220
     * @return boolean|string
221
     */
222 2
    public function getWsdl($urlservice)
223
    {
224 2
        $aURL = explode('?', $urlservice);
225 2
        if (count($aURL) == 1) {
226 2
            $urlservice .= '?wsdl';
227
        }
228 2
        $resposta = $this->zCommCurl($urlservice);
229
        //verifica se foi retornado o wsdl
230 2
        $nPos = strpos($resposta, '<wsdl:def');
231 2
        if ($nPos === false) {
232 1
            $nPos = strpos($resposta, '<definit');
233
        }
234 2
        if ($nPos === false) {
235
            //não retornou um wsdl
236 1
            return false;
237
        }
238 1
        $wsdl = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".trim(substr($resposta, $nPos));
239 1
        return $wsdl;
240
    }
241
242
    /**
243
     * zCommCurl
244
     * Realiza da comunicação via cURL
245
     * @param string $url
246
     * @param string $data
247
     * @param string $parametros
248
     * @return string
249
     */
250
    protected function zCommCurl($url, $data = '', $parametros = array(), $port = 443)
251
    {
252
        //incializa cURL
253
        $oCurl = curl_init();
254
        //setting da seção soap
255
        if ($this->proxyIP != '') {
256
            curl_setopt($oCurl, CURLOPT_HTTPPROXYTUNNEL, 1);
257
            curl_setopt($oCurl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
258
            curl_setopt($oCurl, CURLOPT_PROXY, $this->proxyIP.':'.$this->proxyPORT);
259
            if ($this->proxyPASS != '') {
260
                curl_setopt($oCurl, CURLOPT_PROXYUSERPWD, $this->proxyUSER.':'.$this->proxyPASS);
261
                curl_setopt($oCurl, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
262
            } //fim if senha proxy
263
        }//fim if aProxy
264
        //força a resolução de nomes com IPV4 e não com IPV6, isso
265
        //pode acelerar temporáriamente as falhas ou demoras decorrentes de
266
        //ambiente mal preparados como os da SEFAZ GO, porém pode causar
267
        //problemas no futuro quando os endereços IPV4 deixarem de ser usados
268
        curl_setopt($oCurl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
269
        curl_setopt($oCurl, CURLOPT_CONNECTTIMEOUT, $this->soapTimeout);
270
        curl_setopt($oCurl, CURLOPT_URL, $url);
271
        curl_setopt($oCurl, CURLOPT_VERBOSE, 1);
272
        curl_setopt($oCurl, CURLOPT_HEADER, 1);
273
        //caso não seja setado o protpcolo SSL o php deverá determinar
274
        //o protocolo correto durante o handshake.
275
        //NOTA : poderão haver alguns problemas no futuro se algum serividor não
276
        //estiver bem configurado e não passar o protocolo correto durante o handshake
277
        //nesse caso será necessário setar manualmente o protocolo correto
278
        //curl_setopt($oCurl, CURLOPT_SSLVERSION, 0); //default
0 ignored issues
show
Unused Code Comprehensibility introduced by
59% 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...
279
        //curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //TLSv1
0 ignored issues
show
Unused Code Comprehensibility introduced by
59% 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...
280
        //curl_setopt($oCurl, CURLOPT_SSLVERSION, 2); //SSLv2
0 ignored issues
show
Unused Code Comprehensibility introduced by
59% 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...
281
        //curl_setopt($oCurl, CURLOPT_SSLVERSION, 3); //SSLv3
0 ignored issues
show
Unused Code Comprehensibility introduced by
59% 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...
282
        //curl_setopt($oCurl, CURLOPT_SSLVERSION, 4); //TLSv1.0
0 ignored issues
show
Unused Code Comprehensibility introduced by
59% 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...
283
        //curl_setopt($oCurl, CURLOPT_SSLVERSION, 5); //TLSv1.1
0 ignored issues
show
Unused Code Comprehensibility introduced by
59% 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...
284
        //curl_setopt($oCurl, CURLOPT_SSLVERSION, 6); //TLSv1.2
0 ignored issues
show
Unused Code Comprehensibility introduced by
59% 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...
285
        //se for passado um padrão diferente de zero (default) como protocolo ssl
286
        //esse novo padrão deverá se usado
287
        if ($this->sslProtocol !== 0) {
288
            curl_setopt($oCurl, CURLOPT_SSLVERSION, $this->sslProtocol);
289
        }
290
        curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, 2);
291
        curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, 0);
292
        if ($port == 443) {
293
            curl_setopt($oCurl, CURLOPT_PORT, 443);
294
            curl_setopt($oCurl, CURLOPT_SSLCERT, $this->certKeyPath);
295
            curl_setopt($oCurl, CURLOPT_SSLKEY, $this->priKeyPath);
296
        } else {
297
            $agent= 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)';
298
            curl_setopt($oCurl, CURLOPT_USERAGENT, $agent);
299
        }
300
        curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1);
301
        if ($data != '') {
302
            curl_setopt($oCurl, CURLOPT_POST, 1);
303
            curl_setopt($oCurl, CURLOPT_POSTFIELDS, $data);
304
        }
305
        if (!empty($parametros)) {
306
            curl_setopt($oCurl, CURLOPT_HTTPHEADER, $parametros);
307
        }
308
        //inicia a conexão
309
        $resposta = curl_exec($oCurl);
310
        //obtem as informações da conexão
311
        $info = curl_getinfo($oCurl);
312
        //carrega os dados para debug
313
        $this->zDebug($info, $data, $resposta);
314
        $this->errorCurl = curl_error($oCurl);
315
        //fecha a conexão
316
        curl_close($oCurl);
317
        //retorna resposta
318
        return $resposta;
319
    }
320
    
321
    /**
322
     * zDebug
323
     * @param array $info
324
     * @param string $data
325
     * @param string $resposta
326
     */
327
    private function zDebug($info = array(), $data = '', $resposta = '')
328
    {
329
        $this->infoCurl["url"] = $info["url"];
330
        $this->infoCurl["content_type"] = $info["content_type"];
331
        $this->infoCurl["http_code"] = $info["http_code"];
332
        $this->infoCurl["header_size"] = $info["header_size"];
333
        $this->infoCurl["request_size"] = $info["request_size"];
334
        $this->infoCurl["filetime"] = $info["filetime"];
335
        $this->infoCurl["ssl_verify_result"] = $info["ssl_verify_result"];
336
        $this->infoCurl["redirect_count"] = $info["redirect_count"];
337
        $this->infoCurl["total_time"] = $info["total_time"];
338
        $this->infoCurl["namelookup_time"] = $info["namelookup_time"];
339
        $this->infoCurl["connect_time"] = $info["connect_time"];
340
        $this->infoCurl["pretransfer_time"] = $info["pretransfer_time"];
341
        $this->infoCurl["size_upload"] = $info["size_upload"];
342
        $this->infoCurl["size_download"] = $info["size_download"];
343
        $this->infoCurl["speed_download"] = $info["speed_download"];
344
        $this->infoCurl["speed_upload"] = $info["speed_upload"];
345
        $this->infoCurl["download_content_length"] = $info["download_content_length"];
346
        $this->infoCurl["upload_content_length"] = $info["upload_content_length"];
347
        $this->infoCurl["starttransfer_time"] = $info["starttransfer_time"];
348
        $this->infoCurl["redirect_time"] = $info["redirect_time"];
349
        //coloca as informações em uma variável
350
        $txtInfo ="";
351
        foreach ($info as $key => $content) {
352
            if (is_string($content)) {
353
                $txtInfo .= strtoupper($key).'='.$content."\n";
354
            }
355
        }
356
        //carrega a variavel debug
357
        $this->soapDebug = $data."\n\n".$txtInfo."\n".$resposta;
358
    }
359
    
360
    /**
361
     * getIBPTProd
362
     * Consulta o serviço do IBPT para obter os impostos ao consumidor
363
     * conforme Lei 12.741/2012
364
     * @param string $cnpj
365
     * @param string $tokenIBPT
366
     * @param string $ncm
367
     * @param string $siglaUF
368
     * @param string $exTarif
369
     * @return array
370
     */
371
    public function getIBPTProd(
372
        $cnpj = '',
373
        $tokenIBPT = '',
374
        $ncm = '',
375
        $siglaUF = '',
376
        $exTarif = '0'
377
    ) {
378
        $url = "http://iws.ibpt.org.br/api/Produtos?token=$tokenIBPT&cnpj=$cnpj&codigo=$ncm&uf=$siglaUF&ex=$exTarif";
379
        $resposta = $this->zCommCurl($url, '', array(), 80);
380
        $retorno = str_replace("\r\n", "|", $resposta);
381
        $aResp = explode("||", $retorno);
382
        if (!empty($aResp[1])) {
383
            if (substr($aResp[1], 0, 1) == '{') {
384
                $json = $aResp[1];
385
                return (array) json_decode($json, true);
386
            }
387
        }
388
        return array();
389
    }
390
}
391