douhao7889 2018-08-09 15:27
浏览 32
已采纳

将XML嵌入SOAP / PHP编码低于和高于符号

We have an WSDL that contains the following and make a call using the standard SOAP Client of PHP:

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

The Payload is essentially XML data, which looks for example like this

<code>1</code>

Now the request of the SOAP client, dumped via echo $client->__getLastRequest(); looks like this:

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

which, I believe makes sense, as the < and > should be encoded.

The counterpart seems to expect something like this:

<?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>
  • How can I send such using the PHP SoapClient?
  • Is the WSDL even valid in this case?
  • 写回答

1条回答 默认 最新

  • douzhan1994 2018-08-10 08:42
    关注

    Well, the complex type doSomething says, that the property Payload is of type string. Consequently the encoded string of the xml content should be right. If the provider side expects the content not encoded, the property Payload would be another complex type. So in this case the wsdl is not valid, if it 's true, that the provider side really wants an element and not an encoded string.

    Anyway, there 's a solution you can handle this with PHP. Just handle Payload not as a string. Instead make a complex type out of it.

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

    Above you see the complex type doSomething as a PHP class. You also see an examplary getter and setter method. The get method returns null or a \SoapVar instance. The setter method takes a \SoapVar instance.

    For your purpose you 'll need another PHP class for the Payload property, which contains the code property.

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

    Now just put all together ...

    $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);
    

    Now your request should look like ...

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

    Hope that helped you.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 luckysheet
  • ¥15 ZABBIX6.0L连接数据库报错,如何解决?(操作系统-centos)
  • ¥15 找一位技术过硬的游戏pj程序员
  • ¥15 matlab生成电测深三层曲线模型代码
  • ¥50 随机森林与房贷信用风险模型
  • ¥50 buildozer打包kivy app失败
  • ¥30 在vs2022里运行python代码
  • ¥15 不同尺寸货物如何寻找合适的包装箱型谱
  • ¥15 求解 yolo算法问题
  • ¥15 虚拟机打包apk出现错误