使用 Zeep (python)

问题描述

我在通过 Zeep 获取 SOAP 请求时遇到问题,出现(客户端)验证错误...我也使用 SoapUI 进行了测试,但没有出现相同的验证错误...

以下规范来自服务器...基于该规范,执行请求需要 OrderStatus 和 SynchStatus。

<soapenv:Envelope xmlns:soapenv=http://schemas.xmlsoap.org/soap/envelope/ xmlns:web="WebServiceProvider">
   <soapenv:Header/>
   <soapenv:Body>
      <web:Order_Get>
         <!--Optional:-->
         <web:orderOptions>
            <web:FromDate>?</web:FromDate>
            <web:ToDate>?</web:ToDate>
            <web:OrderStatus>?</web:OrderStatus>
            <web:SynchStatus>?</web:SynchStatus>
            <!--Optional:-->
            <web:OrderNumber>?</web:OrderNumber>
            <web:FromOrderNumberToLastRecieved>?</web:FromOrderNumberToLastRecieved>
            <web:PaymentStatus>?</web:PaymentStatus>
         </web:orderOptions>
      </web:Order_Get>
   </soapenv:Body>
</soapenv:Envelope>

但是,在没有 OrderStatus 和 SynchStatus 的情况下从 SoapUI 执行此操作将为我提供指定日期的所有订单的列表:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="WebServiceProvider">
   <soapenv:Header/>
   <soapenv:Body>
      <web:Order_Get>
         <web:orderOptions>
            <web:FromDate>2021-03-30</web:FromDate>
            <web:ToDate>2021-03-31</web:ToDate>
         </web:orderOptions>
      </web:Order_Get>
   </soapenv:Body>
</soapenv:Envelope>

我想对 Zeep (https://github.com/mvantellingen/python-zeep) 做同样的事情,但客户端验证失败...

我使用以下代码发起请求:

api_url = 'https://abc.se/Webservice20/v3.0/webservice.asmx?WSDL'
session.auth = HTTPDigestAuth(username,password)
api = Client(api_url,transport=Transport(session=session))

然后我尝试执行以下请求:

order_options = {
  'FromDate': '2021-03-30','ToDate': '2021-03-31',}
orders = api.service.Order_Get(orderOptions=order_options)

这将导致以下错误

zeep.exceptions.ValidationError: Missing element OrderStatus (Order_Get.orderOptions.OrderStatus)

如果我将 OrderStatus 添加到请求中,我将收到一条验证错误,指出缺少 SynchStatus。添加后,请求将发送到服务器。

即似乎 zeep 客户端在验证请求中的数据方面比服务器更严格......有没有办法强制客户端跳过此验证?

非常感谢!

解决方法

似乎 zeep 客户端在验证请求中的数据方面比服务器更严格...

看起来像。

查看SoapUI基于WSDL生成的请求,你提到的两个字段是必填的:

 <web:orderOptions>
    <web:FromDate>?</web:FromDate>
    <web:ToDate>?</web:ToDate>
    <web:OrderStatus>?</web:OrderStatus>
    <web:SynchStatus>?</web:SynchStatus>
    <!--Optional:-->
    <web:OrderNumber>?</web:OrderNumber>
    <web:FromOrderNumberToLastRecieved>?</web:FromOrderNumberToLastRecieved>
    <web:PaymentStatus>?</web:PaymentStatus>
 </web:orderOptions>

所以zeep客户端显示的错误是正确的。 Zeep 检查 WSDL 并生成相应的代码以使用合约中的类型。您的 WSDL 合同规定 OrderStatusSynchStatus 是强制性的。服务器不验证它们的事实表明一个问题:Web 服务不尊重它自己的书面合同

WSDL 和 Web 服务的行为应该相同。我建议您联系网络服务所有者并询问这种行为。可能是服务器上缺少验证,您得到的只是它的一些副作用,或者行为是故意的,但有人忘记更新 WSDL 说您也可以在没有这些参数的情况下进行调用。

同时,解决方法非常简单。下载 WSDL,对其进行更改以使这两个字段可选,然后将此更改后的 WSDL 提供给 zeep 以生成代码,而不是使用原始 WSDL。但是,您应该向 Web 服务提供商澄清这一点。如果确实是某人的疏忽,这可能会在某个时候被发现并修复,从而使您的变通方法调用由于缺少字段而无法通过服务器验证。

,

在这篇文章中搜索了更多内容并找到了解决方法:Variatus' very helpful code

所以我的解决方案如下所示:

import plotly.graph_objects as go


import plotly.graph_objects as go

PLOT = go.Figure()

for C in list(df3d.p.unique()):

    PLOT.add_trace(go.Scatter3d(x = df3d[df3d.p == C]['x'],y = df3d[df3d.p == C]['y'],z = df3d[df3d.p == C]['z'],mode = 'markers',marker_size = 8,marker_line_width = 1,name = 'Cluster ' + str(C)))

这将阻止 zeep 对参数 OrderStatus 和 SynchStatus 进行客户端验证。