【问题标题】:How to post SOAP Request from PHP如何从 PHP 发布 SOAP 请求
【发布时间】:2009-01-22 22:32:33
【问题描述】:

有人知道我如何从 PHP 发布 SOAP 请求吗?

【问题讨论】:

标签: php web-services soap


【解决方案1】:

根据我的经验,事情并不是那么简单。内置的PHP SOAP client 不适用于我们必须使用的基于.NET 的SOAP 服务器。它抱怨无效的模式定义。即使 .NET 客户端与该服务器配合得很好。顺便说一句,让我声明 SOAP 互操作性是一个神话。

下一步是NuSOAP。这工作了很长一段时间。顺便说一句,看在上帝的份上,别忘了缓存 WSDL!但即使使用 WSDL 缓存,用户也抱怨这该死的东西很慢。

然后,我们决定使用纯 HTTP,组装请求并使用 SimpleXMLElemnt 读取响应,如下所示:

$request_info = array();

$full_response = @http_post_data(
    'http://example.com/OTA_WS.asmx',
    $REQUEST_BODY,
    array(
        'headers' => array(
            'Content-Type' => 'text/xml; charset=UTF-8',
            'SOAPAction'   => 'HotelAvail',
        ),
        'timeout' => 60,

    ),
    $request_info
);

$response_xml = new SimpleXMLElement(strstr($full_response, '<?xml'));

foreach ($response_xml->xpath('//@HotelName') as $HotelName) {
    echo strval($HotelName) . "\n";
}

请注意,在 PHP 5.2 中,您需要 pecl_http,因为(惊喜!)没有内置 HTTP 客户端。

使用裸 HTTP 使我们的 SOAP 请求时间提高了 30% 以上。 从那时起,我们将所有性能抱怨都重定向到服务器人员。

最后,我推荐后一种方法,而不是因为性能。我认为,一般来说,在像 PHP 这样的动态语言中,所有 WSDL/类型控制没有任何好处。您不需要花哨的库来读取和写入 XML,所有这些存根生成和动态代理。您的语言已经是动态的,SimpleXMLElement 工作得很好,而且非常易于使用。此外,您将拥有更少的代码,这总是好的。

【讨论】:

  • $REQUEST_BODY 字符串应该包含什么,你能把它也添加到示例代码中吗?
【解决方案2】:

PHP 支持 SOAP。 只需拨打电话

$client = new SoapClient($url);

连接到SoapServer,然后你就可以得到函数列表和调用函数了……

$client->__getTypes();      
$client->__getFunctions();  

$result = $client->functionName();  

了解更多http://www.php.net/manual/en/soapclient.soapclient.php

【讨论】:

  • $url 是 WSDL 文件的 URL 吗?
  • @HartleySan 是的
  • @HartleySan 是函数传入的参数应该是数组还是xml?
  • Jimmy.B,我使用 SOAP 已经有一段时间了,但我记得它需要是一个数组,它会自动为你转换。
  • 如果 WSDL 文件落后于授权怎么办? stackoverflow.com/questions/66707432/…
【解决方案3】:

我需要执行许多非常简单的 XML 请求,在阅读了@Ivan Krechetov 关于 SOAP 速度影响的评论后,我尝试了他的代码并发现 http_post_data() 没有内置到 PHP 5.2 中。我真的不想安装它,我尝试了我所有服务器上的 cURL。虽然我不知道 cURL 与 SOAP 相比有多快,但它确实很容易满足我的需求。下面是一个带有 cURL 的示例,供任何需要它的人使用。

$xml_data = '<?xml version="1.0" encoding="UTF-8" ?>
<priceRequest><customerNo>123</customerNo><password>abc</password><skuList><SKU>99999</SKU><lineNumber>1</lineNumber></skuList></priceRequest>';
$URL = "https://test.testserver.com/PriceAvailability";

$ch = curl_init($URL);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml'));
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "$xml_data");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
curl_close($ch);


print_r($output);

【讨论】:

    【解决方案4】:

    我们可以使用 PHP cURL 库来生成简单的 HTTP POST 请求。以下示例向您展示了如何使用 cURL 创建一个简单的 SOAP 请求。

    创建soap-server.php,将SOAP请求写入web文件夹中的soap-request.xml。

    We can use the PHP cURL library to generate simple HTTP POST request. The following example shows you how to create a simple SOAP request using cURL.
    
    Create the soap-server.php which write the SOAP request into soap-request.xml in web folder.
    
    
    <?php
      $HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : '';
      $f = fopen("./soap-request.xml", "w");
      fwrite($f, $HTTP_RAW_POST_DATA);
      fclose($f);
    ?>
    
    
    The next step is creating the soap-client.php which generate the SOAP request using the cURL library and send it to the soap-server.php URL.
    
    <?php
      $soap_request  = "<?xml version=\"1.0\"?>\n";
      $soap_request .= "<soap:Envelope xmlns:soap=\"http://www.w3.org/2001/12/soap-envelope\" soap:encodingStyle=\"http://www.w3.org/2001/12/soap-encoding\">\n";
      $soap_request .= "  <soap:Body xmlns:m=\"http://www.example.org/stock\">\n";
      $soap_request .= "    <m:GetStockPrice>\n";
      $soap_request .= "      <m:StockName>IBM</m:StockName>\n";
      $soap_request .= "    </m:GetStockPrice>\n";
      $soap_request .= "  </soap:Body>\n";
      $soap_request .= "</soap:Envelope>";
    
      $header = array(
        "Content-type: text/xml;charset=\"utf-8\"",
        "Accept: text/xml",
        "Cache-Control: no-cache",
        "Pragma: no-cache",
        "SOAPAction: \"run\"",
        "Content-length: ".strlen($soap_request),
      );
    
      $soap_do = curl_init();
      curl_setopt($soap_do, CURLOPT_URL, "http://localhost/php-soap-curl/soap-server.php" );
      curl_setopt($soap_do, CURLOPT_CONNECTTIMEOUT, 10);
      curl_setopt($soap_do, CURLOPT_TIMEOUT,        10);
      curl_setopt($soap_do, CURLOPT_RETURNTRANSFER, true );
      curl_setopt($soap_do, CURLOPT_SSL_VERIFYPEER, false);
      curl_setopt($soap_do, CURLOPT_SSL_VERIFYHOST, false);
      curl_setopt($soap_do, CURLOPT_POST,           true );
      curl_setopt($soap_do, CURLOPT_POSTFIELDS,     $soap_request);
      curl_setopt($soap_do, CURLOPT_HTTPHEADER,     $header);
    
      if(curl_exec($soap_do) === false) {
        $err = 'Curl error: ' . curl_error($soap_do);
        curl_close($soap_do);
        print $err;
      } else {
        curl_close($soap_do);
        print 'Operation completed without any errors';
      }
    ?>
    
    
    Enter the soap-client.php URL in browser to send the SOAP message. If success, Operation completed without any errors will be shown and the soap-request.xml will be created.
    
    <?xml version="1.0"?>
    <soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope" soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
      <soap:Body xmlns:m="http://www.example.org/stock">
        <m:GetStockPrice>
          <m:StockName>IBM</m:StockName>
        </m:GetStockPrice>
      </soap:Body>
    </soap:Envelope>
    
    
    Original - http://eureka.ykyuen.info/2011/05/05/php-send-a-soap-request-by-curl/
    

    【讨论】:

      【解决方案5】:

      您可能想查看herehere

      第一个链接中的一个小代码示例:

      <?php
      // include the SOAP classes
      require_once('nusoap.php');
      // define parameter array (ISBN number)
      $param = array('isbn'=>'0385503954');
      // define path to server application
      $serverpath ='http://services.xmethods.net:80/soap/servlet/rpcrouter';
      //define method namespace
      $namespace="urn:xmethods-BNPriceCheck";
      // create client object
      $client = new soapclient($serverpath);
      // make the call
      $price = $client->call('getPrice',$param,$namespace);
      // if a fault occurred, output error info
      if (isset($fault)) {
              print "Error: ". $fault;
              }
      else if ($price == -1) {
              print "The book is not in the database.";
      } else {
              // otherwise output the result
              print "The price of book number ". $param[isbn] ." is $". $price;
              }
      // kill object
      unset($client);
      ?>
      

      【讨论】:

        【解决方案6】:

        下面是我在this website 找到的如何执行此操作的快速示例(它最好地向我解释了这个问题)。该网站链接还解释了 WSDL,这对于使用 SOAP 服务很重要。

        但是,我认为他们在以下示例中使用的 API 地址仍然无效,因此只需切换您自己选择的一个即可。

        $wsdl = 'http://terraservice.net/TerraService.asmx?WSDL';
        
        $trace = true;
        $exceptions = false;
        
        $xml_array['placeName'] = 'Pomona';
        $xml_array['MaxItems'] = 3;
        $xml_array['imagePresence'] = true;
        
        $client = new SoapClient($wsdl, array('trace' => $trace, 'exceptions' => $exceptions));
        $response = $client->GetPlaceList($xml_array);
        
        var_dump($response);
        

        【讨论】:

          【解决方案7】:

          如果 XML 在不同级别具有相同名称的身份,则有一个解决方案。您不必提交原始 XML(此 PHP SOAP 对象不允许发送原始 XML),因此您必须始终将 XML 转换为数组,如下例所示:

          $originalXML = "
          <xml>
            <firstClient>
                <name>someone</name>
                <adress>R. 1001</adress>
            </firstClient>
            <secondClient>
                <name>another one</name>
                <adress></adress>
            </secondClient>
          </xml>"
          
          //Translate the XML above in a array, like PHP SOAP function requires
          $myParams = array('firstClient' => array('name' => 'someone',
                                            'adress' => 'R. 1001'),
                      'secondClient' => array('name' => 'another one',
                                            'adress' => ''));
          
          $webService = new SoapClient($someURL);
          $result = $webService->someWebServiceFunction($myParams);
          

          $soapUrl = "http://privpakservices.schenker.nu/package/package_1.3/packageservices.asmx?op=SearchCollectionPoint";
          
          $xml_post_string = '<?xml version="1.0" encoding="utf-8"?><soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope"><soap12:Body><SearchCollectionPoint xmlns="http://privpakservices.schenker.nu/"><customerID>XXX</customerID><key>XXXXXX-XXXXXX</key><serviceID></serviceID><paramID>0</paramID><address>RiksvŠgen 5</address><postcode>59018</postcode><city>Mantorp</city><maxhits>10</maxhits></SearchCollectionPoint></soap12:Body></soap12:Envelope>';
          
          $headers = array(
          "POST /package/package_1.3/packageservices.asmx HTTP/1.1",
          "Host: privpakservices.schenker.nu",
          "Content-Type: application/soap+xml; charset=utf-8",
          "Content-Length: ".strlen($xml_post_string)
          ); 
          
          $url = $soapUrl;
          
          $ch = curl_init();
          curl_setopt($ch, CURLOPT_URL, $url);
          curl_setopt($ch, CURLOPT_POST, true);
          curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_post_string);
          curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
          curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
          
          $response = curl_exec($ch); 
          curl_close($ch);
          
          $response1 = str_replace("<soap:Body>","",$response);
          $response2 = str_replace("</soap:Body>","",$response1);
          
          $parser = simplexml_load_string($response2);
          

          【讨论】:

          • +1 表示 $headers 变量的内容长度部分。另外,您可以添加一件事,即“SOAPAction:xxxx.xxx.com/xxxxx
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多