У меня проблема с подключением 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);
И у меня есть обертка вокруг родного класса Soap Client PHP:
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>
Так что в основном мой запрос такой же, как запрос в документации. Когда я запускаю этот код, я получаю исключение SoapFault с сообщением «Неверная версия» и кодом ошибки «VersionMismatch» и с кодами ошибок »http://schemas.xmlsoap.org/soap/envelope/».
Важно отметить, что если я оберну SOAP-вызов в блоки try / catch и если я не добавлю никакой логики, которая реагирует на исключение (оставляя блок catch пустым), ответ будет возвращен с кодом состояния 200, и он будет проанализирован нормально, и мой скрипт завершит выполнение без каких-либо ошибок.
Исключение определенно выбрасывается, но если я не реагирую на него, жизненный цикл запроса успешно завершен. В чем причина этой ошибки? Как справиться с этим? Должен ли я просто оставить блок catch открытым без какой-либо логики? Есть ли лучшее решение?
Еще немного информации о системе.
Версия SOAP такая же, как в документации (1.1). Моя версия PHP — 7.2, у меня нет доступа к SOAP-серверу, поэтому работающая там версия неизвестна …
Спасибо
РЕДАКТИРОВАТЬ после разрешенияОбязательно ознакомьтесь с обсуждением в комментариях ниже моего ответа. Оказалось, что сам сервис возвращает не SOAP, а XML, что вызывает исключение!
Старый ответ:
Нет способа запросить ваш сервис, так как вы не указали конечную точку. Пожалуйста, предоставьте один, если это вообще возможно. Также полезно посмотреть, что произойдет, если вы используете этот запрос через SOAPUI
, чтобы удостовериться, откуда на самом деле происходит ошибка, и исключить одно за другим.
В противном случае мое дикое предположение состоит в том, что теперь сервис может ожидать конверт версии SOAP 1.2 (без надлежащего обновления в рассматриваемой документации), и вы отправляете версию 1.1, поэтому вы можете попробовать изменить:
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
в
xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope"
и посмотрим, что получится. Стоит попробовать…
Подобный вопрос уже обсуждалось здесь, ищите больше подсказок.
Других решений пока нет …