SOAP与WSDL详解

SOAP是我们Web Service中很常见的一个协议,SOAP确定了一种通过XML实现跨语言、跨机器传输调用的协议,WSDL更像是所提供服务的一个规范、一个文档,本篇文章介绍梳理一下他们的规则与逻辑,更好的认识一下SOAP协议及WSDL描述文件。

SOAP简单对象访问协议

SOAP(Simple Object Access Protocol)简单对象访问协议是交换数据的一种规范,在Web Service中,交换带结构信息。可基于HTTP等协议,使用XML格式传输,抽象于语言实现、平台和硬件。即多语言包括PHP、Java、.Net均可支持。

优点是跨语言,非常适合异步通信和针对松耦合的C/S,缺点是必须做很多运行时检查。

相关概念

  • SOAP封装(envelop),定义了一个框架,描述消息中的内容是什么,是谁发送的,谁应当接受并处理。
  • SOAP编码规则(encoding rules),定义了一种序列化的机制,表示应用程序需要使用的数据类型的实例。
  • SOAP RPC表示(RPC representation),定义了一个协定,用于表示远程过程调用和应答。
  • SOAP绑定(binding),定义了SOAP使用哪种协议交换信息。使用HTTP/TCP/UDP协议都可以。

基本结构

示例:

<?xml version="1.0"?>
<soap:Envelope
    xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
    soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">

    <soap:Header>
      ...
      ...
    </soap:Header>

    <soap:Body>
          ...
          ...
          <soap:Fault>
            ...
            ...
          </soap:Fault>
    </soap:Body>
</soap:Envelope>

一条SOAP消息就是一个普通的XML文档,Envelope元素与Body元素(包含调用和响应信息)必须存在,Header元素(包含头部信息)和Fault元素(提供有关在处理此消息所发生的错误的信息)可以作为可选存在

SOAP Envelope元素

SOAP消息的根元素,可把XML文档定义为SOAP消息

命名空间

xmlns:SOAP命名空间,固定不变。

SOAP在默认命名空间中定义了3个属性:actor,mustUnderstand,encodingStyle。这些被定义在SOAP头部的属性可定义容器如何对SOAP消息进行处理。

  • mustUnderstand属性——用于标识标题项对其进行处理的接受者来说是强制的还是可选的。(0可选1强制)soap:mustUnderstand="0/1"
  • SOAP的actor属性可用于将Header元素寻址到一个特定的端点 soap:actor="URI"
  • SOAP的encodingStyle属性用于定义在文档中使用的数据类型。此属性可出现在任何SOAP元素中,并会被应用到元素的内容及元素的所有子元素上。SOAP消息没有默认的编码方式。soap:encodingstyle="URI"

SOAP Header元素

可选的SOAP Header元素可包含有关SOAP消息的应用程序专用信息。如果Header元素被提供,则它必须是Envelope元素的第一个子元素

<soap:Header>
   <m:Trans xmlns:m="http://www.w3schools.com/transaction/"
    soap:mustUnderstand="1">234 #表示处理此头部的接受者必须认可此元素,假如此元素接受者无法认可此元素,则在处理此头部时必须失效
   </m:Trans>
</soap:Heaser>

SOAP Body元素

必须的SOAP Body元素可包含打算传送到消息最终端点的实际SOAP消息。SOAP Body元素的直接子元素可以使合格的命名空间

SOAP Fault元素

用于存留SOAP消息的错误和状态消息,可选的SOAP Fault元素用于指示错误消息。如果已提供了Fault元素,则它必须是Body元素的子元素,在一条SOAP消息中,Fault元素只能出现一次。

SOAP Fault子元素:

  • 供识别障碍的代码
  • 可供人阅读的有关障碍的说明
  • 有关是谁引发故障的信息
  • 存留涉及Body元素的应用程序的专用错误信息

faultcode值描述:

  • versionMismatch SOAP Envelope的无效命名空间被发现
  • mustUnderstand Header元素的一个直接子元素(mustUnderstand=”1′)无法被理解
  • Client 消息被不正确的构成,或包含不正确的信息
  • Server 服务器有问题,因此无法处理进行下去

WSDL网络服务描述语言

WSDL(Web Services Description Language)网络服务描述语言,WSDL 是一种使用 XML 编写的文档。这种文档可描述某个 Web Service。

基本结构

<definitions>
    <types>
       definition of types........
    </types>
    <message>
       definition of a message....
    </message>
    <portType>
       definition of a port.......
    </portType>
    <binding>
       definition of a binding....
    </binding>
</definitions>

一个WSDL文档通常包含7个重要的元素,即types、import、message、portType、operation、binding、service元素。这些元素嵌套在definitions元素中,definitions是WSDL文档的根元素。

特定实例剖析

以盛付通的一个接口为例,介绍一下整个wsdl描述文件,网址如下http://cardpay.shengpay.com/api-acquire-channel/services/receiveOrderService?wsdl

Types

数据类型定义的容器,它使用某种类型系统(一般地使用XML Schema中的类型系统)。

<xs:element name="receB2COrderRequest" type="tns:ReceB2COrderRequest"/>  
<xs:element name="receB2COrderResponse" type="tns:ReceB2COrderResponse"/>

<xs:complexType name="ReceB2COrderRequest"> 
    <xs:sequence> 
      <xs:element minOccurs="0" name="buyerContact" type="xs:string"/>  
      .......
    </xs:sequence> 
</xs:complexType>  

<xs:complexType name="receiveB2COrder"> 
        <xs:sequence> 
          <xs:element minOccurs="0" name="arg0" type="tns:ReceB2COrderRequest"/> 
        </xs:sequence> 
</xs:complexType>  

Message

通信消息的数据结构的抽象类型化定义。使用Types所定义的类型来定义整个消息的数据结构。

<wsdl:message name="receiveB2COrder"> 
    <wsdl:part element="tns:receiveB2COrder" name="parameters"/> 
  </wsdl:message> 

Operation & PortType

Operation 对服务中所支持的操作的抽象描述,一般单个Operation描述了一个访问入口的请求/响应消息对。
PortType 对于某个访问入口点类型所支持的操作的抽象集合,这些操作可以由一个或多个服务访问点来支持。

<wsdl:portType name="ReceiveOrderAPI"> 
    <wsdl:operation name="receiveB2COrder"> 
      <wsdl:input message="tns:receiveB2COrder" name="receiveB2COrder"/>  
      <wsdl:output message="tns:receiveB2COrderResponse" name="receiveB2COrderResponse"/>  
      <wsdl:fault message="tns:MasAPIException" name="MasAPIException"/> 
    </wsdl:operation> 
  </wsdl:portType>  

Binding

特定端口类型的具体协议和数据格式规范的绑定。

<wsdl:binding name="ReceiveOrderAPIExplorterServiceSoapBinding" type="tns:ReceiveOrderAPI"> 
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>  
    <wsdl:operation name="receiveB2COrder"> 
      <soap:operation soapAction="" style="document"/>  
      <wsdl:input name="receiveB2COrder"> 
        <soap:body use="literal"/> 
      </wsdl:input>  
      <wsdl:output name="receiveB2COrderResponse"> 
        <soap:body use="literal"/> 
      </wsdl:output>  
      <wsdl:fault name="MasAPIException"> 
        <soap:fault name="MasAPIException" use="literal"/> 
      </wsdl:fault> 
    </wsdl:operation> 
  </wsdl:binding>  

Port&Service

Port 定义为协议/数据格式绑定与具体Web访问地址组合的单个服务访问点。
Service 相关服务访问点的集合。

<wsdl:service name="ReceiveOrderAPIExplorterService"> 
    <wsdl:port binding="tns:ReceiveOrderAPIExplorterServiceSoapBinding" name="ReceiveOrderAPIExplorterPort"> 
      <soap:address location="http://cardpay.shengpay.com/api-acquire-channel/services/receiveOrderService"/> 
    </wsdl:port> 
  </wsdl:service> 

PHP操作示例代码

//soap版本为1.1,不缓存wsdl文件
$options = array(
    'trace'=>true,
    'cache_wsdl'=>WSDL_CACHE_NONE,
    'soap_version'=> SOAP_1_1
);
//上送参数
$request = array();//do something

//准备请求
$soapClient = new SoapClient($url, $options);
try {
    $response = $soapClient->__soapCall($function, array(array('arg0'=>$request)));
    if (is_object($response)) {
        $responseArray = get_object_vars($response);
        return $responseArray;
    }
} catch (SOAPFault $e) {
    //do something
} catch(Exception $e) {
    //do something
}

小结

附wsdl示例全文:



<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://www.sdo.com/mas/api/receive/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="ReceiveOrderAPIExplorterService" targetNamespace="http://www.sdo.com/mas/api/receive/">  
  <wsdl:types> 
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" attributeFormDefault="unqualified" elementFormDefault="unqualified" targetNamespace="http://www.sdo.com/mas/api/receive/">  
      <xs:element name="receB2COrderRequest" type="tns:ReceB2COrderRequest"/>  
      <xs:element name="receB2COrderResponse" type="tns:ReceB2COrderResponse"/>  
      <xs:complexType name="ReceB2COrderRequest"> 
        <xs:sequence> 
          <xs:element minOccurs="0" name="buyerContact" type="xs:string"/>  
          <xs:element minOccurs="0" name="buyerId" type="xs:string"/>  
          <xs:element minOccurs="0" name="buyerIp" type="xs:string"/>  
          <xs:element minOccurs="0" name="buyerName" type="xs:string"/>  
          <xs:element minOccurs="0" name="cardPayInfo" type="xs:string"/>  
          <xs:element minOccurs="0" name="cardValue" type="xs:string"/>  
          <xs:element minOccurs="0" name="currency" type="xs:string"/>  
          <xs:element minOccurs="0" name="depositId" type="xs:string"/>  
          <xs:element minOccurs="0" name="depositIdType" type="xs:string"/>  
          <xs:element minOccurs="0" name="expireTime" type="xs:string"/>  
          <xs:element minOccurs="0" name="extension" type="tns:extension"/>  
          <xs:element minOccurs="0" name="header" type="tns:header"/>  
          <xs:element minOccurs="0" name="instCode" type="xs:string"/>  
          <xs:element minOccurs="0" name="language" type="xs:string"/>  
          <xs:element minOccurs="0" name="notifyUrl" type="xs:string"/>  
          <xs:element minOccurs="0" name="orderAmount" type="xs:string"/>  
          <xs:element minOccurs="0" name="orderNo" type="xs:string"/>  
          <xs:element minOccurs="0" name="orderTime" type="xs:string"/>  
          <xs:element minOccurs="0" name="pageUrl" type="xs:string"/>  
          <xs:element minOccurs="0" name="payChannel" type="xs:string"/>  
          <xs:element minOccurs="0" name="payType" type="xs:string"/>  
          <xs:element minOccurs="0" name="payeeId" type="xs:string"/>  
          <xs:element minOccurs="0" name="payerAuthTicket" type="xs:string"/>  
          <xs:element minOccurs="0" name="payerId" type="xs:string"/>  
          <xs:element minOccurs="0" name="payerMobileNo" type="xs:string"/>  
          <xs:element minOccurs="0" name="productDesc" type="xs:string"/>  
          <xs:element minOccurs="0" name="productId" type="xs:string"/>  
          <xs:element minOccurs="0" name="productName" type="xs:string"/>  
          <xs:element minOccurs="0" name="productNum" type="xs:string"/>  
          <xs:element minOccurs="0" name="productUrl" type="xs:string"/>  
          <xs:element minOccurs="0" name="sellerId" type="xs:string"/>  
          <xs:element minOccurs="0" name="signature" type="tns:signature"/>  
          <xs:element minOccurs="0" name="terminalType" type="xs:string"/>  
          <xs:element minOccurs="0" name="unitPrice" type="xs:string"/> 
        </xs:sequence> 
      </xs:complexType>  
      <xs:complexType name="extension"> 
        <xs:sequence> 
          <xs:element minOccurs="0" name="ext1" type="xs:string"/>  
          <xs:element minOccurs="0" name="ext2" type="xs:string"/>  
          <xs:element minOccurs="0" name="ext3" type="xs:string"/> 
        </xs:sequence> 
      </xs:complexType>  
      <xs:complexType name="header"> 
        <xs:sequence> 
          <xs:element minOccurs="0" name="charset" type="xs:string"/>  
          <xs:element minOccurs="0" name="sendTime" type="xs:string"/>  
          <xs:element minOccurs="0" name="sender" type="tns:sender"/>  
          <xs:element minOccurs="0" name="service" type="tns:service"/>  
          <xs:element minOccurs="0" name="traceNo" type="xs:string"/> 
        </xs:sequence> 
      </xs:complexType>  
      <xs:complexType name="sender"> 
        <xs:sequence> 
          <xs:element minOccurs="0" name="senderId" type="xs:string"/> 
        </xs:sequence> 
      </xs:complexType>  
      <xs:complexType name="service"> 
        <xs:sequence> 
          <xs:element minOccurs="0" name="serviceCode" type="xs:string"/>  
          <xs:element minOccurs="0" name="version" type="xs:string"/> 
        </xs:sequence> 
      </xs:complexType>  
      <xs:complexType name="signature"> 
        <xs:sequence> 
          <xs:element minOccurs="0" name="signMsg" type="xs:string"/>  
          <xs:element minOccurs="0" name="signType" type="xs:string"/> 
        </xs:sequence> 
      </xs:complexType>  
      <xs:complexType name="ReceB2COrderResponse"> 
        <xs:sequence> 
          <xs:element minOccurs="0" name="customerLogoUrl" type="xs:string"/>  
          <xs:element minOccurs="0" name="customerName" type="xs:string"/>  
          <xs:element minOccurs="0" name="customerNo" type="xs:string"/>  
          <xs:element minOccurs="0" name="extension" type="tns:extension"/>  
          <xs:element minOccurs="0" name="header" type="tns:header"/>  
          <xs:element minOccurs="0" name="orderAmount" type="xs:string"/>  
          <xs:element minOccurs="0" name="orderNo" type="xs:string"/>  
          <xs:element minOccurs="0" name="orderType" type="xs:string"/>  
          <xs:element minOccurs="0" name="returnInfo" type="tns:returnInfo"/>  
          <xs:element minOccurs="0" name="sessionId" type="xs:string"/>  
          <xs:element minOccurs="0" name="signature" type="tns:signature"/>  
          <xs:element minOccurs="0" name="tokenId" type="xs:string"/>  
          <xs:element minOccurs="0" name="transNo" type="xs:string"/>  
          <xs:element minOccurs="0" name="transStatus" type="xs:string"/>  
          <xs:element minOccurs="0" name="transTime" type="xs:string"/> 
        </xs:sequence> 
      </xs:complexType>  
      <xs:complexType name="returnInfo"> 
        <xs:sequence> 
          <xs:element minOccurs="0" name="errorCode" type="xs:string"/>  
          <xs:element minOccurs="0" name="errorMsg" type="xs:string"/> 
        </xs:sequence> 
      </xs:complexType>  
      <xs:element name="MasAPIException" type="tns:MasAPIException"/>  
      <xs:complexType name="MasAPIException"> 
        <xs:sequence/> 
      </xs:complexType>  
      <xs:element name="receiveB2COrder" type="tns:receiveB2COrder"/>  
      <xs:complexType name="receiveB2COrder"> 
        <xs:sequence> 
          <xs:element minOccurs="0" name="arg0" type="tns:ReceB2COrderRequest"/> 
        </xs:sequence> 
      </xs:complexType>  
      <xs:element name="receiveB2COrderResponse" type="tns:receiveB2COrderResponse"/>  
      <xs:complexType name="receiveB2COrderResponse"> 
        <xs:sequence> 
          <xs:element minOccurs="0" name="return" type="tns:ReceB2COrderResponse"/> 
        </xs:sequence> 
      </xs:complexType> 
    </xs:schema> 
  </wsdl:types>  
  <wsdl:message name="receiveB2COrder"> 
    <wsdl:part element="tns:receiveB2COrder" name="parameters"/> 
  </wsdl:message>  
  <wsdl:message name="receiveB2COrderResponse"> 
    <wsdl:part element="tns:receiveB2COrderResponse" name="parameters"/> 
  </wsdl:message>  
  <wsdl:message name="MasAPIException"> 
    <wsdl:part element="tns:MasAPIException" name="MasAPIException"/> 
  </wsdl:message>  
  <wsdl:portType name="ReceiveOrderAPI"> 
    <wsdl:operation name="receiveB2COrder"> 
      <wsdl:input message="tns:receiveB2COrder" name="receiveB2COrder"/>  
      <wsdl:output message="tns:receiveB2COrderResponse" name="receiveB2COrderResponse"/>  
      <wsdl:fault message="tns:MasAPIException" name="MasAPIException"/> 
    </wsdl:operation> 
  </wsdl:portType>  
  <wsdl:binding name="ReceiveOrderAPIExplorterServiceSoapBinding" type="tns:ReceiveOrderAPI"> 
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>  
    <wsdl:operation name="receiveB2COrder"> 
      <soap:operation soapAction="" style="document"/>  
      <wsdl:input name="receiveB2COrder"> 
        <soap:body use="literal"/> 
      </wsdl:input>  
      <wsdl:output name="receiveB2COrderResponse"> 
        <soap:body use="literal"/> 
      </wsdl:output>  
      <wsdl:fault name="MasAPIException"> 
        <soap:fault name="MasAPIException" use="literal"/> 
      </wsdl:fault> 
    </wsdl:operation> 
  </wsdl:binding>  
  <wsdl:service name="ReceiveOrderAPIExplorterService"> 
    <wsdl:port binding="tns:ReceiveOrderAPIExplorterServiceSoapBinding" name="ReceiveOrderAPIExplorterPort"> 
      <soap:address location="http://cardpay.shengpay.com/api-acquire-channel/services/receiveOrderService"/> 
    </wsdl:port> 
  </wsdl:service> 
</wsdl:definitions>

0条留言