介绍
显然,这里缺少文档。不幸的是,$soapClient->__getTypes()
并没有说太多。它只显示 Web 服务支持的可用复杂类型,但没有显示它们之间的关系。即使您有所有可用操作的列表及其返回的输入和输出类型$soapClient->__getFunctions()
,也不能保证您可以在不知道复杂类型的确切性质或没有任何类型的文档的情况下继续进行。但幸运的是,这是一个提供 WSDL 文档的基于 SOAP 的 Web 服务。WSDL 文档描述了所有支持的操作和复杂类型,以及它们之间的关系。因此,我们只需检查 WSDL 文档就可以了解如何使用该服务。
检查 WSDL 文档有两种方法:
- 从 WSDL 文档生成工件(客户端类)并检查工件
- 查看 WSDL 文档和 XML Schema 文档。
1. 神器
工件可以由 Java 或 C# 等强类型语言提供的工具生成。https://qa-api.ukmail.com/Services/UKMAuthenticationServices/页面建议使用该工具svcutil.exe
为 C# 编程语言生成工件,或者您也可以使用该wsimport
工具为 Java 编程语言生成工件。我怀疑是否有任何好的工具可以为 PHP 编程语言生成工件。
2. WSDL 文档和 XML Schemas
如果您不熟悉 C# 或 Java,您始终可以通过查看 WSDL 文档和 XML Schemas 来检查它。XML 模式可以包含在 WSDL 文档中或从外部文件导入。WSDL 文档描述了可以在 Web 服务上执行的操作,而 XML 模式描述了复杂的类型及其关系。
行动
我写了介绍部分,以便您知道如何自己做。下面我想展示一个例子。为了检查 WSDL 文档,我使用了两种方法。首先,我使用该wsimport
工具生成了工件,然后我阅读了很多 XML。
import
此服务的 WSDL 文档使用语句分为几个文件。因此,为了找到所有操作和复杂类型,您必须遵循这些import
语句。
验证
如果我们查看 Authentication Service 的 WSDL 文档(location),我们可以看到它导入了另一个 WSDL 文档:
<wsdl:import namespace="http://tempuri.org/" location="https://qa-api.ukmail.com/Services/UKMAuthenticationServices/UKMAuthenticationService.svc?wsdl=wsdl1"/>
后者(location)又导入另一个:
<wsdl:import namespace="http://www.UKMail.com/Services/Contracts/ServiceContracts" location="https://qa-api.ukmail.com/Services/UKMAuthenticationServices/UKMAuthenticationService.svc?wsdl=wsdl0"/>
最后一个(location),导入所有相关的 XML Schema:
<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()
操作接受$parameters
typeLogin
作为其参数并返回 type 的响应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
,它也是一个复杂的类型LoginWebRequest
,在另一个导入的 XML Schema 中进行了描述:
<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
更简单。它有两种简单的类型Username
和Password
类型String
。
在 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
的 typeArrayOfAccountWebModel
和AuthenticationToken
of typeString
元素,以及另外三个继承自type 、of type和of typeUKMWebResponse
的元素(注意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>
在该工具生成的工件中,wsimport
它看起来像这样:
public class UKMLoginResponse extends UKMWebResponse { ... }
因此,为了从 中获取身份验证令牌LoginResponse
,我们执行以下操作:
$LoginResponse = $soapClient->Login($Login);
$AuthenticationToken = $LoginResponse->LoginResult->AuthenticationToken;
调用方法
我不会在这里很具体,因为它与我们上面所做的非常相似。
例如,让我们调用一个AddDomesticConsignment()
方法。根据寄售服务的 WSDL 文档,$soapClient->__getFunctions()
该AddDomesticConsignment()
方法返回的结果采用一个$parameters
type 的参数,AddDomesticConsignment
并返回一个 type 的结果AddDomesticConsignmentResponse
。通过分析AddDomesticConsignment
复杂类型,我们看到它有一个名为request
类型的元素AddDomesticConsignmentWebRequest
extendsAddConsignmentWebRequest
本身 extends 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
请注意,并非所有元素都是必需的。那些可选的minOccurs
属性0
在 XML Schema 中设置为。
<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
解析为我们根据LoginResponse
XML Schema 文档中的定义解析 。
好吧,我想这就是全部。我自己没有尝试过,但理论上它应该可以工作。希望这可以帮助。
更新
根据跟踪货物的文件,应该像执行以下操作一样简单:
// 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
}
就是这样!