PHP SOAP 服务器返回正确响应的 Soap 客户端错误版本错误
PHP Soap Client wrong version error with SOAP server returning correct response
连接到 Web 服务的 SOAP 请求出现问题。
首先,这是我的代码:
$soapClient = new NewSoapClient(null, [
'location' =>
"https://www.phobs.net/test/webservice/pc/service.php",
'uri' => "http://www.opentravel.org/OTA/2003/05",
'trace' => 1,
"soap_version" => SOAP_1_1,
]);
$ns_wsse = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd';
$password_type = 'ns2:http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText';
// Creating WSS identification header using SimpleXML
$root = new \SimpleXMLElement('<root/>');
$security = $root->addChild('ns2:Security', null, $ns_wsse);
$usernameToken = $security->addChild('ns2:UsernameToken', null, $ns_wsse);
$usernameToken->addChild('ns2:Username', 'username', $ns_wsse);
$usernameToken->addChild('ns2:Password', 'pass', $ns_wsse)->addAttribute('xsi:xsi:type', $password_type);
$root->registerXPathNamespace('ns2', $ns_wsse);
$full = $root->xpath('/root/ns2:Security');
$auth = $full[0]->asXML();
$auth = str_replace(' xmlns:ns2="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"','', $auth);
$soapClient->__setSoapHeaders(new \SoapHeader($ns_wsse, 'Security', new \SoapVar($auth, XSD_ANYXML), true));
try {
$response = $soapClient->__soapCall("OTA_RoomRateListRQ",[
new \SoapVar('<ns1:HotelInfo HotelCode="' . 'ATL476' . '" DestinationSystemCode="' . 'ATLANTIS' . '" />', XSD_ANYXML)
]);
} catch (\SoapFault $exception)
{
var_dump($exception);
//die();
}
$response = json_decode(json_encode((array)simplexml_load_string($soapClient->__getLastResponse())),1);
我对 PHP 的本地 Soap 客户端进行了包装 class:
class NewSoapClient extends \SoapClient
{
public function __doRequest($request, $location, $action, $version, $one_way = 0)
{
$string = '<?xml version="1.0" encoding="UTF-8"?>';
$request = str_replace($string , '', $request);
$request = str_replace('xmlns:xsd="http://www.w3.org/2001/XMLSchema"', 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"', $request);
$request = str_replace('xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"', '', $request);
$request = str_replace('xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >', 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">', $request);
$request = trim($request);
return parent::__doRequest($request, $location, $action, $version, $one_way); // TODO: Change the autogenerated stub
}
}
所以基本上它连接到 SOAP Web 服务(没有 WSDL)并获取一些数据。这里的很多代码只是为了执行字符串(或 XML)操作,因此请求看起来与 SOAP Web 服务文档中的完全一样。最终请求(所有修改后)如下所示:
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="http://www.opentravel.org/OTA/2003/05"
xmlns:ns2="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Header>
<ns2:Security>
<ns2:UsernameToken>
<ns2:Username>username</ns2:Username>
<ns2:Password xsi:type="ns2:http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">pass</ns2:Password>
</ns2:UsernameToken>
</ns2:Security>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns1:OTA_RoomRateListRQ>
<ns1:HotelInfo HotelCode="ATL476" DestinationSystemCode="ATLANTIS" />
</ns1:OTA_RoomRateListRQ>
</SOAP-ENV:Body>
所以基本上我的要求和文档中的要求是一样的。当我触发此代码时,我收到消息 "Wrong version" 和故障代码 "VersionMismatch" 以及故障代码“http://schemas.xmlsoap.org/soap/envelope/”.
的 SoapFault 异常
需要注意的重要事项,如果我将 SOAP 调用包装在 try/catch 块中,并且如果我不放置任何对异常做出反应的逻辑(将 catch 块留空),响应将与状态代码一起返回200,它会被正常解析,我的脚本将无误地完成执行。
肯定会抛出异常,但如果我不对此做出反应,则请求生命周期已成功完成。这个错误的原因是什么?如何解决这个问题?我应该在没有任何逻辑的情况下让 catch 块保持打开状态吗?有更好的解决方案吗?
关于系统的更多信息。
SOAP 版本与文档 (1.1) 中的版本相同。我的 PHP 版本是 7.2,我无法访问 SOAP 服务器,所以版本 运行 未知...
谢谢
解决后编辑:请务必查看我回答下方评论中的讨论。原来是服务本身没有returnSOAP,而是XML,才导致异常!
旧答案:
由于您未提供端点,因此无法查询您的服务。请尽可能提供一份。如果您通过 SOAPUI
使用此请求,看看会发生什么情况也是一个好主意,以确保错误的实际来源并一一排除。
否则我的疯狂猜测是该服务现在可能需要 SOAP 1.2 版本(没有在相关文档中正确更新)信封,而您发送的是 v 1.1,因此您可以尝试更改:
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
至
xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope"
看看会发生什么。值得一试...
类似的问题已经,寻找更多线索
连接到 Web 服务的 SOAP 请求出现问题。
首先,这是我的代码:
$soapClient = new NewSoapClient(null, [
'location' =>
"https://www.phobs.net/test/webservice/pc/service.php",
'uri' => "http://www.opentravel.org/OTA/2003/05",
'trace' => 1,
"soap_version" => SOAP_1_1,
]);
$ns_wsse = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd';
$password_type = 'ns2:http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText';
// Creating WSS identification header using SimpleXML
$root = new \SimpleXMLElement('<root/>');
$security = $root->addChild('ns2:Security', null, $ns_wsse);
$usernameToken = $security->addChild('ns2:UsernameToken', null, $ns_wsse);
$usernameToken->addChild('ns2:Username', 'username', $ns_wsse);
$usernameToken->addChild('ns2:Password', 'pass', $ns_wsse)->addAttribute('xsi:xsi:type', $password_type);
$root->registerXPathNamespace('ns2', $ns_wsse);
$full = $root->xpath('/root/ns2:Security');
$auth = $full[0]->asXML();
$auth = str_replace(' xmlns:ns2="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"','', $auth);
$soapClient->__setSoapHeaders(new \SoapHeader($ns_wsse, 'Security', new \SoapVar($auth, XSD_ANYXML), true));
try {
$response = $soapClient->__soapCall("OTA_RoomRateListRQ",[
new \SoapVar('<ns1:HotelInfo HotelCode="' . 'ATL476' . '" DestinationSystemCode="' . 'ATLANTIS' . '" />', XSD_ANYXML)
]);
} catch (\SoapFault $exception)
{
var_dump($exception);
//die();
}
$response = json_decode(json_encode((array)simplexml_load_string($soapClient->__getLastResponse())),1);
我对 PHP 的本地 Soap 客户端进行了包装 class:
class NewSoapClient extends \SoapClient
{
public function __doRequest($request, $location, $action, $version, $one_way = 0)
{
$string = '<?xml version="1.0" encoding="UTF-8"?>';
$request = str_replace($string , '', $request);
$request = str_replace('xmlns:xsd="http://www.w3.org/2001/XMLSchema"', 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"', $request);
$request = str_replace('xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"', '', $request);
$request = str_replace('xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >', 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">', $request);
$request = trim($request);
return parent::__doRequest($request, $location, $action, $version, $one_way); // TODO: Change the autogenerated stub
}
}
所以基本上它连接到 SOAP Web 服务(没有 WSDL)并获取一些数据。这里的很多代码只是为了执行字符串(或 XML)操作,因此请求看起来与 SOAP Web 服务文档中的完全一样。最终请求(所有修改后)如下所示:
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="http://www.opentravel.org/OTA/2003/05"
xmlns:ns2="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Header>
<ns2:Security>
<ns2:UsernameToken>
<ns2:Username>username</ns2:Username>
<ns2:Password xsi:type="ns2:http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">pass</ns2:Password>
</ns2:UsernameToken>
</ns2:Security>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns1:OTA_RoomRateListRQ>
<ns1:HotelInfo HotelCode="ATL476" DestinationSystemCode="ATLANTIS" />
</ns1:OTA_RoomRateListRQ>
</SOAP-ENV:Body>
所以基本上我的要求和文档中的要求是一样的。当我触发此代码时,我收到消息 "Wrong version" 和故障代码 "VersionMismatch" 以及故障代码“http://schemas.xmlsoap.org/soap/envelope/”.
的 SoapFault 异常需要注意的重要事项,如果我将 SOAP 调用包装在 try/catch 块中,并且如果我不放置任何对异常做出反应的逻辑(将 catch 块留空),响应将与状态代码一起返回200,它会被正常解析,我的脚本将无误地完成执行。
肯定会抛出异常,但如果我不对此做出反应,则请求生命周期已成功完成。这个错误的原因是什么?如何解决这个问题?我应该在没有任何逻辑的情况下让 catch 块保持打开状态吗?有更好的解决方案吗?
关于系统的更多信息。 SOAP 版本与文档 (1.1) 中的版本相同。我的 PHP 版本是 7.2,我无法访问 SOAP 服务器,所以版本 运行 未知...
谢谢
解决后编辑:请务必查看我回答下方评论中的讨论。原来是服务本身没有returnSOAP,而是XML,才导致异常!
旧答案:
由于您未提供端点,因此无法查询您的服务。请尽可能提供一份。如果您通过 SOAPUI
使用此请求,看看会发生什么情况也是一个好主意,以确保错误的实际来源并一一排除。
否则我的疯狂猜测是该服务现在可能需要 SOAP 1.2 版本(没有在相关文档中正确更新)信封,而您发送的是 v 1.1,因此您可以尝试更改:
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
至
xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope"
看看会发生什么。值得一试...
类似的问题已经