2

我是 SOAP WSDL 函数的新手。我有一个客户,他从一家从事汽车测试的公司获得了一个 wsdl 文件。我的客户是他们的分包商。他们告诉我们上传关于车牌、类别等的信息,一旦发送了详细信息,服务器就会有成功或失败的响应。请协助。

浏览不同的信息,我尝试执行以下操作,但无法正常工作

    <?php
$data = array('1'=>'value','2'=>'value','3'=>'value','4'='value','5'=>'value');
$wsdl ='http://181.24.80.32/ws/services/servicename';
$client = new SoapClient($wsdl); 
$response = $client->servicenamerequest($data);  

echo $response->servicenamereturn;  
    ?>
4

2 回答 2

3

首先:如果您正在处理未知的 Soap 服务,请获取SoapUI 。SoapUI 将读取 WSDL 文件,并允许您查看与 Soap 方法、参数和返回值相关的几乎所有内容(如果您敢于调用实时服务 - 希望有一个沙箱服务器不做任何关键的事情)。

但是 SoapUI 可以通过创建一个模拟服务来帮助您,该服务接收您的请求并以您准备的预设请求进行响应。以下是我在不触及实际服务的情况下从您链接的 WSDL 到工作代码示例的方法。

设置 SoapUI

在 SoapUI 中创建一个新项目并给出 WSDL 的位置。你可以命名这个项目。

SoapUI 然后读取 WSDL 的内容并创建包含所有描述的请求的项目。之后,您会看到服务提供了哪些方法,以及必须将哪些类型的参数输入其中,就像一棵树一样。打开这棵树将为检测到的每个方法提供“请求 1”,它在免费版本中显示一些 XML(付费版本更适合填写表格),如下所示(来自vehiclePassedTest方法):

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tr="http://tr.gov.tp.stp.ws.PassedVehicleTestService">
   <soapenv:Header>
      <tr:password>?</tr:password>
      <tr:username>?</tr:username>
   </soapenv:Header>
   <soapenv:Body>
      <tr:vehiclePassedTest>
         <chassisNo>?</chassisNo>
         <plateNo>?</plateNo>
         <plateCode>?</plateCode>
         <plateCategory>?</plateCategory>
         <plcEmiCode>?</plcEmiCode>
         <currentUserName>?</currentUserName>
      </tr:vehiclePassedTest>
   </soapenv:Body>
</soapenv:Envelope>

问号是您必须提供数据的地方。此请求结构必须由您使用 PHP 的 SoapClient 创建。

让我们嘲笑一下。模拟意味着 SoapUI 启动它自己的接受请求的 Soap 服务器。它通常在 127.0.0.1:8080 上运行。右键单击项目“PassedVehicleTestService”并选择“New MockService”。接受名称,按确定。

右键单击要模拟的方法。选择“添加到模拟服务”并选择上一步中创建的。回答“是”以打开模拟响应编辑器。在那里,您可以看到答案的 XML 结构,以及服务将填写的数据的问号。此服务的所有响应都允许将一个答案作为字符串,因此请编写一些将返回的好东西。如果需要,您可以稍后将其他方法添加到此服务。

右键单击“MockService 1”并选择“开始最小化”。这将启动 Soap 服务器,它将等待传入的请求。

为模拟设置 PHP SoapClient。

你需要知道两件事。首先是 WSDL 的位置。该文件包含用于请求的真实服务器的地址,但 PHP 允许覆盖它。因此,您需要的第二个信息是正在运行的模拟服务的地址。

SoapUI 在请求编辑器中显示来自 WSDL 的地址。在您的情况下http://181.24.80.32/ws/services/PassedVehicleTestService- 模拟服务运行在http://127.0.0.1:8080/ws/services/PassedVehicleTestService- IP 和端口被替换,路径被保留。

这导致 PHP 代码的第一行:

$options = array(
    'location' => 'http://127.0.0.1:8080/ws/services/PassedVehicleTestService',
);

$client = new SoapClient("http://www.quickregistration.ae/temp/PassedVehicleTestService.xml", $options);

之后,您有一个配置好的 SoapClient 能够与您的模拟服务对话。如果稍后您想使用真正的服务,请将带有“位置”的行从数组中删除,如果您碰巧添加了一些配置参数,请保留其他配置参数。

与模拟对话

有了客户端,你就可以做到$client->nameOfSoapMethod(paramStructure)。参数结构通常是数组或对象和标量值(如字符串)的混合。所以这就是我首先尝试的:

$result = $client->vehiclePassedTest(array());
var_dump($result);

然后我查看 SoapUI 看看会发生什么。php脚本的输出:

Notice: Array to string conversion in [...]/soap.php on line 20
string(1) "?"

SoapUI 说:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://tr.gov.tp.stp.ws.PassedVehicleTestService">
    <SOAP-ENV:Body>
        <ns1:vehiclePassedTest>
            <chassisNo>Array</chassisNo>
            <plateNo/>
            <plateCode/>
            <plateCategory/>
            <plcEmiCode/>
            <currentUserName/>
        </ns1:vehiclePassedTest>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

那不是正确的做法。该数组被转换为字符串“Array”,并作为第一个参数放置。其余为空。很好,因为我知道soap 调用可能接受不止一个参数,这就是这些服务之一。

$result = $client->vehiclePassedTest('chassisNo', 'plateNo', 'plateCode', 'plateCategory', 'plcEmiCode', 'currentUserName');

这在 SoapUI 中正确显示,但标题仍然缺失。

将 SoapHeader 添加到请求中

SoapClient 提供了一个名为 的方法__setSoapHeaders(),并且有一个类SoapHeader

描述说 setSoapHeaders() 接受一个 SoapHeader 对象或一组 SoapHeader 对象。让我们创建一个,传递它,看看会发生什么:

$username = new SoapHeader();
$client->__setSoapHeaders($username);
$result = $client->vehiclePassedTest('chassisNo', 'plateNo', 'plateCode', 'plateCategory', 'plcEmiCode', 'currentUserName');
var_dump($result);

PHP 说:Warning: SoapHeader::SoapHeader() expects at least 2 parameters, 0 given

$username = new SoapHeader('namespace', 'username', 'MyUserName');

这行得通。SoapUI 说:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://tr.gov.tp.stp.ws.PassedVehicleTestService" xmlns:ns2="namespace">
    <SOAP-ENV:Header>
        <ns2:username>MyUserName</ns2:username>
    </SOAP-ENV:Header>
    <SOAP-ENV:Body>
        <ns1:vehiclePassedTest><chassisNo>chassisNo</chassisNo><plateNo>plateNo</plateNo><plateCode>plateCode</plateCode><plateCategory>plateCategory</plateCategory><plcEmiCode>plcEmiCode</plcEmiCode><currentUserName>currentUserName</currentUserName></ns1:vehiclePassedTest>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

请注意 SOAP-ENV:Envelope 元素中的两个 xmlns 属性。原始请求要求用户名位于命名空间“tr”中——但“tr”只是定义为“xlmns:tr”的字符串的快捷方式——后面的字符串是您需要的命名空间(尽管它可能已经使用真正的服务)。

$username = new SoapHeader("http://tr.gov.tp.stp.ws.PassedVehicleTestService", 'username', 'myUser');
$password = new SoapHeader("http://tr.gov.tp.stp.ws.PassedVehicleTestService", 'password', 'yetAnotherPassword');
$client->__setSoapHeaders(array($username, $password));

如您所见,这正确定义了标题:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://tr.gov.tp.stp.ws.PassedVehicleTestService">
    <SOAP-ENV:Header>
        <ns1:username>myUser</ns1:username>
        <ns1:password>yetAnotherPassword</ns1:password>
    </SOAP-ENV:Header>
    <SOAP-ENV:Body>
        <ns1:vehiclePassedTest><chassisNo>chassisNo</chassisNo><plateNo>plateNo</plateNo><plateCode>plateCode</plateCode><plateCategory>plateCategory</plateCategory><plcEmiCode>plcEmiCode</plcEmiCode><currentUserName>currentUserName</currentUserName></ns1:vehiclePassedTest>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

信封元素中没有两个命名空间,每个元素都属于命名空间“ns1”。这应该有效。

您的最终代码:

$options = array(
    'location' => 'http://127.0.0.1:8080/ws/services/PassedVehicleTestService',
);

$client = new SoapClient("http://www.quickregistration.ae/temp/PassedVehicleTestService.xml", $options);

$username = new SoapHeader("http://tr.gov.tp.stp.ws.PassedVehicleTestService", 'username', 'myUser');
$password = new SoapHeader("http://tr.gov.tp.stp.ws.PassedVehicleTestService", 'password', 'yetAnotherPassword');
$client->__setSoapHeaders(array($username, $password));

$result = $client->vehiclePassedTest('chassisNo', 'plateNo', 'plateCode', 'plateCategory', 'plcEmiCode', 'currentUserName');

var_dump($result);
于 2012-12-15T17:32:53.937 回答
1

try something like this. Works for me.

try {
  $client = new SoapClient("http://wsdl",  array('trace' => 1));
  $data = $client->someFunction(array('parma1' => 'value1', 'param2' => 'value2'));
  print_r($data);
} catch (SoapFault $fault) {
   trigger_error("SOAP Fault: (faultcode: {$fault->faultcode}, faultstring: {$fault->faultstring})", E_USER_ERROR);
   exit();
}

And check is you have installed php-soap package in your server.

Greatings.

于 2012-12-15T15:07:49.240 回答