首页 > 解决方案 > 使用 Python 将带有附件的 XML 发送到 SOAP ws

问题描述

在过去的几周里,我一直在学习 Python,并尝试将自定义 XML 发送到公共测试 WS。现在我觉得我没有取得任何进展。因此,对于我目前的情况,我需要帮助或任何建议。

如果您使用 SoapUI 或其他方法(我尝试过 -mzeep)对其进行分析,Soap ws 会要求提供以下代码。

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://service.sunat.gob.pe">    <soapenv:Header/>    <soapenv:Body>
      <ser:sendBill>
         <!--Optional:-->
         <fileName>?</fileName>
         <!--Optional:-->
         <contentFile>?</contentFile>
         <!--Optional:-->
         <partyType>?</partyType>
      </ser:sendBill>    </soapenv:Body> </soapenv:Envelope>

但是 WS 实际上需要的是这样的 XML:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ser="http://service.sunat.gob.pe" xmlns:wsse="http://docs.oasisopen.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
    <soapenv:Header>
        <wsse:Security>
            <wsse:UsernameToken>
                <wsse:Username>?</wsse:Username>
                <wsse:Password>?</wsse:Password>
            </wsse:UsernameToken>
        </wsse:Security>
    </soapenv:Header>
    <soapenv:Body>
        <ser:sendBill>
            <fileName>?</fileName>
            <contentFile>?</contentFile>
        </ser:sendBill>
    </soapenv:Body>
</soapenv:Envelope>

作为 on 的值<contentFile>,一个以 base64 编码的 zip 文件,包含一个 XML 文件。WS 文档特别要求将此字段编码如下:

- 使用真实数据制作 XML 结构。- 将其放入 .zip - 将 .zip 编码为 base64 格式 - 最后将其附加到 XML

到目前为止,我已经将自定义 XML 发送到 WS。如果我使用 SoapUI 执行此操作,则它可以正常工作,因为它检测到我放入基于 base64 编码的 zip 中的 XML 中的无效值(它返回一个映射错误,说“无效值”)。但是,如果我尝试使用 Python 使用它,我会从该 WS 收到一条错误消息,该消息未映射到 WS 提供程序提供的错误列表中。

这是我的代码。我确实阅读了 Zeep 文档,并在 Python 的 Discord 上向人们寻求帮助。

from zeep import Client, Settings
from zeep.wsse.username import UsernameToken

import base64

with open("20100066603-01-F001-1.zip", "rb") as f:
    bytes = f.read()
    encoded = base64.b64encode(bytes)


settings = Settings(strict=False, xml_huge_tree=True)
wsdl = 'https://e-beta.sunat.gob.pe/ol-ti-itcpfegem-beta/billService?wsdl'
client = Client(wsdl=wsdl, wsse=UsernameToken('20100066603MODDATOS', 'moddatos'), settings=settings)

node = client.create_message(client.service.sendBill('20100066603-01-F001-1.zip', encoded))

# response = client.service.sendBill('20100066603-01-F001-1.zip', b'bytes')
# print(client.service.sendBill('20100066603-01-F001-1.zip', b'encoded'))
# print(client.service.sendBill('20100066603-01-F001-1.zip', encoded))
# print(encoded.decode())
print(node)

I want to know if what I am doing on python is correct. I would like to get the XML response the WS will deliver when sending that test data. (my goal is to have the same error message as when sending the request usin SoapUI) The reason I decided to use Zeep was because it was the most well documented library for SOAP request I could find. As i said before I'm new at python and I really need to consume this WS. If this is a duplicated question please let me know. Or if this question can be answered with other answered questions please link me to them. Doing some research about Zeep i noticed some people say Zeep does not like attachments (its support for attachments is not good). So i would like to know if there is another library i could use. If so, please would you kindly show me an example? If not, would you recommend me another programming language and its libraries where i can succesfully do this.This is my first question on StackO ever. BTW don't worry about the usernameToken data on the pyhthon code, that's fictional data. I did a request using Requests library and got an XML saying there was a server internal error. But i just ask the provider, and their WS is functioning normal. I could confirm this by doing a request using SoapUI and getting the error i was expecting. Sorry if it was long. Thanks in advance. Jajdp

标签: pythonsoappython-requestsattachmentzeep

解决方案


谁会想到用于将数据发送到 SOAP ws 的库通常会自动在 base64 上对您的文件进行编码。我所做的所有代码都是正确的,但只有一个部分。代替:

node = client.create_message(client.service.sendBill('20100066603-01-F001-1.zip', encoded))

它应该是

node = client.create_message(client.service.sendBill('20100066603-01-F001-1.zip', bytes))

现在脚本可以正常工作了!


推荐阅读