У меня проблема с 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 (без WSDL) и извлекает некоторые данные. Большая часть этого кода предназначена только для манипуляций со строками (или XML), поэтому запрос может выглядеть точно так же, как в документации веб-сервиса SOAP. Окончательный запрос (после всех доработок) выглядит так:
<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>
So basically my request is the same as the request in documentation. When I trigger this code I get SoapFault exception with message "Wrong version" and fault code "VersionMismatch" and with faultcodens "http://schemas.xmlsoap.org/soap/envelope/".
Важно отметить, что если я оборачиваю вызов SOAP в блоки try/catch и не добавляю никакой логики, которая реагирует на исключение (оставляя блок catch пустым), ответ будет возвращен с кодом состояния 200 и будет проанализирован. нормально, и мой скрипт завершит выполнение без каких-либо ошибок.
Исключение определенно выбрасывается, но если я не реагирую на него, жизненный цикл запроса завершается успешно. В чем причина этой ошибки? Как справиться с этим? Должен ли я просто оставить блок catch открытым без какой-либо логики? Есть ли лучшее решение?
Еще немного информации о системе. Версия SOAP такая же, как в документации (1.1). Моя версия PHP 7.2, у меня нет доступа к серверу SOAP, поэтому версия, которая там работает, неизвестна...
Спасибо