我必须使用PHP使用SOAP Web服务,并且出现标题错误。
wsdl的(部分)结构是:
<xs:element name="Obligations" type="tns:ObligationsType"/>
<xs:complexType name="ObligationsType">
<xs:sequence>
<xs:element maxOccurs="99" name="Taxes" type="tns:TaxesType"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="TaxesType">
<xs:sequence>
<xs:element name="tax">
<xs:simpleType>
<xs:restriction base="xs:int">
<xs:maxInclusive value="9999"/>
<xs:minInclusive value="1"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="amount">
<xs:simpleType>
<xs:restriction base="xs:double">
<xs:minInclusive value="0.01"/>
<xs:maxInclusive value="9999999999.99"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:complexType>
我发送的关联数组:
$params = array(
'token' => $TOKEN,
'sign' => $SIGN,
'paymentEntity' => 1001,
'form' => array(
'formNumber' => 6042,
'idPaymentType' => 951,
'Obligations' => array (
array(
'Taxes' => array(
'tax' => 6041,
'amount' => 602.0
)
)
)
)
);
我尝试对类进行操作,但遇到相同的错误。问题出在“义务”对象上。
我尝试过这样的嵌套:
'Obligations'=> array('Taxes'=> array('tax'=> 1,'amount'=> 1.0))我得到了无法识别的字段义务
'Obligations'=> array('tax'=> 1,'amount'=> 1.0)我得到的对象没有'Taxes'属性
'义务'=>数组(array('Taxes'=> array('tax'=> 1,'amount'=> 1.0)))我得到对象没有'tax'属性
'Obligations'=> array('Taxes'=> array('tax'=> 1))我得到对象没有'amount'属性
'Obligations'=> array('Taxes'=> array('amount'=> 1))我发现对象没有'tax'属性
最后一个请求xml
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="...">
<SOAP-ENV:Body>
<ns1:createForm>
<ns1:token>********</ns1:token>
<ns1:sign>********</ns1:sign>
<ns1:paymentEntity>1001</ns1:paymentEntity>
<ns1:form>
<ns1:formNumber>6042</ns1:formNumber>
<ns1:idPaymentType>951</ns1:idPaymentType>
<ns1:Obligations>
<ns1:Taxes>
<tax>6041</tax>
<amount>602.0</amount>
</ns1:Taxes>
</ns1:Obligations>
</ns1:form>
</ns1:createForm>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
结构
"createFormResponse createForm(createForm $parameters)" [2]=> string(74)
"struct createForm { string token; string sign; int paymentEntity; FormType form; }"
"struct FormType { formNumber formNumber; idPaymentType idPaymentType; Obligations ObligationsType; }"
"struct ObligationsType { TaxesType Taxes; }"
"struct TaxesType { tax tax; amount amount; }"
我有一个请求示例,它与我获得的示例相同。 它只有一个注释
税收。此属性是列表类型。
税额。此属性是列表类型。
但是它已经在wsdl中标记了。
任何建议,我将不胜感激。问候
答案 0 :(得分:0)
在处理复杂类型时最好使用对象。它更干净,更易于操作。以下示例提示如何使用php处理复杂类型。
/**
* Entity from complex type ObligationsType
* @see xsd:complexType "ObligationsType"
*/
class ObligationsType
{
/**
* Is an array because the containing 'TaxtesType' can appear up to 99 times
* @var \ArrayObject
*/
protected $Taxes;
public function getTaxes() : \ArrayObject
{
return $this->Taxes;
}
public function setTaxes(TaxesType $taxes) : ObligationsType
{
if ($this->Taxes === null) {
$this->Taxes = new \ArrayObject();
}
$this->Taxes->append($taxes);
return $this;
}
public function encode() :\SoapVar
{
$container = new \ArrayObject();
foreach (get_obect_vars($this) as $property) {
if ($property instanceof \ArrayObject) {
foreach ($property as $element) {
$container->append($element);
}
} else {
$container->append($property);
}
}
return new \SoapVar(
$container,
SOAP_ENC_OBJ,
null,
null,
'Obligations',
'http://www.example.com/namespace/tns'
);
}
}
class TaxesType
{
protected $tax;
protected $amount;
public function getTax() : int
{
return $this->tax;
}
public function setTax(int $tax) : TaxesType
{
$this->tax = $tax;
return $this;
}
public function getAmount() : float
{
return $this->amount;
}
public function setAmount(float $amount) : TaxesType
{
$this->amount = $amount;
return $this;
}
public function encode() : \SoapVar
{
return new \SoapVar(
$this,
SOAP_ENC_OBJ,
null,
null,
'Taxes',
'http://www.example.com/namespace/tns'
);
}
}
因此,现在我们在wsdl als PHP实体类中获得了两种复杂的类型。该类唯一要做的就是保存我们的数据并对其进行编码,以便通过soap客户端类发送数据。
如何使用它?
只需告诉您的肥皂客户端类,您就有用于预期数据的类。出于此目的,肥皂客户端可以选择classmap
。
$client = new \SoapClient(
$path_to_your_wsdl,
[
'class_map' => [
'ObligationsType' => ObligationsType::class,
'TaxesType' => TaxesType::class,
],
'exceptions' => true,
'trace' => true,
],
);
$tax1 = (new TaxesType())
->setTax(19)
->setAmount(49.99)
->encode();
$tax2 = (new TaxesType())
->setTax(7)
->setAmount(29.49)
->encode();
$obligations = (new ObligationsType())
->setTaxes($tax1)
->setTaxes($tax2)
->encode();
$result = $client->YourWebserviceFunction($obligations);
这段简单的代码片段应说明xsd复杂类型如何与php soap客户端一起使用。形象地讲,每个复杂类型都是一个类,其中包含为该复杂类型描述的成员。这种理解使处理肥皂请求和响应中的数据变得容易。此外,每个Web服务功能都有在wsdl或任何绑定的xsd文件中描述的返回类型。找到此返回类型,并从中返回一个php类,并在soap客户端的classmap选项中提及它。 soap客户端可以轻松地在classmap选项中提到的返回类型类中对请求的返回进行水化处理。
如您所见,SOAP和PHP可以很好地协同工作。
请始终记住:上面显示的代码未经测试。请不要在生产中使用此代码。
编辑:如何在try / catch块中获取最后一个请求
正如您在此答案下的评论中提到的那样,您无法获得上一个请求。我将在接下来的几行中向您展示如何实现。只需将soap client init包装在try catch块中。如果soap客户端已初始化,则也可以在catch块中对其进行访问。
try {
$client = new \SoapClient(
$wsdl_path,
$options
);
// call of your webservice methods here
...
} catch (\SoapFault $e) {
// get the last request in the catch block
if ($client !== null) {
echo "<pre>";
var_dump(htmlentities($client->__getLastRequest()));
echo "</pre>";
}
}
别忘了将trace选项设置为true。如果没有,您将无法调用soap客户端的__getLastRequest()
方法。
请使用上一个xml请求编辑您的问题。