Andrija Glavas
Andrija Glavas

Reputation: 143

PHP Soap Client wrong version error with SOAP server returning correct response

I have a problem with SOAP request connecting to web service.

First, this is my code:

$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);

And I have wrapper around PHP's native Soap Client 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
}

}

So basically it is connecting to SOAP web service (without WSDL) and it fetches some data. A lot of this code is here just to do string (or XML) manipulation so the request can look exactly as in the SOAP web service documentation. Final request (after all modifications) looks like this:

<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/".

Important thing to notice, if I wrap SOAP call in try/catch blocks and if I don't put any logic that is reacting to exception (leaving catch block empty), response will be returned with status code 200, and it will be parsed normally and my script will finish execution without any error.

Exception is definitely thrown, but if I don't react to it request lifecycle is completed successfully. What is the cause of this error? How to tackle this? Should I just leave catch block open without any logic? Is there a better solution?

Few more information about the system. SOAP version is the same as in the documentation (1.1). My PHP version is 7.2, I don't have access to SOAP server so version running there is unknown...

Thanks

Upvotes: 1

Views: 5382

Answers (1)

Plamen G
Plamen G

Reputation: 4759

EDIT after resolution: Be sure to check out the discussion in comments below my answer. It turned out that the service itself doesn't return SOAP, but XML, which causes the exception!

Old answer:

There's no way to query your service as you have not provided endpoint. Please do provide one if at all possible. It's also a good idea to see what happens if you use this request via SOAPUI, to make sure where the error actually comes from and rule out things one by one.

Otherwise my wild guess is that the service might now expect SOAP 1.2 version (without this being properly updated in the documentation in question) envelope and you are sending v 1.1 one, so you might try changing:

xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"

to xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope"

and see what happens. Worth a try... A similar question has already been discussed here, look for more clues.

Upvotes: 2

Related Questions