如何使用 SoapClient 类进行 PHP SOAP 调用

我习惯于编写 PHP 代码,但并不经常使用面向对象的代码。我现在需要与 SOAP (作为一个客户端)交互,但是不能正确地使用语法。我有一个 WSDL 文件,它允许我使用 SoapClient 类正确地设置一个新连接。但是,我无法实际进行正确的调用并获得返回的数据。我需要发送以下(简化)数据:

  • 联系方式
  • 联络人姓名
  • 概述
  • 金额

WSDL 文档中定义了两个函数,但是我只需要一个(下面的“ FirstFunction”)。下面是我为了获得可用函数和类型的信息而运行的脚本:

$client = new SoapClient("http://example.com/webservices?wsdl");
var_dump($client->__getFunctions());
var_dump($client->__getTypes());

下面是它产生的输出:

array(
[0] => "FirstFunction Function1(FirstFunction $parameters)",
[1] => "SecondFunction Function2(SecondFunction $parameters)",
);


array(
[0] => struct Contact {
id id;
name name;
}
[1] => string "string description"
[2] => string "int amount"
}

假设我想用数据调用 FirstFunction:

  • 联系人编号: 100
  • 联系人: 约翰
  • 一般描述: 油桶
  • 数额: 500

正确的语法是什么?我一直在尝试各种各样的选择,但它似乎肥皂结构是相当灵活的,所以有很多方法这样做。从手册上也看不出来。


更新1: 来自 MMK 的试用样品:

$client = new SoapClient("http://example.com/webservices?wsdl");


$params = array(
"id" => 100,
"name" => "John",
"description" => "Barrel of Oil",
"amount" => 500,
);
$response = $client->__soapCall("Function1", array($params));

但是我得到了这样的回答: Object has no 'Contact' property。正如您在 getTypes()的输出中看到的,有一个称为 Contactstruct,所以我想我需要在某种程度上说明我的参数包括 Contact 数据,但问题是: 如何?

更新2: 我也尝试了这些结构,同样的错误。

$params = array(
array(
"id" => 100,
"name" => "John",
),
"Barrel of Oil",
500,
);

还有:

$params = array(
"Contact" => array(
"id" => 100,
"name" => "John",
),
"description" => "Barrel of Oil",
"amount" => 500,
);

两种情况下都有错误: 对象没有“ Contact”属性

470957 次浏览

首先初始化 webservices:

$client = new SoapClient("http://example.com/webservices?wsdl");

然后设置并传递参数:

$params = array (
"arg0" => $contactid,
"arg1" => $desc,
"arg2" => $contactname
);


$response = $client->__soapCall('methodname', array($params));

请注意,方法名称在 WSDL 中可以作为操作名称使用,例如:

<operation name="methodname">

你需要一个多维数组,你可以试试下面的方法:

$params = array(
array(
"id" => 100,
"name" => "John",
),
"Barrel of Oil",
500
);

在 PHP 中,数组是一种结构,非常灵活。通常,对于肥皂调用,我使用 XML 包装器,因此不确定它是否能正常工作。

编辑:

您可能需要尝试创建一个 json 查询来发送或使用该查询创建一个 xml 购买排序,类似于本页中的内容: http://onwebdev.blogspot.com/2011/08/php-converting-rss-to-json.html

如果您创建 SoapParam 的对象,这将解决您的问题。创建一个类并将其与 WebService 给出的对象类型映射,初始化值并发送请求。参见下面的示例。

struct Contact {


function Contact ($pid, $pname)
{
id = $pid;
name = $pname;
}
}


$struct = new Contact(100,"John");


$soapstruct = new SoapVar($struct, SOAP_ENC_OBJECT, "Contact","http://soapinterop.org/xsd");


$ContactParam = new SoapParam($soapstruct, "Contact")


$response = $client->Function1($ContactParam);

阅读此文; -

Http://php.net/manual/en/soapclient.call.php

或者

对于 SOAP 函数“ _ _ call”,这是一个很好的例子。 然而,它是不被推崇的。

<?php
$wsdl = "http://webservices.tekever.eu/ctt/?wsdl";
$int_zona = 5;
$int_peso = 1001;
$cliente = new SoapClient($wsdl);
print "<p>Envio Internacional: ";
$vem = $cliente->__call('CustoEMSInternacional',array($int_zona, $int_peso));
print $vem;
print "</p>";
?>

您需要声明类 合同

class Contract {
public $id;
public $name;
}


$contract = new Contract();
$contract->id = 100;
$contract->name = "John";


$params = array(
"Contact" => $contract,
"description" => "Barrel of Oil",
"amount" => 500,
);

或者

$params = array(
$contract,
"description" => "Barrel of Oil",
"amount" => 500,
);

然后

$response = $client->__soapCall("Function1", array("FirstFunction" => $params));

或者

$response = $client->__soapCall("Function1", $params);

这就是你需要做的。

我试图重现当时的情景。


  • 对于这个示例,我创建了一个.NET 示例 WebService (WS) ,其中的 WebMethod称为 Function1,预期参数如下:

Function1(Contact Contact,字符串描述,int amount)

  • 其中 Contact只是一个模型,其中包含 idname的读取器和设置器,就像在您的例子中一样。

  • 您可以从以下网址下载.NET 示例 WS:

Https://www.dropbox.com/s/6pz1w94a52o5xah/11593623.zip


密码。

这是在 PHP 端需要做的事情:

(测试和工作)

<?php
// Create Contact class
class Contact {
public function __construct($id, $name)
{
$this->id = $id;
$this->name = $name;
}
}


// Initialize WS with the WSDL
$client = new SoapClient("http://localhost:10139/Service1.asmx?wsdl");


// Create Contact obj
$contact = new Contact(100, "John");


// Set request params
$params = array(
"Contact" => $contact,
"description" => "Barrel of Oil",
"amount" => 500,
);


// Invoke WS method (Function1) with the request params
$response = $client->__soapCall("Function1", array($params));


// Print WS response
var_dump($response);


?>

测试整个过程。

  • 如果执行 print_r($params),您将看到以下输出,正如 WS 所期望的那样:

数组([ Contact ] = > Contact Object ([ id ] = > 100[ name ] = > John) [描述] = > 油桶[数量] = > 500)

  • 当我调试.NET 示例 WS 时,我得到了以下结果:

enter image description here

(如您所见,Contact对象既不是 null也不是其他参数。这意味着从 PHP 端成功完成了请求)

  • 来自.NET 示例 WS 的响应是预期的,这是我在 PHP 方面得到的结果:

Object (stdClass)[3] public‘ Function1Result’= > string‘ Detail 你的要求的信息! id: 100,姓名: 约翰,描述: 桶 油量: 500’(长度 = 98)


您也可以这样使用 SOAP 服务:

<?php
//Create the client object
$soapclient = new SoapClient('http://www.webservicex.net/globalweather.asmx?WSDL');


//Use the functions of the client, the params of the function are in
//the associative array
$params = array('CountryName' => 'Spain', 'CityName' => 'Alicante');
$response = $soapclient->getWeather($params);


var_dump($response);


// Get the Cities By Country
$param = array('CountryName' => 'Spain');
$response = $soapclient->getCitiesByCountry($param);


var_dump($response);

这是一个具有实际服务的示例,它在 url 启动时工作。

以防 http://www.webservicex.net坏了。

下面是 使用示例 Web 服务的另一个例子,从 W3C XML Web 服务的例子中,你可以找到更多关于链接的信息。

<?php
//Create the client object
$soapclient = new SoapClient('https://www.w3schools.com/xml/tempconvert.asmx?WSDL');


//Use the functions of the client, the params of the function are in
//the associative array
$params = array('Celsius' => '25');
$response = $soapclient->CelsiusToFahrenheit($params);


var_dump($response);


// Get the Celsius degrees from the Farenheit
$param = array('Fahrenheit' => '25');
$response = $soapclient->FahrenheitToCelsius($param);


var_dump($response);

这正在工作并返回转换后的温度值。

我不知道为什么我的 Web 服务具有与您相同的结构,但它不需要 Class 参数,只是数组。

例如: 我的 WSDL:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns="http://www.kiala.com/schemas/psws/1.0">
<soapenv:Header/>
<soapenv:Body>
<ns:createOrder reference="260778">
<identification>
<sender>5390a7006cee11e0ae3e0800200c9a66</sender>
<hash>831f8c1ad25e1dc89cf2d8f23d2af...fa85155f5c67627</hash>
<originator>VITS-STAELENS</originator>
</identification>
<delivery>
<from country="ES" node=””/>
<to country="ES" node="0299"/>
</delivery>
<parcel>
<description>Zoethout thee</description>
<weight>0.100</weight>
<orderNumber>10K24</orderNumber>
<orderDate>2012-12-31</orderDate>
</parcel>
<receiver>
<firstName>Gladys</firstName>
<surname>Roldan de Moras</surname>
<address>
<line1>Calle General Oraá 26</line1>
<line2>(4º izda)</line2>
<postalCode>28006</postalCode>
<city>Madrid</city>
<country>ES</country>
</address>
<email>gverbruggen@kiala.com</email>
<language>es</language>
</receiver>
</ns:createOrder>
</soapenv:Body>
</soapenv:Envelope>

I var _ dump:

var_dump($client->getFunctions());
var_dump($client->getTypes());

结果如下:

array
0 => string 'OrderConfirmation createOrder(OrderRequest $createOrder)' (length=56)


array
0 => string 'struct OrderRequest {
Identification identification;
Delivery delivery;
Parcel parcel;
Receiver receiver;
string reference;
}' (length=130)
1 => string 'struct Identification {
string sender;
string hash;
string originator;
}' (length=75)
2 => string 'struct Delivery {
Node from;
Node to;
}' (length=41)
3 => string 'struct Node {
string country;
string node;
}' (length=46)
4 => string 'struct Parcel {
string description;
decimal weight;
string orderNumber;
date orderDate;
}' (length=93)
5 => string 'struct Receiver {
string firstName;
string surname;
Address address;
string email;
string language;
}' (length=106)
6 => string 'struct Address {
string line1;
string line2;
string postalCode;
string city;
string country;
}' (length=99)
7 => string 'struct OrderConfirmation {
string trackingNumber;
string reference;
}' (length=71)
8 => string 'struct OrderServiceException {
string code;
OrderServiceException faultInfo;
string message;
}' (length=97)

所以在我的代码里:

    $client  = new SoapClient('http://packandship-ws.kiala.com/psws/order?wsdl');


$params = array(
'reference' => $orderId,
'identification' => array(
'sender' => param('kiala', 'sender_id'),
'hash' => hash('sha512', $orderId . param('kiala', 'sender_id') . param('kiala', 'password')),
'originator' => null,
),
'delivery' => array(
'from' => array(
'country' => 'es',
'node' => '',
),
'to' => array(
'country' => 'es',
'node' => '0299'
),
),
'parcel' => array(
'description' => 'Description',
'weight' => 0.200,
'orderNumber' => $orderId,
'orderDate' => date('Y-m-d')
),
'receiver' => array(
'firstName' => 'Customer First Name',
'surname' => 'Customer Sur Name',
'address' => array(
'line1' => 'Line 1 Adress',
'line2' => 'Line 2 Adress',
'postalCode' => 28006,
'city' => 'Madrid',
'country' => 'es',
),
'email' => 'test.ceres@yahoo.com',
'language' => 'es'
)
);
$result = $client->createOrder($params);
var_dump($result);

但是成功了!

首先,使用 肥皂水从 wsdl 创建肥皂项目。尝试发送一个请求来处理 wsdl 的操作。观察 xml 请求如何组合数据字段。

然后,如果在让 SoapClient 按照您的要求运行时遇到问题,以下是我如何调试它的方法。设置选项 Trace,这样函数 _ _ getLastRequest ()就可以使用了。

$soapClient = new SoapClient('http://yourwdsdlurl.com?wsdl', ['trace' => true]);
$params = ['user' => 'Hey', 'account' => '12345'];
$response = $soapClient->__soapCall('<operation>', $params);
$xml = $soapClient->__getLastRequest();

然后,$xml变量包含 SoapClient 为您的请求编写的 xml。将这个 xml 与 SoapUI 中生成的 xml 进行比较。

对我来说,SoapClient 似乎忽略了关联数组 $帕兰姆斯的键,并将其解释为索引数组,从而导致 xml 中的参数数据错误。也就是说,如果我在 $帕兰姆斯中重新排序数据,$回应是完全不同的:

$params = ['account' => '12345', 'user' => 'Hey'];
$response = $soapClient->__soapCall('<operation>', $params);

有一个用 WsdlInterpreter 类生成 php5对象的选项

例如:

require_once 'WSDLInterpreter-v1.0.0/WSDLInterpreter.php';
$wsdlLocation = '<your wsdl url>?wsdl';
$wsdlInterpreter = new WSDLInterpreter($wsdlLocation);
$wsdlInterpreter->savePHP('.');

我也有过同样的问题,但是我只是像这样包装了参数,现在它起作用了。

    $args = array();
$args['Header'] = array(
'CustomerCode' => 'dsadsad',
'Language' => 'fdsfasdf'
);
$args['RequestObject'] = $whatever;


// this was the catch, double array with "Request"
$response = $this->client->__soapCall($name, array(array( 'Request' => $args )));

使用此功能:

 print_r($this->client->__getLastRequest());

您可以根据自己的参数查看请求 XML 是否在更改。

在 SoapClient 选项中使用[ trace = 1,eption = 0]。

GetLastRequest () :

此方法只有在创建 SoapClient 对象时跟踪选项设置为 TRUE 时才有效。

在这种情况下,TRUE 由1表示

$wsdl = storage_path('app/mywsdl.wsdl');
try{


$options = array(
// 'soap_version'=>SOAP_1_1,
'trace'=>1,
'exceptions'=>1,
               

'cache_wsdl'=>WSDL_CACHE_NONE,
//   'stream_context' => stream_context_create($arrContextOptions)
);
// $client = new \SoapClient($wsdl, array('cache_wsdl' => WSDL_CACHE_NONE) );
$client = new \SoapClient($wsdl, array('cache_wsdl' => WSDL_CACHE_NONE));
$client     = new \SoapClient($wsdl,$options);

下面的代码可能会有帮助

    $wsdl ='My_WSDL_Service.wsdl";
$options = array(
'login' => 'user-name',
'password' => 'Password',
);
try {
$client = new SoapClient($wsdl, $options);
$params = array(
'para1' => $para1,
'para2' => $para2
);
$res = $client->My_WSDL_Service($params);