【问题标题】:Generating XML for use with Salesforce SOAP API生成用于 Salesforce SOAP API 的 XML
【发布时间】:2023-03-28 13:49:01
【问题描述】:

我已经成功使用 Salesforce REST API 有一段时间了,但遇到了一些只能通过 SOAP API 获得的功能。一个这样的函数是convertLead() 函数。我相信我应该能够使用 Salesforce 访问令牌(a/k/a 会话 ID)来调用 SOAP API,但我没有看到一个好的库可用于此函数以及我的其他一些函数我感兴趣。

Salesforce 在此处提供示例 SOAP 请求:https://developer.salesforce.com/page/Enterprise_Convert_Lead

我尝试编写一些 convertLead() 函数,但遇到了一些错误,而且由于我是 SOAP 以及 lxml 库的新手,我不确定如何诊断。

这是我为生成 XML 而编写的类:

from lxml import etree


class SalesforceLeadConverter(object):

    def __init__(self, session_id, lead_id, **kwargs):
        self.session_id = session_id
        self.lead_id = lead_id

    def build_xml(self):
        root = etree.Element(
            "{soapenv}Envelope",
             soapenv='<a rel="nofollow" class="external free" href="http://schemas.xmlsoap.org/soap/envelope/">http://schemas.xmlsoap.org/soap/envelope/</a>',
            urn="urn:enterprise.soap.sforce.com"
            )
        soapenv = etree.SubElement(root, "{soapenv}Header")
        urn = etree.SubElement(soapenv, "{urn}SessionHeader")
        session_id = etree.SubElement(urn, "{urn}sessionId").text=self.session_id
        soapenv2 = etree.SubElement(root, "{soapenv}Body")
        urn2 = etree.SubElement(soapenv2, "{urn}convertLead")
        lead_converts = etree.SubElement(urn2, "{urn}leadConverts")
        lead_id = etree.SubElement(lead_converts, "{urn}leadId").text=self.lead_id

        print(etree.tostring(root, pretty_print=True))
        return root

这样设计是为了让我可以传入lead_id 和 session_id(访问令牌)的值并生成一些 XML,如下所示:

 >>> from integrations.salesforce.soap import SalesforceLeadConverter
 >>> slc = SalesforceLeadConverter(session_id="1q2w3e4r...", lead_id="00Qj000000PMV3h")
 >>> xml = slc.build_xml()

生成以下输出:

 <ns0:Envelope xmlns:ns0="soapenv" urn="urn:enterprise.soap.sforce.com">
    <ns0:Header>
      <ns1:SessionHeader xmlns:ns1="urn">
        <ns1:sessionId>1q2w3e4r...</ns1:sessionId>
      </ns1:SessionHeader>
    </ns0:Header>
    <ns0:Body>
      <ns2:convertLead xmlns:ns2="urn">
        <ns2:leadConverts>
          <ns2:leadId>00Qj000000PMV3h</ns2:leadId>
        </ns2:leadConverts>
      </ns2:convertLead>
    </ns0:Body>
  </ns0:Envelope>

最后,我使用requests 将 XML 数据传递到 Salesforce SOAP API 端点;我将“SOAPAction”设置为任何值(在本例中为“x”),因为 another thread 我发现建议将其设置为一些随机文本值。

>>> headers = {'Content-Type':'application/xml', 'SOAPAction':'x'}
>>> requests.post('https://na1.salesforce.com/services/Soap/c/10.0', data=xml, headers=headers)

我收到以下错误:

TypeError: data must be a memoryview, buffer or byte string

完整的错误输出在这里:https://gist.github.com/joefusaro/f3297c253beb6bba93e075d8b8da9822

【问题讨论】:

    标签: xml soap python-requests lxml


    【解决方案1】:

    您正在传递作为元素对象的根,您需要返回您正在打印的内容,即 etree.tostring(root)

    def build_xml(self):
            root = etree.Element(
                "{soapenv}Envelope",
                urn="urn:enterprise.soap.sforce.com"
                )
            soapenv = etree.SubElement(root, "{soapenv}Header")
            urn = etree.SubElement(soapenv, "{urn}SessionHeader")
            session_id = etree.SubElement(urn, "{urn}sessionId").text=self.session_id
            soapenv2 = etree.SubElement(root, "{soapenv}Body")
            urn2 = etree.SubElement(soapenv2, "{urn}convertLead")
            lead_converts = etree.SubElement(urn2, "{urn}leadConverts")
            lead_id = etree.SubElement(lead_converts, "{urn}leadId").text=self.lead_id
            return etree.tostring(root)
    

    您可能还想更改标题 = {'Content-Type':'text/xml'}

    【讨论】:

    • 谢谢,这似乎已经解决了!但是,我收到另一个 SOAP 错误,知道我做错了什么吗? &lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"&gt;&lt;soapenv:Body&gt;&lt;soapenv:Fault&gt;&lt;faultcode&gt;soapenv:VersionMismatch&lt;/faultcode&gt;&lt;faultstring&gt;The SOAP request must use SOAP 1.1, did not recieve a SOAP 1.1 Envelope as the document root&lt;/faultstring&gt;&lt;/soapenv:Fault&gt;&lt;/soapenv:Body&gt;&lt;/soapenv:Envelope
    • 我针对这个话题提出了一个新问题:stackoverflow.com/questions/39183423/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-21
    • 1970-01-01
    • 1970-01-01
    • 2011-12-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多