如何使用名称空间(在params和方法中)和嵌套结构(在param中)在PHP中调用SOAP方法


How do I call SOAP methods in PHP using namespaces (in params and methods) and nested structures (in params)?

假设我有这个XML(它是一个SOAP调用)

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ext="http://api.movilway.net/schema/extended">
  <soapenv:Header/>
  <soapenv:Body>
    <ext:GetBalanceRequest>
      <ext:AuthenticationData>
        <ext:Username>Foo</ext:Username>
        <ext:Password>Bar$123!password</ext:Password>
        <ext:SessionID>as3hy4ri37g2f345</ext:SessionID>
      </ext:AuthenticationData>
      <ext:DeviceType>3</ext:DeviceType>
    </ext:GetBalanceRequest>
  </soapenv:Body>
</soapenv:Envelope>

(Foo,Bar$123!password,as3hy4ri37g2f345和3只是示例值)通常,当我想进行简单的SOAP调用时,我会使用这样的SoapClient

$sc = new SoapClient('http://my.url/my/service?wsdl');
$result = $sc->someMethod(array('some' => 'params'));

但是这个似乎使用xsd名称空间和嵌套结构。

Q:如何调用带有命名空间前缀的方法(在本例中为ext:)和带有命名空间前缀(和嵌套结构)的参数?

编辑:我所尝试的包括将名称空间作为uri选项。有一个例外:

SoapFault:函数("GetBalanceRequest")不是此服务的有效方法

我试过的代码是这样的:

try {
    $client = new SoapClient('http://THEURLHERE/Path/To/The/Service?wsdl', array('uri' => 'http://api.movilway.net/schema/extended'));
    print_r($client->GetBalanceRequest(
        array(
            'AuthenticationData' => array(
                'Username' => 'MYUSERHERE',
                'Password' => 'MYPASSWORDHERE'
            ),
            'DeviceType' => 1
        )
    ));
} catch(Exception $e) {
    print_r($e);
}

假设没有错误或打字错误,因为我直接从文档中获得了所需的XML。

Q+:我必须在代码中添加什么才能发送这样的请求?

首先,正确的术语不是"extension",而是"namespace"——这里的namespace被称为"extended",并且在示例中被赋予了别名ext:,这只是巧合。

其次,XML名称空间只是表示"这些元素和属性属于特定类型"的一种方式;它不会自动暗示普通XML之外的任何特殊结构——例如,它与XSD没有自动关系。命名空间是由URI唯一标识的,URI实际上不必指向任何地方(有关更多信息,请参阅前面的回答)。在文档中,它被赋予了一个任意的前缀,这样你就不必在每个元素旁边写URI。

SOAP本身使用名称空间http://schemas.xmlsoap.org/soap/envelope/作为表示SOAP"信封"的元素,这里给出了别名soapenv。SOAP消息的"主体"不在该名称空间中,因此SOAP服务通常将其元素声明为其他特定名称空间的一部分;如果没有,它们将位于默认的、无名称的命名空间中。

所以,理论就到此为止了。练习:

如果您正在使用WSDL加载web服务,并且该WSDL的格式正确,那么SOAPClient类应该自动向您的请求添加适当的命名空间。由于请求完全存在于该名称空间内,因此无需区分"名称空间http://api.movilway.net/schema/extended中的AuthenticationData"answers"AuthenticationData"。

如果由于某种原因这不起作用,或者您没有WSDL,那么您可能需要创建具有适当名称空间的SoapVar对象。

然而,根据您刚刚编辑到问题中的错误消息,以上所有内容可能都完全无关,因为问题可能与命名空间无关——您在WSDL模式下操作,而客户端告诉您该方法不存在。所以,对我来说,显而易见的问题是,该方法是否在WSDL文件中明确定义?