|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace NFePHP\Common\Soap; |
|
4
|
|
|
|
|
5
|
|
|
/** |
|
6
|
|
|
* SoapClient based in cURL class |
|
7
|
|
|
* |
|
8
|
|
|
* @category NFePHP |
|
9
|
|
|
* @package NFePHP\Common\Soap\SoapCurl |
|
10
|
|
|
* @copyright NFePHP Copyright (c) 2016 |
|
11
|
|
|
* @license http://www.gnu.org/licenses/lgpl.txt LGPLv3+ |
|
12
|
|
|
* @license https://opensource.org/licenses/MIT MIT |
|
13
|
|
|
* @license http://www.gnu.org/licenses/gpl.txt GPLv3+ |
|
14
|
|
|
* @author Roberto L. Machado <linux.rlm at gmail dot com> |
|
15
|
|
|
* @link http://github.com/nfephp-org/sped-common for the canonical source repository |
|
16
|
|
|
*/ |
|
17
|
|
|
|
|
18
|
|
|
use NFePHP\Common\Soap\SoapBase; |
|
19
|
|
|
use NFePHP\Common\Soap\SoapInterface; |
|
20
|
|
|
use NFePHP\Common\Soap\SoapData; |
|
21
|
|
|
use NFePHP\Common\Exception\SoapException; |
|
22
|
|
|
use NFePHP\Common\Certificate; |
|
23
|
|
|
use Psr\Log\LoggerInterface; |
|
24
|
|
|
|
|
25
|
|
|
class SoapCurl extends SoapBase implements SoapInterface |
|
26
|
|
|
{ |
|
27
|
|
|
/** |
|
28
|
|
|
* Constructor |
|
29
|
|
|
* @param Certificate $certificate |
|
30
|
|
|
* @param LoggerInterface $logger |
|
31
|
|
|
*/ |
|
32
|
|
|
public function __construct(Certificate $certificate = null, LoggerInterface $logger = null) |
|
33
|
|
|
{ |
|
34
|
|
|
parent::__construct($certificate, $logger); |
|
35
|
|
|
} |
|
36
|
|
|
|
|
37
|
|
|
/** |
|
38
|
|
|
* Send soap message to url |
|
39
|
|
|
* @param string $url |
|
40
|
|
|
* @param string $operation |
|
41
|
|
|
* @param string $action |
|
42
|
|
|
* @param int $soapver |
|
43
|
|
|
* @param array $parameters |
|
44
|
|
|
* @param array $namespaces |
|
45
|
|
|
* @param string $request |
|
46
|
|
|
* @param \SoapHeader $soapheader |
|
47
|
|
|
* @return string |
|
48
|
|
|
* @throws \NFePHP\Common\Exception\SoapException |
|
49
|
|
|
*/ |
|
50
|
|
|
public function send( |
|
51
|
|
|
$url, |
|
52
|
|
|
$operation = '', |
|
53
|
|
|
$action = '', |
|
54
|
|
|
$soapver = SOAP_1_2, |
|
55
|
|
|
$parameters = [], |
|
56
|
|
|
$namespaces = [], |
|
57
|
|
|
$request = '', |
|
58
|
|
|
$soapheader = null |
|
59
|
|
|
) { |
|
60
|
|
|
$data = new SoapData(); |
|
61
|
|
|
$data->urlService = $url; |
|
62
|
|
|
$data->urlAction = $action; |
|
63
|
|
|
$data->soapNamespaces = $namespaces; |
|
64
|
|
|
$data->envelopedData = $this->makeEnvelopeSoap($request, $namespaces, $soapver, $soapheader); |
|
65
|
|
|
$data->contentType = 'application/soap+xml'; |
|
66
|
|
|
|
|
67
|
|
|
return $this->send2($data); |
|
68
|
|
|
} |
|
69
|
|
|
|
|
70
|
|
|
public function send2(SoapData $data): string { |
|
71
|
|
|
$parameters = self::buildParameters($data); |
|
72
|
|
|
$this->requestHead = implode('\n', $parameters); |
|
73
|
|
|
$this->requestBody = $data->envelopedData; |
|
74
|
|
|
|
|
75
|
|
|
$url = $data->urlService; |
|
76
|
|
|
|
|
77
|
|
|
$httpcode = 0; |
|
78
|
|
|
try { |
|
79
|
|
|
$curl = $this->create_curl($url, $data->envelopedData, $parameters); |
|
80
|
|
|
|
|
81
|
|
|
$response = curl_exec($curl); |
|
82
|
|
|
|
|
83
|
|
|
$httpcode = $this->dispose_curl($curl, $response, $data->urlMethod); |
|
84
|
|
|
} |
|
85
|
|
|
catch(\Exception $e) { |
|
86
|
|
|
throw SoapException::unableToLoadCurl($e->getMessage()); |
|
87
|
|
|
} |
|
88
|
|
|
|
|
89
|
|
|
if ($this->soaperror != '') |
|
90
|
|
|
throw SoapException::soapFault($this->soaperror . " [$url]"); |
|
91
|
|
|
|
|
92
|
|
|
if ($httpcode != 200) |
|
93
|
|
|
throw SoapException::soapFault(" [$url]" . $this->responseHead); |
|
94
|
|
|
|
|
95
|
|
|
return $this->responseBody; |
|
96
|
|
|
} |
|
97
|
|
|
|
|
98
|
|
|
private static function buildParameters(SoapData $data): array { |
|
99
|
|
|
$msgSize = strlen($data->envelopedData); |
|
100
|
|
|
$parameters = array( |
|
101
|
|
|
"Content-Type: $data->contentType;charset=\"utf-8\"", |
|
102
|
|
|
"Content-Length: $msgSize", |
|
103
|
|
|
); |
|
104
|
|
|
if (!empty($data->urlMethod)) { |
|
105
|
|
|
$parameters[0] .= ";action=\"$data->urlMethod\""; |
|
106
|
|
|
} |
|
107
|
|
|
if (!empty($data->urlAction)) { |
|
108
|
|
|
$parameters[] = "SOAPAction: $data->urlAction"; |
|
109
|
|
|
} |
|
110
|
|
|
return $parameters; |
|
111
|
|
|
} |
|
112
|
|
|
|
|
113
|
|
|
/** |
|
114
|
|
|
* Set proxy into cURL parameters |
|
115
|
|
|
* @param resource $oCurl |
|
116
|
|
|
*/ |
|
117
|
|
|
private function setCurlProxy(&$oCurl) |
|
118
|
|
|
{ |
|
119
|
|
|
if ($this->proxyIP != '') { |
|
120
|
|
|
curl_setopt($oCurl, CURLOPT_HTTPPROXYTUNNEL, 1); |
|
121
|
|
|
curl_setopt($oCurl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); |
|
122
|
|
|
curl_setopt($oCurl, CURLOPT_PROXY, $this->proxyIP . ':' . $this->proxyPort); |
|
123
|
|
|
if ($this->proxyUser != '') { |
|
124
|
|
|
curl_setopt($oCurl, CURLOPT_PROXYUSERPWD, $this->proxyUser . ':' . $this->proxyPass); |
|
125
|
|
|
curl_setopt($oCurl, CURLOPT_PROXYAUTH, CURLAUTH_BASIC); |
|
126
|
|
|
} |
|
127
|
|
|
} |
|
128
|
|
|
} |
|
129
|
|
|
|
|
130
|
|
|
private function create_curl($url, $envelope, $parameters) |
|
131
|
|
|
{ |
|
132
|
|
|
$oCurl = curl_init(); |
|
133
|
|
|
$this->setCurlProxy($oCurl); |
|
134
|
|
|
curl_setopt($oCurl, CURLOPT_URL, $url); |
|
135
|
|
|
curl_setopt($oCurl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); |
|
136
|
|
|
curl_setopt($oCurl, CURLOPT_CONNECTTIMEOUT, $this->soaptimeout); |
|
137
|
|
|
curl_setopt($oCurl, CURLOPT_TIMEOUT, $this->soaptimeout + 30); |
|
138
|
|
|
curl_setopt($oCurl, CURLOPT_HEADER, 1); |
|
139
|
|
|
curl_setopt($oCurl, CURLOPT_VERBOSE, 1); |
|
140
|
|
|
// curl_setopt($oCurl, CURLOPT_FAILONERROR, 1); |
|
|
|
|
|
|
141
|
|
|
curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, 0); |
|
142
|
|
|
curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, 0); |
|
143
|
|
|
|
|
144
|
|
|
if (!$this->disablesec) { |
|
145
|
|
|
curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, 2); |
|
146
|
|
|
if (is_file($this->casefaz)) { |
|
147
|
|
|
curl_setopt($oCurl, CURLOPT_CAINFO, $this->casefaz); //must have already called function loadCA at this point. |
|
148
|
|
|
} |
|
149
|
|
|
} |
|
150
|
|
|
|
|
151
|
|
|
curl_setopt($oCurl, CURLOPT_SSLVERSION, $this->soapprotocol); |
|
152
|
|
|
curl_setopt($oCurl, CURLOPT_SSLCERT, $this->tempdir . $this->certfile); |
|
153
|
|
|
curl_setopt($oCurl, CURLOPT_SSLKEY, $this->tempdir . $this->prifile); |
|
154
|
|
|
|
|
155
|
|
|
if (!empty($this->temppass)) { |
|
156
|
|
|
curl_setopt($oCurl, CURLOPT_KEYPASSWD, $this->temppass); |
|
157
|
|
|
} |
|
158
|
|
|
|
|
159
|
|
|
curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1); |
|
160
|
|
|
|
|
161
|
|
|
if (!empty($envelope)) { |
|
162
|
|
|
curl_setopt($oCurl, CURLOPT_POST, 1); |
|
163
|
|
|
curl_setopt($oCurl, CURLOPT_POSTFIELDS, $envelope); |
|
164
|
|
|
curl_setopt($oCurl, CURLOPT_HTTPHEADER, $parameters); |
|
165
|
|
|
} |
|
166
|
|
|
|
|
167
|
|
|
return $oCurl; |
|
168
|
|
|
} |
|
169
|
|
|
|
|
170
|
|
|
private function dispose_curl($oCurl, $response, $operation = '') |
|
171
|
|
|
{ |
|
172
|
|
|
$this->soaperror = curl_error($oCurl); |
|
173
|
|
|
$ainfo = curl_getinfo($oCurl); |
|
174
|
|
|
|
|
175
|
|
|
if (is_array($ainfo)) { |
|
176
|
|
|
$this->soapinfo = $ainfo; |
|
177
|
|
|
} |
|
178
|
|
|
|
|
179
|
|
|
$headsize = curl_getinfo($oCurl, CURLINFO_HEADER_SIZE); |
|
180
|
|
|
$httpcode = curl_getinfo($oCurl, CURLINFO_HTTP_CODE); |
|
181
|
|
|
curl_close($oCurl); |
|
182
|
|
|
|
|
183
|
|
|
if ($response) { |
|
184
|
|
|
$this->responseHead = trim(substr($response, 0, $headsize)); |
|
185
|
|
|
$this->responseBody = trim(substr($response, $headsize)); |
|
186
|
|
|
} |
|
187
|
|
|
|
|
188
|
|
|
$this->saveDebugFiles( |
|
189
|
|
|
$operation, |
|
190
|
|
|
$this->requestHead . "\n" . $this->requestBody, |
|
191
|
|
|
$this->responseHead . "\n" . $this->responseBody |
|
192
|
|
|
); |
|
193
|
|
|
|
|
194
|
|
|
return $httpcode; |
|
195
|
|
|
} |
|
196
|
|
|
} |
|
197
|
|
|
|
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.