PHP SoapClient目标命名空间不在请求参数中

时间:2014-03-03 11:51:07

标签: php web-services soap wsdl

我在WSDL模式下使用PHP SoapClient。

这就是预期的SOAP请求应该是这样的:

<soapenv:Envelope 
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:ns="http://xml.m4u.com.au/2009"> 
<soapenv:Header/> 
<soapenv:Body> 
 <ns:sendMessages> 
   <ns:authentication> 
     <ns:userId>Username</ns:userId> 
     <ns:password>Password</ns:password> 
   </ns:authentication> 
   <ns:requestBody> 
     <ns:messages> 
       <ns:message> 
         <ns:recipients> 
           <ns:recipient>61400000001</ns:recipient>  
         </ns:recipients> 
         <ns:content>Message Content</ns:content> 
       </ns:message> 
     </ns:messages> 
   </ns:requestBody> 
 </ns:sendMessages> 
</soapenv:Body> 
</soapenv:Envelope> 

这就是PHP SoapClient发送的内容:

<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="http://xml.m4u.com.au/2009">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<ns1:sendMessages>
  <ns1:authentication>
    <userId>Username</userId>
    <password>Password</password>
  </ns1:authentication>
  <ns1:requestBody>
    <messages>
      <message>
        <recipients>
          <recipient>61400000001</recipient>
        </recipients>
        <content>Message Content</content>
      </message>
    </messages>
  </ns1:requestBody>
</ns1:sendMessages>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

这就是我构建客户端和params的方式:

function sendMessages($recipient, $content) {

    $authenticationType = new SoapVar(array('userId' => $this->username, 'password' => $this->password), SOAP_ENC_OBJECT);

    $recipientsType = new SoapVar(array('recipient' => $recipient), SOAP_ENC_OBJECT);
    $messageType = new SoapVar(array('recipients' => $recipientsType, 'content' => $content), SOAP_ENC_OBJECT);
    $messagesType = new SoapVar(array('message' => $messageType), SOAP_ENC_OBJECT);

    $requestBodyType = new SoapVar(array('messages' => $messagesType), SOAP_ENC_OBJECT);

    $params = array(
                'authentication' => $authenticationType,
                'requestBody' => $requestBodyType
            );

    try {
        $this->soapClient = new SoapClient($this->wsdl, array('trace' => 1));
        $this->soapClient->__setSoapHeaders(array());

        return $this->soapClient->sendMessages($params);

    } catch (SoapFault $fault) {
        echo '<h2>Request</h2><pre>' . htmlspecialchars($this->soapClient->__getLastRequest(), ENT_QUOTES) . '</pre>';
        trigger_error("SOAP Fault: (faultcode: {$fault->faultcode}, faultstring: {$fault->faultstring})", E_USER_ERROR);
    }

}

为什么“ns1”出现在“身份验证”和“requestBody”但是缺少子节点? 我究竟做错了什么? WSDL位于此处=&gt; http://soap.m4u.com.au/?wsdl

感谢任何可以提供帮助的人。

2 个答案:

答案 0 :(得分:0)

尝试使用nusoap库。以下是示例代码:

<?php
$wsdl = "http://soap.m4u.com.au/?wsdl";
// generate request veriables
$data = array();

$action = ""; // ws action
$param = ""; //parameters

$options = array(
            'location'  => 'http://soap.m4u.com.au',
            'uri'       => ''
            );
// eof generate request veriables

//$client = new soap_client($wsdl, $options);// create soap client
$client = new nusoap_client($wsdl, 'wsdl');

$client->setCredentials($api_username, $api_password);// set crendencials
$opt = $client->call($action, $param, '', '', false, true);

print_r($opt);
?>

答案 1 :(得分:0)

您必须指定命名空间的URI以对对象进行编码。这将包括所有必要的(包括您缺少的命名空间)。命名空间名称的首字母缩写是无关紧要的。

此:

$authenticationType = new SoapVar(array('userId' => $this->username, 'password' => $this->password), SOAP_ENC_OBJECT);

应该是:

$authenticationType = new SoapVar(array('userId' => $this->username, 'password' => $this->password), SOAP_ENC_OBJECT, "authentication","http://xml.m4u.com.au/2009");

您使用命名空间序列化看到的问题来自于使用soapvar而没有所有参数。当它在发送请求之前序列化请求时,假定命名空间已经包含在内。相反,如果您将每个数组创建为一个简单数组并将它们包含在$params中,那么它将正确地包含内部参数的命名空间。通过演示:

$authenticationType = array('userId' => $this->username, 'password' => $this->password)