代码之家  ›  专栏  ›  技术社区  ›  Alex

将XML嵌入到SOAP/PHP中编码小于和大于号

  •  0
  • Alex  · 技术社区  · 6 年前

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

    <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>
    

    现在SOAP客户端的请求,通过 echo $client->__getLastRequest(); 看起来像这样:

    <?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 回复  |  直到 6 年前
        1
  •  1
  •   Marcel    6 年前

    嗯,复杂的类型 doSomething 说,那房子 Payload 属于字符串类型。因此,xml内容的编码字符串应该是正确的。如果提供方希望内容未编码,则属性 有效载荷 会是另一种复杂的类型。因此,在这种情况下,wsdl是无效的,如果它是真的,那么提供者端确实需要一个元素而不是一个编码字符串。

    无论如何,有一个解决方案可以用PHP来处理。处理好 有效载荷 不是一根绳子。而是用它做一个复杂的类型。

    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'
            );
        }
    }
    

    上面你看到复杂的类型 剂量测定 作为一个PHP类。您还可以看到一个示例性的getter和setter方法。get方法返回null或\SoapVar实例。setter方法接受一个\SoapVar实例。

    出于您的目的,您需要另一个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>
    

    希望这对你有帮助。