PHP Soap Client错误版本错误,SOAP服务器返回正确的响应

时间:2018-11-26 23:02:42

标签: php laravel soap version mismatch

我对连接到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服务器,因此在该服务器上运行的版本未知...

谢谢

1 个答案:

答案 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,请寻找更多线索。