Ошибка неверной версии PHP Soap Client, когда SOAP-сервер возвращает правильный ответ - PullRequest
0 голосов
/ 27 ноября 2018

У меня проблема с подключением 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 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-серверу, поэтому работающая там версия неизвестна ...

Спасибо

1 Ответ

0 голосов
/ 27 ноября 2018

РЕДАКТИРОВАТЬ после разрешения : Обязательно ознакомьтесь с обсуждением в комментариях под моим ответом.Оказалось, что сама служба возвращает не 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"

и посмотрим, что получится.Стоит попробовать ... Подобный вопрос уже обсуждался здесь , ищите больше подсказок.

...