将XML嵌入SOAP/PHP编码低于和大于符号
我们有一个包含以下内容的WSDL,并使用PHP的标准SOAP客户端进行调用:将XML嵌入SOAP/PHP编码低于和大于符号,php,soap,Php,Soap,我们有一个包含以下内容的WSDL,并使用PHP的标准SOAP客户端进行调用: <element name="doSomething"> <complexType> <sequence> <element name="Payload" nillable="true" type="xsd:string"/> <element name="Username" type="str
<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>
现在,SOAP客户端的请求通过echo$client->\uuu 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><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>
<?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是否有效
doSomething
表示,属性有效负载
是字符串类型。因此,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'
);
}
}
在上面,您可以看到复杂类型doSomething
是一个PHP类。您还可以看到示例getter和setter方法。get方法返回null或\SoapVar实例。setter方法采用\SoapVar实例
出于您的目的,您需要另一个PHP类来处理Payload
属性,该属性包含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>
希望这对您有所帮助。因此,在为代码属性初始化\SoapVar类时,只需释放namspace参数即可。我已经用这种方式编辑了我的答案。你会把这个解决方案称为“黑客”吗?我根本不会把它称为“黑客”。在您这边(消费者/php方面),这个解决方案是干净的,因为它都是原生php,没有变通方法或polyfill。使用未声明为干净的web服务解决提供者的问题是可以的。考虑一下,本地PHP SOAP客户端有一个类映射选项,您可以在这里列出所有WebService复杂类型。在实现soap客户机时,使用类和php自己提供的soap类是很自然的。
<ns1:doSomething>
<ns1:Payload>
<code>1</code>
</ns1:Payload>
<ns1:Username>...</ns1:Username>
<ns1:Service>...</ns1:Service>
<ns1:Password>...</ns1:Password>
</ns1:doSomething>