问题似乎是WSDL文档受到某种方式的保护(基本身份验证-
我不认为摘要身份验证受支持
SoapClient,因此在这种情况下您会很不走运),因此WSDL文档
SoapClient无法读取和解析服务描述。
首先,您应该尝试在浏览器中打开WSDL位置,以检查是否显示了身份验证对话框。如果存在认证对话框,则必须确保
SoapClientWSDL在检索WSDL文档时使用必需的登录凭证。问题是,
SoapClient将只发送给定的凭证
login和
password(以及选项
local_cert使用证书认证时选择)上调用该服务时,获取的WSDL不是当创建客户端。有两种方法可以解决此问题:
- 在
SoapClient
构造函数调用中将登录凭证添加到WSDL URL$client = new SoapClient('https://' . urlenpre($login) . ':' . urlenpre($password) . '@example.com/WSDL/nameofservice',array( 'login' => $login, 'password' => $password));
这应该是最简单的解决方案-但是在PHP Bug#27777中,它写成也不起作用(我没有尝试过)。
- 使用HTTP流包装器手动获取WSDL,
ext/curl
或者通过浏览器手动获取WSDLwget
,例如通过将其存储在磁盘上,并SoapClient
使用对本地WSDL的引用实例化WSDL。
如果WSDL文档发生更改(因为您必须检测到更改并将新版本存储在磁盘上),则此解决方案可能会出现问题。
如果未显示验证对话框,并且您可以在浏览器中阅读WSDL,则应提供更多详细信息以检查其他可能的错误/问题。
最终,此问题与服务本身无关,因为
SoapClient在发出对服务本身的调用之前读取服务描述文档时已经遇到了麻烦。
编辑:
在本地拥有WSDL文件是第一步-这将使WSDL
SoapClient知道如何与服务进行通信。WSDL是直接从服务位置,从另一台服务器提供还是从本地文件中读取都没有关系-
服务URL在WSDL中编码,因此
SoapClient始终知道在哪里寻找服务端点。
现在的第二个问题是本机
SoapClient不支持WS-Security规范,这意味着您必须扩展
SoapClient以处理特定的标头。添加所需行为的扩展点是在将
SoapClient::__doRequest()XML有效载荷发送到服务端点之前对其进行预处理。但我认为,自己实施WS-
Security解决方案将需要对特定WS-Security规范有相当的了解。也许还可以使用
SoapClient::__setSoapHeaders()和适当
SoapHeader的来创建WS-Security标头并将其打包到XML请求中,但我怀疑这样做是否可行,将定制
SoapClient扩展名留为唯一可能性。
一个简单的
SoapClient扩展是
class My_SoapClient extends SoapClient{ protected function __doRequest($request, $location, $action, $version) { $domRequest = new DOMdocument(); $domRequest->loadXML($request); // modify XML using the DOM API, e.g. get the <s:Header>-tag // and add your custom headers $xp = new DOMXPath($domRequest); $xp->registerNamespace('s', 'http://www.w3.org/2003/05/soap-envelope'); // fails if no <s:Header> is found - error checking needed $header = $xp->query('/s:Envelope/s:Header')->item(0); // now add your custom header $usernameToken = $domRequest->createElementNS('http://schemas.xmlsoap.org/ws/2002/07/secext', 'wsse:UsernameToken'); $username = $domRequest->createElementNS('http://schemas.xmlsoap.org/ws/2002/07/secext', 'wsse:Username', 'userid'); $password = $domRequest->createElementNS('http://schemas.xmlsoap.org/ws/2002/07/secext', 'wsse:Password', 'password'); $usernameToken->appendChild($username); $usernameToken->appendChild($password); $header->appendChild($usernameToken); $request = $domRequest->saveXML(); return parent::__doRequest($request, $location, $action, $version); }}对于基本的WS-Security认证,您必须将以下内容添加到SOAP标头中:
<wsse:UsernameToken> <wsse:Username>userid</wsse:Username> <wsse:Password>password</wsse:Password></wsse:UsernameToken>
但是正如我上面所说:我认为需要更多有关WS-Security规范和给定服务体系结构的知识才能使此工作正常进行。
_如果您需要整个WS- *规范范围的企业级解决方案,并且可以安装PHP模块,则应该查看PHP的WSO2 Web服务框架(WSO2 WSF /PHP)



