介绍
很显然,这里缺少文档。不幸的是,$soapClient->__getTypes()
并没有提供太多信息。它只显示Web服务支持的可用复杂类型,但它并不显示它们之间的关系。即使您拥有所有可用操作及其输入输出类型的列表,由$soapClient->__getFunctions()
返回,也无法保证您能在不知道复杂类型的确切性质或没有任何文档的情况下继续。但幸运的是,这是一个基于SOAP的Web服务,它提供了一个WSDL文档。WSDL文档描述了所有支持的操作和复杂类型以及它们之间的关系。因此,通过仅检查WSDL文档,我们就可以弄清楚如何使用该服务。
检查WSDL文档有两种方法:
- 从WSDL文档生成工件(客户端类)并检查工件
- 查看WSDL文档和XML模式文档。
1. 工件
工件可以由像Java或C#这样的强类型语言提供的工具生成。 https://qa-api.ukmail.com/Services/UKMAuthenticationServices/页面建议使用svcutil.exe
工具为C#编程语言生成工件,或者您也可以使用wsimport
工具为Java编程语言生成工件。我怀疑,对于PHP编程语言,可能没有好的工具来生成工件。
2. WSDL文档和XML模式文档
如果您不熟悉C#或Java,您始终可以通过查看WSDL文档和XML模式文档来检查WSDL文档。 XML模式文档可以包含在WSDL文档中或从外部文件导入。虽然WSDL文档描述了可以在Web服务上执行的操作,但XML模式文档描述了复杂类型及其关系。
操作
我撰写了介绍部分,以便您知道如何自行完成。下面我要展示一个示例。为了检查WSDL文档,我使用了两种方法。首先,我使用wsimport
工具生成了工件,然后阅读了很多XML。
该服务的WSDL文档使用import
语句将其分成几个文件。因此,为了找到所有操作和复杂类型,您必须遵循import
语句。
身份验证
如果我们查看认证服务的WSDL文档(位置),我们可以看到它导入了另一个WSDL文档:
<wsdl:import namespace="http://tempuri.org/" location="https://qa-api.ukmail.com/Services/UKMAuthenticationServices/UKMAuthenticationService.svc?wsdl=wsdl1"/>
后者(位置),又引入了另一个:
<wsdl:import namespace="http://www.UKMail.com/Services/Contracts/ServiceContracts" location="https://qa-api.ukmail.com/Services/UKMAuthenticationServices/UKMAuthenticationService.svc?wsdl=wsdl0"/>
最后一个(位置),导入了所有相关的XML模式:
<wsdl:types>
<xsd:schema targetNamespace="http://www.UKMail.com/Services/Contracts/ServiceContracts/Imports">
<xsd:import schemaLocation="https://qa-api.ukmail.com/Services/UKMAuthenticationServices/UKMAuthenticationService.svc?xsd=xsd0" namespace="http://www.UKMail.com/Services/Contracts/ServiceContracts"/>
<xsd:import schemaLocation="https://qa-api.ukmail.com/Services/UKMAuthenticationServices/UKMAuthenticationService.svc?xsd=xsd1" namespace="http://schemas.microsoft.com/2003/10/Serialization/"/>
<xsd:import schemaLocation="https://qa-api.ukmail.com/Services/UKMAuthenticationServices/UKMAuthenticationService.svc?xsd=xsd2" namespace="http://www.UKMail.com/Services/Contracts/DataContracts"/>
<xsd:import schemaLocation="https://qa-api.ukmail.com/Services/UKMAuthenticationServices/UKMAuthenticationService.svc?xsd=xsd3" namespace="http://schemas.datacontract.org/2004/07/UKMWebAPICommon.WebResponses"/>
</xsd:schema>
</wsdl:types>
它还描述了可以通过调用
$soapClient->__getFunctions()
查看的操作:
Array
(
[0] => LoginResponse Login(Login $parameters)
[1] => LogoutResponse Logout(Logout $parameters)
)
在这里,我们可以看到Login()
操作接受类型为Login
的$parameters
作为其参数,并返回类型为LoginResponse
的响应。在WSDL文档中,它看起来是这样的:
<wsdl:operation name="Login">
<wsdl:input wsaw:Action="http://www.UKMail.com/Services/IUKMAuthenticationService/Login" message="tns:IUKMAuthenticationService_Login_InputMessage"/>
<wsdl:output wsaw:Action="http://www.UKMail.com/Services/Contracts/ServiceContracts/IUKMAuthenticationService/LoginResponse" message="tns:IUKMAuthenticationService_Login_OutputMessage"/>
</wsdl:operation>
Login
是一个复杂类型,在其中一个导入的 XML Schema 文档(schemaLocation)中可以看到:
<xs:element name="Login">
<xs:complexType>
<xs:sequence>
<xs:element xmlns:q1="http://www.UKMail.com/Services/Contracts/DataContracts" minOccurs="0" name="loginWebRequest" nillable="true" type="q1:LoginWebRequest"/>
</xs:sequence>
</xs:complexType>
</xs:element>
它有一个名为loginWebRequest
的元素,它也是另一个导入的XML模式中描述的名为LoginWebRequest
的复杂类型:
<xs:complexType name="LoginWebRequest">
<xs:sequence>
<xs:element name="Password" nillable="true" type="xs:string"/>
<xs:element name="Username" nillable="true" type="xs:string"/>
</xs:sequence>
</xs:complexType>
LoginWebRequest
更为简单。它只有两个类型为 String
的 简单 类型 Username
和 Password
。
在 PHP 中,复杂类型由 stdClass
对象表示。因此,为了调用 Login()
操作,我们需要创建两个对象 Login
和 LoginWebRequest
:
$LoginWebRequest = new stdClass();
$LoginWebRequest->Username = 'Username';
$LoginWebRequest->Password = 'p@$$w0rd';
$Login = new stdClass();
$Login->loginWebRequest = $LoginWebRequest;
$soapClient = new SoapClient('https://qa-api.ukmail.com/Services/UKMAuthenticationServices/UKMAuthenticationService.svc?wsdl');
$LoginResponse = $soapClient->Login($Login);
这将会返回一个类型为
LoginResponse
的结果:
<xs:element name="LoginResponse">
<xs:complexType>
<xs:sequence>
<xs:element xmlns:q2="http://www.UKMail.com/Services/Contracts/DataContracts" minOccurs="0" name="LoginResult" nillable="true" type="q2:UKMLoginResponse"/>
</xs:sequence>
</xs:complexType>
</xs:element>
该段落包含一个名为LoginResult
的元素,其类型为UKMLoginResponse
:
<xs:complexType name="UKMLoginResponse">
<xs:complexContent mixed="false">
<xs:extension base="tns:UKMWebResponse">
<xs:sequence>
<xs:element minOccurs="0" name="Accounts" nillable="true" type="tns:ArrayOfAccountWebModel"/>
<xs:element name="AuthenticationToken" nillable="true" type="xs:string"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
UKMLoginResponse
有两个自己的元素Accounts
和AuthenticationToken
,类型分别为ArrayOfAccountWebModel
和String
,还继承了UKMWebResponse
的三个元素(注意extension
语句):Errors
类型为ArrayOfUKMWebError
,Warnings
类型为ArrayOfUKMWebWarning
,Result
类型为UKMResultState
:
<xs:complexType name="UKMWebResponse">
<xs:sequence>
<xs:element minOccurs="0" name="Errors" nillable="true" type="tns:ArrayOfUKMWebError"/>
<xs:element xmlns:q1="http://schemas.datacontract.org/2004/07/UKMWebAPICommon.WebResponses" name="Result" type="q1:UKMResultState"/>
<xs:element minOccurs="0" name="Warnings" nillable="true" type="tns:ArrayOfUKMWebWarning"/>
</xs:sequence>
</xs:complexType>
< p > 在由
wsimport
工具生成的工件中,它看起来像这样:
public class UKMLoginResponse extends UKMWebResponse { ... }
因此,为了从
LoginResponse
获得身份验证令牌,我们执行以下操作:
$LoginResponse = $soapClient->Login($Login);
$AuthenticationToken = $LoginResponse->LoginResult->AuthenticationToken;
调用方法
这里我不会过于具体,因为它与我们上面所做的非常相似。
以一个例子来说,让我们调用一个 AddDomesticConsignment()
方法。根据寄存服务的 WSDL 文档和 $soapClient->__getFunctions()
返回的结果,AddDomesticConsignment()
方法需要一个类型为 AddDomesticConsignment
的 $parameters
参数,并返回一个类型为 AddDomesticConsignmentResponse
的结果。通过分析 AddDomesticConsignment
复杂类型,我们可以看到它有一个名为 request
的元素,其类型为 AddDomesticConsignmentWebRequest
,该类型扩展了 AddConsignmentWebRequest
,而后者则扩展了 WebRequest
。以下是 AddDomesticConsignmentWebRequest
类型的所有元素列表:
// AddDomesticConsignmentWebRequest's own elements
boolean BookIn
decimal CODAmount
string ConfirmationEmail
string ConfirmationTelephone
boolean ExchangeOnDelivery
int ExtendedCover
boolean LongLength
PreDeliveryNotificationType PreDeliveryNotification
string SecureLocation1
string SecureLocation2
boolean SignatureOptional
// elements inhereted from AddConsignmentWebRequest
string AccountNumber
AddressWebModel Address
string AlternativeRef
string BusinessName
string CollectionJobNumber
boolean ConfirmationOfDelivery
string ContactName
string CustomersRef
string Email
int Items
int ServiceKey
string SpecialInstructions1
string SpecialInstructions2
string Telephone
decimal Weight
// elements inhereted from WebRequest
string Username
string AuthenticationToken
请注意,并非所有元素都是必需的。其中可选的元素在 XML Schema 中具有
minOccurs
属性,其设置为
0
。
<xs:element minOccurs="0" name="PreDeliveryNotification" type="tns:PreDeliveryNotificationType"/>
因此,最终我们这样调用该方法:
$AddDomesticConsignmentWebRequest = new stdClass();
$AddDomesticConsignmentWebRequest->Username = 'Username';
// setting the Authentication Token from the previous step
$AddDomesticConsignmentWebRequest->AuthenticationToken = $AuthenticationToken;
// other properties are set here...
$AddDomesticConsignment = new stdClass();
$AddDomesticConsignment->request = $AddDomesticConsignmentWebRequest;
$soapClient = new SoapClient('https://qa-api.ukmail.com/Services/UKMConsignmentServices/UKMConsignmentService.svc?wsdl');
$AddDomesticConsignmentResponse = $soapClient->AddDomesticConsignment($AddDomesticConsignment);
AddDomesticConsignmentResponse
会根据其在XML模式文件中的定义进行解析,就像我们解析
LoginResponse
一样。
好了,我想这就是全部内容了。虽然我自己没有尝试过,但理论上应该可以工作。
希望这有所帮助。
更新
根据文档,跟踪托运应该很容易,只需要执行以下操作即可:
// create the SOAP client
$soapClient = new SoapClient('http://web-service/?wsdl');
// call the `ConsignmentTrackingSearchV1` method and pass the search parameters
$ConsignmentTrackingSearchV1Response = $soapClient->ConsignmentTrackingSearchV1(
'mail.com', // Username
'123', // Password
'', // Token
'01161', // ConsignmentNumber
'false', // IsPartialConsignmentNumber
'', // CustomerReference
'false' // IsPartialCustomerReference
'', // DeliveryPostCode
'', // MailingID
100 // MaxResults
);
// parse the response
$ConsignmentTrackingSearchV1Result = $ConsignmentTrackingSearchV1Response->ConsignmentTrackingSearchV1Result;
$ResultState = $ConsignmentTrackingSearchV1Result->ResultState; // Successful
$ConsignmentResults = $ConsignmentTrackingSearchV1Result->ConsignmentResults;
// loop through the `ConsignmentResults`
foreach ($ConsignmentResults as $ConsignmentSearchResult) {
$ConsignmentNumber = $ConsignmentSearchResult->ConsignmentNumber;
$ConsignmentStatus = $ConsignmentSearchResult->ConsignmentStatus;
// other properties
}
就是这样了!
Login()
操作两次,请勿这样做;2)不要将脚本分开,第二部分依赖于第一部分的$AuthenticationToken
;3)为$AddDomesticConsignmentWebRequest
对象设置所有必需的属性。请参考文档中所需的属性;4)最好在尝试调用操作并希望得到任何合理结果之前获取您的用户名/密码。当我在CLI中尝试运行脚本时,我收到错误消息“SOAP-ERROR: Encoding: object hasn't 'ConfirmationOfDelivery' property”(见第3点)。 - zafarkhaja