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协议都可以。

基本结构

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
复制代码<?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元素的第一个子元素

1
2
3
4
5
复制代码<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。

基本结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
复制代码<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中的类型系统)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
复制代码<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所定义的类型来定义整个消息的数据结构。

1
2
3
复制代码<wsdl:message name="receiveB2COrder"> 
    <wsdl:part element="tns:receiveB2COrder" name="parameters"/>
  </wsdl:message>

Operation & PortType

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

1
2
3
4
5
6
7
复制代码<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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
复制代码<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 相关服务访问点的集合。

1
2
3
4
5
复制代码<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操作示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
复制代码//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示例全文:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
复制代码<?xml version="1.0" encoding="utf-8"?>
 
<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%