【问题标题】:php soap client How to change namespace prefix?php soap client 如何更改命名空间前缀?
【发布时间】:2017-01-12 10:21:50
【问题描述】:

我想通过soup客户端发送这样的xml:

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:hot="http://TekTravel/HotelBookingApi">
   <soap:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
      <hot:Credentials UserName="test" Password="test@123"/>
      <wsa:Action>http://test/HotelBookingApi/CountryListRequest</wsa:Action>
      <wsa:To>http://api.test.in/HotelAPI_V7/HotelService.svc</wsa:To>
   </soap:Header>

   <soap:Body>
      <hot:CountryListRequest/>
   </soap:Body>
</soap:Envelope>

但它会像这样发送 xml:

<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:ns1="http://TekTravel/HotelBookingApi">
    <env:Header>
        <ns1:Credentials UserName="test" Password="test@123"/>
        <ns1:Action>http://test/HotelBookingApi/HotelSearch</ns1:Action>
        <ns1:To>http://api.test.in/HotelAPI_V7/HotelService.svc</ns1:To>
    </env:Header>
    <env:Body>
        <ns1:CountryListRequest/>
    </env:Body>
</env:Envelope>

api 需要与第一个完全相同的 xml。我使用 Laravel 5.2,这是我的代码:

<?php

namespace App\Model\Hotel;

use Illuminate\Database\Eloquent\Model;

use SoapClient;
use SoapHeader;
use SoapVar;

class HotelTBO extends Model
{

    //Credentials
    var $Credentials = ['UserName' => 'test', 'Password' => 'test@123'];

    //WSDL
    var $wsdl = 'http://api.tbotechnology.in/HotelAPI_V7/HotelService.svc?wsdl';

    //Actions
    var $ActionHotelSearch = "http://TekTravel/HotelBookingApi/HotelSearch";

    //NS
    var $NS = "http://TekTravel/HotelBookingApi";

    //TO
    var $ToHotelSearch = "http://api.tbotechnology.in/HotelAPI_V7/HotelService.svc";

    public function testSearch()
    {

        $client = new SoapClient(public_path('\assets\file\TBO.wsdl'), array('soap_version' => SOAP_1_2, 'trace' => 1, "exceptions" => 0));


        $HeaderVar = new SoapVar($this->HeaderXML, XSD_ANYXML, null, null, null);

        $Headers[] = new SoapHeader($this->NS, "Credentials", $this->Credentials,false);
        $Headers[] = new SoapHeader($this->NS, "Action", $this->ActionHotelSearch);
        $Headers[] = new SoapHeader($this->NS, "To", $this->ToHotelSearch);

        $client->__setSoapHeaders($Headers);
        $result = $client->__soapCall('CountryList', []);


    }

有一个名为https://github.com/BeSimple/BeSimpleSoap 的包,但没有任何相关文档。 非常感谢您的帮助

【问题讨论】:

  • 您是否尝试过手动构建 XML 字符串并用您的变量替换字符串中的凭据?我有同样的问题,在我最终构建 XML 字符串并使用 CURL 发布之前,我尝试了一堆处理 WSDL 服务的包。
  • 是的,我现在就是这样做的
  • 如果 XML 不完全相同,会报错吗?命名空间前缀本质上只是变量,所以无论使用什么它都应该起作用。
  • 是的 api 不匹配错误

标签: php xml soap laravel-5 soap-client


【解决方案1】:

使用nusoap参数必须配置

https://github.com/pwnlabs/nusoap

添加全局命名空间

$client-&gt;namespaces['tem'] = "http://tempuri.org/";

并为元素添加本地命名空间

 $dom  = new \DOMDocument('1.0');
            $document = $dom->createElement('tem:CAV_GET_DATA');
            $document = $dom->appendChild($document);
            $el = $dom->createElement("tem:UsuarioID", '111');
            $document->appendChild($el);
            $el = $dom->createElement("tem:Password", '111');
            $document->appendChild($el);
            $el = $dom->createElement("tem:idEmpleado", 111);
            $document->appendChild($el);
            $param = $dom->saveXML($dom->documentElement, LIBXML_NOEMPTYTAG);

示例完成

 $client = new nusoap_client('urlexamplee?WSDL', 'wsdl');
            $client->soap_defencoding = 'UTF-8';
            $client->response_timeout = 300
            $namespaces['tem'] = "http://tempuri.org/";

$dom  = new \DOMDocument('1.0');
                $document = $dom->createElement('tem:CAV_GET_DATA');
                $document = $dom->appendChild($document);
                $el = $dom->createElement("tem:UsuarioID", '111');
                $document->appendChild($el);
                $el = $dom->createElement("tem:Password", '111');
                $document->appendChild($el);
                $el = $dom->createElement("tem:idEmpleado", 111);
                $document->appendChild($el);
                $param = $dom->saveXML($dom->documentElement, LIBXML_NOEMPTYTAG);

 $responseService = $this->client->call(
                'CAV_GET_DATA',
                $param

            );

请求

<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tem="http://tempuri.org/" xmlns:ns6704="tem"><SOAP-ENV:Body><tem:CAV_GET_DATA><tem:UsuarioID>example</tem:UsuarioID><tem:Password>example</tem:Password><tem:idEmpleado>000000</tem:idEmpleado></tem:CAV_GET_DATA></SOAP-ENV:Body></SOAP-ENV:Envelope>

【讨论】:

    【解决方案2】:

    这是仅使用 PHP SOAP 客户端无法实现的。

    【讨论】:

      【解决方案3】:

      您在发送请求时收到什么错误?使用此代码:

      public function testSearch()
      {
      
          $client = new SoapClient($this->wsdl, array('soap_version' => SOAP_1_2, 'trace' => 1, "exceptions" => 0));
          $cred_ns = 'http://TekTravel/HotelBookingApi';
          $action_ns = 'http://www.w3.org/2005/08/addressing';
      
          $credentialHeader = ['UserName' => 'test', 'Password' => 'test@123'];
          $actionHeader = 'http://TekTravel/HotelBookingApi/CountryList';
          $toHeader = 'http://api.test.in/HotelAPI_V7/HotelService.svc';
      
          $Headers[] = new SoapHeader($cred_ns, 'Credentials', $credentialHeader , false);
          $Headers[] = new SoapHeader($action_ns, "Action", $actionHeader, false);
          $Headers[] = new SoapHeader($action_ns, "To", $toHeader, false);
      
          $client->__setSoapHeaders($Headers);
          $result = $client->__soapCall('CountryList', []);
          print_r($client->__getLastRequest());
          echo PHP_EOL;
          print_r($result);
      }
      

      我收到如下请求:

      <?xml version="1.0" encoding="UTF-8"?>
      <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:ns1="http://TekTravel/HotelBookingApi" xmlns:ns2="http://www.w3.org/2005/08/addressing">
         <env:Header>
            <ns1:Credentials UserName="test" Password="test@123"/>
            <ns2:Action>http://TekTravel/HotelBookingApi/CountryList</ns2:Action>
            <ns2:To>http://api.test.in/HotelAPI_V7/HotelService.svc</ns2:To>
          </env:Header>
          <env:Body>
              <ns1:CountryListRequest/>
          </env:Body>
      </env:Envelope>
      

      结果是授权错误: 标准类对象

      (
      [Status] => stdClass Object
          (
              [StatusCode] => 02
              [Description] => LoginErr: Login Failed.
          )
      )
      

      【讨论】:

      • 获取有关拒绝投票的原因的信息对我来说非常有用,以避免将来出现此类错误。
      • 我认为是因为您没有直接回答问题:“如何更改命名空间前缀”?如果您知道如何在 PHP 中执行此操作,请更改您的答案。您生成的 XML 仍然具有 OP 试图摆脱的相同命名空间前缀。
      • 哦,我明白了。谢谢您的回答。但是,由于我收到旧命名空间的授权错误(不是 api 不匹配错误),我建议问题可能出在其他地方,而不是在命名空间中。
      猜你喜欢
      • 2011-08-19
      • 2021-01-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多