我对连接到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 Client类进行了包装:
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>
因此,基本上我的要求与文档中的要求相同。当我触发此代码时,出现SoapFault异常,消息为“ Wrong version”,错误代码为“ VersionMismatch”,故障代码为“ http://schemas.xmlsoap.org/soap/envelope/”。
重要的注意事项,如果我将SOAP调用包装在try / catch块中,并且如果我不对异常做出反应的任何逻辑(将catch块留空),则响应将返回状态代码200,并且它会返回将正常解析,并且我的脚本将完成执行而不会出现任何错误。
肯定会引发异常,但是如果我不对此作出反应,则请求生命周期已成功完成。此错误的原因是什么?如何解决呢?我是否应该在没有任何逻辑的情况下将捕获块保持打开状态?有更好的解决方案吗?
关于该系统的更多信息。 SOAP版本与文档(1.1)中的相同。我的PHP版本是7.2,我无权访问SOAP服务器,因此在该服务器上运行的版本未知...
谢谢
答案 0 :(得分:1)
解决后进行编辑:请务必在我的答案下方的评论中查看讨论内容。事实证明,服务本身不返回SOAP,而是返回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"
看看会发生什么。值得一试... 类似的问题已经been discussed here,请寻找更多线索。