为何PHP中Guzzle调用SOAP正常但SoapClient调用失败?
问题:PHP SoapClient无法加载WSDL但Guzzle和SoapUI可正常调用
我用Guzzle调用SOAP接口能成功获取响应,代码如下:
$client = new Client(); $body = '<?xml version="1.0" encoding="utf-8"?> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <GetAuthenticationToken xmlns="http://tempuri.org/"> <username>'. config('services.tmw.username') .'</username> <password>'. config('services.tmw.username') .'</password> <applicationName>testing</applicationName> </GetAuthenticationToken> </soap:Body> </soap:Envelope> '; $wsdl = '*** MASKED URL ***Service.svc'; $res = $client->request('POST', $wsdl, [ 'headers' => ['Content-Type' => 'text/xml; charset=utf-8', 'SOAPAction' => 'http://tempuri.org/IDRTrackWebService/GetAuthenticationToken'], 'body' => $body]); $body = $res->getBody(); dd($body->getContents());
但想用更简便的SoapClient,写了如下代码:
$svcUrl = '---MASKED URL ---Service.svc'; $wsdl = '---MASKED URL ---Service.svc?wsdl'; $client = new \SoapClient($wsdl, array('trace' => 1)); $params = new \stdClass(); $params->username = 'username'; $params->password = 'password'; $params->applicationName = 'testing'; $result = $client->__soapCall('GetAuthenticationToken', ['GetAuthenticationToken' => $params]); dd($result);
不管加不加?wsdl参数,都会报错:
SOAP-ERROR: Parsing WSDL: Couldn't load from '---MASKED URL ---Service.svc?wsdl' : failed to load external entity "---MASKED URL ---Service.svc?wsdl"
已验证的情况:
- 浏览器访问不带
?wsdl的URL能看到使用说明,带?wsdl能显示完整XML内容 - WSDL里的
wsdl:service => port => soap:address和$svcUrl一致 - SoapUI中可正常调用该接口
解决思路
- 检查PHP
allow_url_fopen配置:SoapClient默认依赖allow_url_fopen加载远程WSDL,通过phpinfo()查看该配置是否为On,若关闭则无法加载远程资源。 - 添加自定义流上下文:部分服务器会拦截非浏览器请求,或需要代理/特定HTTP头,给SoapClient传入
stream_context参数模拟浏览器请求:$context = stream_context_create([ 'http' => [ 'header' => "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36\r\n" // 需代理则添加:'proxy' => 'tcp://proxy:port', 'request_fulluri' => true ] ]); $client = new \SoapClient($wsdl, ['trace' => 1, 'stream_context' => $context]); - 本地加载WSDL:先把WSDL内容下载到本地,再通过
location指定服务地址:$localWsdl = '/path/to/local/service.wsdl'; $client = new \SoapClient($localWsdl, [ 'trace' => 1, 'location' => $svcUrl ]); - 处理SSL证书问题:若服务为HTTPS,PHP可能无法验证证书,临时关闭验证(仅测试用,生产环境需配置可信证书):
$context = stream_context_create([ 'ssl' => [ 'verify_peer' => false, 'verify_peer_name' => false ] ]); $client = new \SoapClient($wsdl, ['trace' => 1, 'stream_context' => $context]); - 检查WSDL依赖文件:部分WSDL会导入其他XSD/XML文件,浏览器和SoapUI会自动加载,但PHP可能无法获取这些依赖。查看WSDL中的
<import>/<include>标签,确认依赖URL可访问,或下载到本地并修改WSDL路径。
内容的提问来源于stack exchange,提问作者TJ Sherrill
相关产品推荐
相关产品推荐

