无法从WSDL手动编写简单的SOAP请求

时间:2016-02-24 05:06:03

标签: xml web-services soap wsdl salesforce

我正在编写基于Salesforce的Web应用程序的客户端(iOS,Swift),我需要通过SOAP访问自定义API。

我正在努力手工组装基于我从服务器端收到的WSDL的XML请求。

我对XML / SOAP完全缺乏经验,现在才刚刚开始了解整个WSDL的内容。我已阅读thisthis以及其他介绍性在线文档,但我仍在努力掌握所有新概念。

由于保密原因(暴露我的网络应用程序的内部),我不愿意使用任何在线自动生成器,如this one

这是我的WSDL的相关部分(我认为):

<definitions targetNamespace="http://soap.sforce.com/schemas/class/[WSDL_File_Name]" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"  
    xmlns="http://schemas.xmlsoap.org/wsdl/" 
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
    xmlns:tns="http://soap.sforce.com/schemas/class/[WSDL_File_Name]">

    <!-- ... -->

    <message name="executeXmlRequest">
        <part name="parameters" element="tns:executeXml" />
    </message>

    <!-- ... -->

    <binding name="[WSDL_File_Name]Binding" type="tns:[WSDL_File_Name]PortType">
        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
        <operation name="executeXml">
            <soap:operation soapAction=""/>
                <input>
                    <soap:header use="literal" part="SessionHeader" message="tns:Header"/>
                    <soap:header use="literal" part="CallOptions" message="tns:Header"/>
                    <soap:header use="literal" part="DebuggingHeader" message="tns:Header"/>
                    <soap:header use="literal" part="AllowFieldTruncationHeader" message="tns:Header"/>
                    <soap:body use="literal" parts="parameters"/>
                </input>
                <output>
                    <!-- skipped -->
                </output>
        </operation>
    </binding>
<service name="[WSDL_File_Name]Service">
    <documentation></documentation>
        <port binding="tns:[WSDL_File_Name]Binding" name="[WSDL_File_Name]">
            <soap:address location="https://XXX.salesforce.com/services/Soap/class/[WSDL_File_Name]"/>
        </port>
 </service>

(我已经混淆了 [WSDL_File_Name] - WSDL文件的名称,它也作为前缀出现在这里和那里。)

特别是我无法理解消息部分:

<message name="executeXmlRequest">
    <part name="parameters" element="tns:executeXml" />
</message>

在我在网络上找到的大多数示例中(例如herehere),通常是name="body"不是 {{1} }),所以我不确定如何将其转换为实际的SOAP请求的XML主体。我试过这个请求主体:

"parameters"

...但我得到“参数1不能为空”错误回复:

<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:enterprise.soap.sforce.com">
    <soapenv:Header>
        <urn:SessionHeader>
            <urn:sessionId>[My OAuth 2.0 Token]</urn:sessionId>
        </urn:SessionHeader>
    </soapenv:Header>
    <soapenv:Body>
        <tns:executeXml xmlns:tns="http://soap.sforce.com/schemas/class/[WSDL_File_Name]">

        <!-- PAYLOAD HERE (more XML) -->

        </tns:executeXml>
    </soapenv:Body>
</soapenv:Envelope>

(同样,特定于应用程序的类名/等在方括号中混淆)

所以,我的请求主体应该是什么样的?

澄清:字符串“参数”在整个WSDL文件中出现(作为xml属性值)总共三次次:

  1. 输入讯息:<?xml version="1.0" encoding="UTF-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="http://soap.sforce.com/schemas/class/[WSDL_File_Name]"> <soapenv:Body> <executeXmlResponse> <result> <!-- The following inline-XML came from the server with all entities escaped (e.g., "&lt;" instead of "<"); I replaced them back here for legibility. --> <?xml version="1.0" encoding="UTF-8"?> <response> <success>false</success> <exception> <typeName>System.NullPointerException</typeName> <message>Argument 1 cannot be null</message> <stackTrace>Class.[Inbound_Service_Class].Message.<init>: line 271, column 1 Class.[Inbound_Service_Class].parse: line 47, column 1 Class.[Inbound_Service_Class].receive: line 29, column 1 Class.[WSDL_File_Name].executeXml: line 18, column 1 </stackTrace> </exception> </response> <!-- Originally escaped entitied end here --> </result> </executeXmlResponse> </soapenv:Body> </soapenv:Envelope>
  2. 输出消息:<message name="executeXmlRequest"><part name="parameters"...
  3. 装订:<message name="executeXmlResponse"><part name="parameters"...
  4. SOLUTION:

    this answer的内容为指导并重新阅读所有文档(例如this page),我终于意识到<binding...> ... <soap:body use="literal" parts="parameters"/>...标记的内容在类型中指定我的WSDL部分(对不起,我没有在我的问题中发布这部分。类型部分很大,我完全跳过它):

    tns:executeXml

    ...所以我认为这会转换成一个带有包络体的SOAP请求:

    <xsd:element name="executeXml">
        <xsd:complexType>
         <xsd:sequence>
            <xsd:element name="reqXml" type="xsd:string" nillable="true"/>
                          <!-- ^ THIS GUY... -->
         </xsd:sequence>
        </xsd:complexType>
     </xsd:element>
    

    现在我只是获取有关我发布的XML内容的特定于应用程序的错误消息,但我可以自己解决。我似乎成功地进入了API。

    对不起@Sundar我以前没提供足够的信息。我接受了你的答案,因为它使我朝着正确的方向前进。

1 个答案:

答案 0 :(得分:2)

使用像SOAPUI这样的工具,有免费版本,将其指向WSDL并创建一个新的soap项目,然后您可以创建一个带有虚拟值的soap请求,接受它并替换为您的值。我们拥有完整的WSDL是不可能在请求xml中说明什么,这就是合同的重点。

但是你的错误似乎非常具体,你没有为特定参数发送一个空值,该参数不应为null,我认为