将XML嵌入SOAP / PHP中可对小于和大于符号进行编码

时间:2018-08-09 15:27:31

标签: php soap

我们有一个包含以下内容的WSDL,并使用标准的PHP SOAP Client进行调用:

<element name="doSomething">
    <complexType>
        <sequence>
            <element name="Payload" nillable="true" type="xsd:string"/>
            <element name="Username" type="string"/>
            <element name="service" type="string"/>
            <element name="Password" type="string"/>
        </sequence>
    </complexType>
</element>

有效载荷本质上是XML数据,例如看起来像这样

<code>1</code>

现在,通过echo $client->__getLastRequest(); 转储的SOAP客户端请求如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="pa/WebshopService"><SOAP-ENV:Body><ns1:doSomething><ns1:Payload>&lt;code&gt;
1
&lt;/code&gt;
</ns1:pcRequest><ns1:Username>bar</ns1:Username><ns1:service>bar</ns1:service><ns1:Password>bar</ns1:Password></ns1:doSomething></SOAP-ENV:Body></SOAP-ENV:Envelope>

我认为这是有道理的,因为<>应该被编码。

对方似乎期望这样:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="pa/WebshopService"><SOAP-ENV:Body><ns1:doSomething><ns1:Payload><code>
1
</code>
</ns1:pcRequest><ns1:Username>bar</ns1:Username><ns1:service>bar</ns1:service><ns1:Password>bar</ns1:Password></ns1:doSomething></SOAP-ENV:Body></SOAP-ENV:Envelope>
  • 如何使用PHP SoapClient发送此类邮件?
  • 在这种情况下WSDL甚至有效吗?

1 个答案:

答案 0 :(得分:1)

好吧,复杂类型doSomething说,属性Payload是字符串类型。因此,xml内容的编码字符串应该正确。如果提供方希望未编码的内容,则属性Payload将是另一种复杂类型。因此,在这种情况下,wsdl无效(如果为true),则提供者端确实需要元素而不是编码字符串。

无论如何,有一种解决方案可以使用PHP处理。只处理Payload而不是字符串。而是用它做成一个复杂的类型。

class DoSomething()
{
    protected $Payload;

    protected $Username;

    protected $Service;

    protected $Password;

    public function getPayload() : ?\SoapVar        {
        return $this->Payload;
    }

    public function setPayload(\SoapVar $payload) : DoSomething
    {
        $this->Payload = $payload;
        return $this;
    }

    ...

    public function encode() : \SoapVar
    {
        return new \SoapVar(
            $this,
            SOAP_ENC_OBJECT,
            null,
            null,
            'doSomething',
            'http://www.example.com/namespace'
        );
    }
}

上面您将复杂类型doSomething视为一个PHP类。您还会看到示例吸气剂和塞特方法。 get方法返回null或\ SoapVar实例。 setter方法采用一个\ SoapVar实例。

出于您的目的,您将需要Payload属性的另一个PHP类,其中包含code属性。

class Payload
{
    protected $Code;

    public function getCode() : ?\SoapVar
    {
        return $this->Code;
    }

    public function setCode(\SoapVar $code) : Payload
    {
        $this->Code = $code;
        return $this;
    }

    public function encode() : \SoapVar
    {
        return new \SoapVar
        {
            $this,
            SOAP_ENC_OBJECT,
            null,
            null,
            'Payload',
            'http://www.example.com/namespace'
        }
    }
}

现在将所有东西放在一起...

$code = new \SoapVar(1, XSD_INT, null, null, 'code');

$payload = (new Payload())
    ->setCode($code)
    ->encode();

$doSomething = (new DoSomething())
    ->setPayload($payload)
    ->setUsername(...)
    ->setService(...)
    ->setPassword(...)
    ->encode();

$result = $client->doSomething($doSomething);

现在您的请求应该看起来像...

<ns1:doSomething>
    <ns1:Payload>
        <code>1</code>
    </ns1:Payload>
    <ns1:Username>...</ns1:Username>
    <ns1:Service>...</ns1:Service>
    <ns1:Password>...</ns1:Password>
</ns1:doSomething>

希望对您有帮助。