PHP SoapClient: How to prefix SOAP parameter tag n

2020-06-27 09:22发布

I'm using PHP's SoapClient to consume a SOAP service but am receiving an error that the SOAP service cannot see my parameters.

<tns:GenericSearchResponse xmlns:tns="http://.../1.0">
  <tns:Status>
    <tns:StatusCode>1</tns:StatusCode>
    <tns:StatusMessage>Invalid calling system</tns:StatusMessage>
  </tns:Status>
</tns:GenericSearchResponse>

The XML PHP's SoapClient sends for the SOAP call:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
    xmlns:ns1="http://.../1.0">
  <SOAP-ENV:Body>
    <ns1:GenericSearchRequest>
      <UniqueIdentifier>12345678</UniqueIdentifier>
      <CallingSystem>WEB</CallingSystem>
    </ns1:GenericSearchRequest>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

I used soap-ui initially, that works successfully when consuming the same WSDL. The XML soap-ui sends for the call:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:ns1="http://.../1.0">
  <SOAP-ENV:Body>
    <ns1:GenericSearchRequest>
      <ns1:UniqueIdentifier>12345678</ns1:UniqueIdentifier>
      <ns1:CallingSystem>WEB</ns1:CallingSystem>
    </ns1:GenericSearchRequest>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

The difference being the UniqueIdentifier and CallingSystem parameters are prefixed with ns1 in the soap-ui request.

I've tried using passing SoapVar objects to the SoapClient call but this does not augment the parameter tags and prefix them with ns1.

I know that WEB is a valid CallingSystem value as the XSD specifies it, and it works when using soap-ui.

My current SoapClient code:

try {
  $client = new SoapClient($wsdl, array('trace' => 1));
  $query = new stdClass;
  $query->UniqueIdentifier = $id;
  $query->CallingSystem = 'WEB';
  $response = $client->GenericUniqueIdentifierSearch($query);
} catch (SoapFault $ex) {
  $this->view->error = $ex->getMessage();
  ...
}

I found this blog post but I was hoping there might be a cleaner implementation.

Update: Used a solution from this question but is pretty clunky:

$xml = "<ns1:GenericSearchRequest>"
     . "<ns1:UniqueIdentifier>$id</ns1:UniqueIdentifier>"
     . "<ns1:CallingSystem>WEB</ns1:CallingSystem>"
     . "</ns1:GenericSearchRequest>";
$query = new SoapVar($xml, XSD_ANYXML);

$response = $this->client->__SoapCall(
    'GenericUniqueIdentifierSearch',
    array($query)
);

2条回答
太酷不给撩
2楼-- · 2020-06-27 09:37

Use a SoapVar to namespace the GenericSearchRequest fields:

$xml = "<ns1:GenericSearchRequest>"
     . "<ns1:UniqueIdentifier>$id</ns1:UniqueIdentifier>"
     . "<ns1:CallingSystem>WEB</ns1:CallingSystem>"
     . "</ns1:GenericSearchRequest>";
$query = new SoapVar($xml, XSD_ANYXML);

$response = $this->client->__SoapCall(
    'GenericUniqueIdentifierSearch',
    array($query)
);
查看更多
我只想做你的唯一
3楼-- · 2020-06-27 09:57

The reasonable way I found to do this, is to use a combination of SoapVar and SoapParam.

Note, SoapVar has options to specify the namespace of each var.

So your code should be something like:

$wrapper = new StdClass;
$wrapper->UniqueIdentifier = new SoapVar($id, XSD_STRING, "string", "http://www.w3.org/2001/XMLSchema", "UniqueIdentifier", "ns1");
$wrapper->CallingSystem = new SoapVar("WEB", XSD_STRING, "string", "http://www.w3.org/2001/XMLSchema", "CallingSystem", "ns1");
$searchrequest = new SoapParam($wrapper, "GenericSearchRequest");

try{
    $response = $this->client->GenericUniqueIdentifierSearch($searchrequest);
}catch(Exception $e){
    die("Error calling method: ".$e->getMessage());
}

If you get an issue where the attributes and the method are getting different namespaces, try specifying the namespace for your SoapVar as the url as defined in your envelope (in your example: "http://.../1.0") like:

$wrapper->UniqueIdentifier = new SoapVar($id, XSD_STRING, "string", "http://www.w3.org/2001/XMLSchema", "UniqueIdentifier", "http://.../1.0");

See the Soap constants for a list of all XSD_* constants.

查看更多
登录 后发表回答