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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11593623/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 00:49:46  来源:igfitidea点击:

How to make a PHP SOAP call using the SoapClient class

phpsoap

提问by Oscar Jara

I'm used to writing PHP code, but do not often use Object-Oriented coding. I now need to interact with SOAP (as a client) and am not able to get the syntax right. I've got a WSDL file which allows me to properly set up a new connection using the SoapClient class. However, I'm unable to actually make the right call and get data returned. I need to send the following (simplified) data:

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

  • Contact ID
  • Contact Name
  • General Description
  • Amount
  • 联系方式
  • 联系人姓名
  • 一般说明
  • 数量

There are two functions defined in the WSDL document, but I only need one ("FirstFunction" below). Here is the script I run to get information on the available functions and types:

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

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

And here is the output it generates:

这是它生成的输出:

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"
}

Say I want to make a call to the FirstFunction with the data:

假设我想用数据调用 FirstFunction:

  • Contact ID: 100
  • Contact Name: John
  • General Description: Barrel of Oil
  • Amount: 500
  • 联系方式:100
  • 联系人姓名:约翰
  • 一般描述:一桶油
  • 数量:500

What would be the right syntax? I've been trying all sorts of options but it appears the soap structure is quite flexible so there are very many ways of doing this. Couldn't figure it out from the manual either...

什么是正确的语法?我一直在尝试各种选择,但看起来肥皂结构非常灵活,所以有很多方法可以做到这一点。说明书上也查不出来。。。



UPDATE 1: tried sample from MMK:

更新 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));

But I get this response: Object has no 'Contact' property. As you can see in the output of getTypes(), there is a structcalled Contact, so I guess I somehow need to make clear my parameters include the Contact data, but the question is: how?

但我得到了这样的回应:Object has no 'Contact' property。正如您在 的输出中看到的getTypes(),有一个struct被调用的Contact,所以我想我需要以某种方式明确我的参数包括联系数据,但问题是:如何?

UPDATE 2: I've also tried these structures, same error.

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

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

As well as:

也:

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

Error in both cases: Object has no 'Contact' property`

两种情况下的错误:对象没有“联系人”属性

回答by Oscar Jara

This is what you need to do.

这是你需要做的。

I tried to recreate the situation...

我试图重现这种情况......



  • For this example, I created a .NET sample WebService (WS) with a WebMethodcalled Function1expecting the following params:
  • 对于此示例,我创建了一个 .NET 示例 WebService (WS),其中WebMethod调用了Function1期望以下参数的调用:

Function1(Contact Contact, string description, int amount)

功能1(联系人联系人,字符串描述,整数金额)

  • Where Contactis just a model that has getters and setters for idand namelike in your case.

  • You can download the .NET sample WS at:

  • 其中Contact仅仅是对getter和setter的模型idname像你的情况。

  • 您可以在以下位置下载 .NET 示例 WS:

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

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



The code.

编码。

This is what you need to do at PHP side:

这是您需要在 PHP 端执行的操作:

(Tested and working)

(测试和工作)

<?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);

?>


Testing the whole thing.

测试整个事情。

  • If you do print_r($params)you will see the following output, as your WS would expect:
  • 如果您这样做,print_r($params)您将看到以下输出,正如您的 WS 所期望的那样:

Array ( [Contact] => Contact Object ( [id] => 100 [name] => John ) [description] => Barrel of Oil [amount] => 500 )

Array ( [Contact] => Contact Object ( [id] => 100 [name] => John ) [description] => Barrel of Oil [amount] => 500)

  • When I debugged the .NET sample WS I got the following:
  • 当我调试 .NET 示例 WS 时,我得到以下信息:

enter image description here

在此处输入图片说明

(As you can see, Contactobject is not nullnor the other params. That means your request was successfully done from PHP side)

(如您所见,Contactobject 不是null其他参数。这意味着您的请求已从 PHP 端成功完成)

  • The response from the .NET sample WS was the expected one and this is what I got at PHP side:
  • 来自 .NET 示例 WS 的响应是预期的响应,这就是我在 PHP 端得到的响应:

object(stdClass)[3] public 'Function1Result' => string 'Detailed information of your request! id: 100, name: John, description: Barrel of Oil, amount: 500' (length=98)

object(stdClass)[3] public 'Function1Result' => string '您的请求的详细信息!id:100,姓名:John,描述:一桶油,数量:500'(长度=98)



Happy Coding!

快乐编码!

回答by Salvador P.

You can use SOAP services this way too:

您也可以这样使用 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);

This is an example with a real service, and it works.

这是一个真实服务的例子,它有效。

Hope this helps.

希望这可以帮助。

回答by MMK

First initialize webservices:

首先初始化网络服务:

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

Then set and pass the parameters:

然后设置并传递参数:

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

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

Note that the method name is available in WSDL as operation name, e.g.:

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

<operation name="methodname">

回答by Tín Ph?m

I don't know why my web service has the same structure with you but it doesn't need Class for parameter, just is array.

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

For example: - My WSDL:

例如: - 我的 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>(4o izda)</line2>
                    <postalCode>28006</postalCode>
                    <city>Madrid</city>
                    <country>ES</country>
                </address>
                <email>[email protected]</email>
                <language>es</language>
            </receiver>
        </ns:createOrder>
    </soapenv:Body>
</soapenv:Envelope>

I var_dump:

我 var_dump:

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

Here is result:

这是结果:

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)

So in my code:

所以在我的代码中:

    $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' => '[email protected]',
            'language' => 'es'
        )
    );
    $result = $client->createOrder($params);
    var_dump($result);

but it successfully!

但它成功了!

回答by Sang Nguyen

First, use SoapUIto create your soap project from the wsdl. Try to send a request to play with the wsdl's operations. Observe how the xml request composes your data fields.

首先,使用SoapUI从wsdl 创建您的soap 项目。尝试发送一个请求来玩 wsdl 的操作。观察 xml 请求如何组成您的数据字段。

And then, if you are having problem getting SoapClient acts as you want, here is how I debug it. Set the option traceso that the function __getLastRequest()is available for use.

然后,如果您在让 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();

Then the $xmlvariable contains the xml that SoapClient compose for your request. Compare this xml with the one generated in the SoapUI.

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

For me, SoapClient seems to ignore the keys of the associative array $paramsand interpret it as indexed array, causing wrong parameter data in the xml. That is, if I reorder the data in $params, the $responseis completely different:

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

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

回答by Umesh Chavan

If you create the object of SoapParam, This will resolve your problem. Create a class and map it with object type given by WebService, Initialize the values and send in the request. See the sample below.

如果您创建 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);

回答by Abid Hussain

read this;-

读这个;-

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

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

Or

或者

This is a good example, for the SOAP function "__call". However it is deprecated.

这是一个很好的例子,对于 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>";
?>

回答by Martin Zvarík

I had the same issue, but I just wrapped the arguments like this and it works now.

我遇到了同样的问题,但我只是像这样包装了参数,现在可以使用了。

    $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 )));

Using this function:

使用此功能:

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

You can see the Request XML whether it's changing or not depending on your arguments.

您可以根据您的参数查看请求 XML 是否发生变化。

Use [ trace = 1, exceptions = 0 ] in SoapClient options.

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

回答by CollinsKe

getLastRequest():

getLastRequest():

This method works only if the SoapClient object was created with the trace option set to TRUE.

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

TRUE in this case is represented by 1

在这种情况下,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); 

worked for me.

为我工作。

回答by Ramil Amerzyanov

You need declare class Contract

您需要声明类合同

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,
);

or

或者

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

Then

然后

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

or

或者

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