You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Zeep发送SOAP请求缺失必填属性引发验证错误,求解决方案

Zeep发送SOAP请求时遗漏必填属性的解决办法

问题描述

使用Zeep发送SOAP请求时,employmentRatesReplace节点缺少服务端要求的SOAP-ENC:arrayType属性,导致返回验证错误:

['Mandatory values [rate] missing in employmentRatesReplace section']

Zeep生成的问题请求结构:

<soap-env:Body>
  <ns0:wsdlUpdateAgreementsV2 xmlns:ns0="uri:FlexForce">
    <apiKey>xxxxx</apiKey>
    <agreements>
      <UpdateAgreementV2>
        <extAgreementId>6005961001</extAgreementId>
        <employmentRatesReplace>
          <EmploymentRate>
            <fromDate>2023-08-29</fromDate>
            <rate>80.00</rate>
          </EmploymentRate>
          <EmploymentRate>
            <fromDate>2023-06-20</fromDate>
            <rate>70.00</rate>
          </EmploymentRate>
          <EmploymentRate>
            <fromDate>2023-06-19</fromDate>
            <rate>100.00</rate>
          </EmploymentRate>
        </employmentRatesReplace>
        <validationErrors/>
      </UpdateAgreementV2>
    </agreements>
  </ns0:wsdlUpdateAgreementsV2>
</soap-env:Body>

服务端接受的正确请求结构(SoapUI测试通过):

<soap-env:Body>
  <ns0:wsdlUpdateAgreementsV2 xmlns:ns0="uri:FlexForce">
      <apiKey>xxxx</apiKey>
      <agreements>
        <UpdateAgreementV2>
           <extAgreementId>6005961001</extAgreementId>
           <employmentRatesReplace SOAP-ENC:arrayType="tns:EmploymentRate[2]">
              <item xsi:type="tns:EmploymentRate">
                 <fromDate xsi:type="xsd:date">2023-08-16</fromDate>
                 <rate xsi:type="xsd:decimal">50.00</rate>
              </item>
              <item xsi:type="tns:EmploymentRate">
                 <fromDate xsi:type="xsd:date">2023-10-16</fromDate>
                 <rate xsi:type="xsd:decimal">60.00</rate>
              </item>
           </employmentRatesReplace>
           <validationErrors/>
        </UpdateAgreementV2>
     </agreements>
  </ns0:wsdlUpdateAgreementsV2>
</soap-env:Body>

核心差异:

  • 正确结构用<item>标签包裹每个EmploymentRate对象
  • employmentRatesReplace节点需要添加SOAP-ENC:arrayType="tns:EmploymentRate[N]"属性(N为数组元素数量)

解决方案

方法1:手动构造符合要求的XML节点

通过Zeep的RawElement直接生成符合服务端要求的XML结构,绕过Zeep默认序列化规则:

from zeep import Client, xsd
from zeep.helpers import serialize_object
from lxml import etree

# 初始化Zeep客户端
client = Client('https://rc.quinyx.com/FlexForceWebServices.php?wsdl')

# 构造EmploymentRate对象列表
employment_rates = [
    client.get_type('tns:EmploymentRate')(fromDate='2023-08-29', rate=80.00),
    client.get_type('tns:EmploymentRate')(fromDate='2023-06-20', rate=70.00),
    client.get_type('tns:EmploymentRate')(fromDate='2023-06-19', rate=100.00)
]

# 获取所需命名空间
soap_enc_ns = client.wsdl.get_namespace('SOAP-ENC')
tns_ns = client.wsdl.get_namespace('tns')
xsi_ns = client.wsdl.get_namespace('xsi')

# 创建带SOAP-ENC属性的employmentRatesReplace节点
employment_rates_replace = etree.Element(
    '{uri:FlexForce}employmentRatesReplace',
    attrib={
        f'{{{soap_enc_ns}}}arrayType': f'{tns_ns}:EmploymentRate[{len(employment_rates)}]'
    }
)

# 为每个EmploymentRate生成item节点并添加属性
for rate in employment_rates:
    rate_elem = serialize_object(rate, target_cls=etree.Element)
    rate_elem.tag = 'item'
    rate_elem.set(f'{{{xsi_ns}}}type', f'{tns_ns}:EmploymentRate')
    employment_rates_replace.append(rate_elem)

# 构造UpdateAgreementV2对象,使用RawElement传入自定义节点
update_agreement = client.get_type('tns:UpdateAgreementV2')(
    extAgreementId='6005961001',
    employmentRatesReplace=xsd.Raw(employment_rates_replace),
    validationErrors=None
)

# 调用接口
result = client.service.wsdlUpdateAgreementsV2(
    apiKey='xxxxx',
    agreements=[update_agreement]
)

方法2:使用Zeep插件自动添加属性

编写Zeep插件,在请求发送前自动为employmentRatesReplace节点添加SOAP-ENC:arrayType属性:

from zeep import Client, Plugin

class AddArrayTypePlugin(Plugin):
    def egress(self, envelope, http_headers, operation, binding_options):
        # 定位employmentRatesReplace节点
        nodes = envelope.xpath('//ns0:employmentRatesReplace', namespaces={'ns0': 'uri:FlexForce'})
        for node in nodes:
            item_count = len(node.findall('.//item'))
            soap_enc_ns = envelope.nsmap.get('SOAP-ENC')
            tns_ns = envelope.nsmap.get('tns')
            if soap_enc_ns and tns_ns:
                node.set(f'{{{soap_enc_ns}}}arrayType', f'{tns_ns}:EmploymentRate[{item_count}]')
        return envelope, http_headers

# 加载插件初始化客户端
client = Client('https://rc.quinyx.com/FlexForceWebServices.php?wsdl', plugins=[AddArrayTypePlugin()])

# 构造数据时,用item列表包裹EmploymentRate对象
employment_rates = [
    {'fromDate': '2023-08-29', 'rate': 80.00},
    {'fromDate': '2023-06-20', 'rate': 70.00},
    {'fromDate': '2023-06-19', 'rate': 100.00}
]

update_agreement = {
    'extAgreementId': '6005961001',
    'employmentRatesReplace': {'item': employment_rates},
    'validationErrors': None
}

# 调用接口
result = client.service.wsdlUpdateAgreementsV2(apiKey='xxxxx', agreements=[update_agreement])

原因说明

该服务端依赖旧版SOAP编码规范(SOAP-ENC),要求数组类型必须携带SOAP-ENC:arrayType属性,且数组元素用<item>标签包裹。而Zeep默认采用文档/文字格式序列化,不会自动生成这类SOAP-ENC相关属性和结构,因此需要手动干预或通过插件修正。

内容的提问来源于stack exchange,提问作者Frej

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 06:27:03