2017-01-08 2 views
0

У меня есть приложение PHP, работающее в Google App Engine. Я пытаюсь сделать запрос веб-службы SOAP 1.2 от клиента PHP на удаленный хост. Я получаю следующее сообщение об ошибке при создании SoapClient используя код ниже:App Engine PHP-приложение не удалось создать SoapClient

$opts = array(
      'https'=>array('user_agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36'), 
      'ssl' => array('verify_peer'=>false, 'verify_peer_name' => false) 
     ); 

$context = stream_context_create($opts); 

$params = array (
    'encoding' => 'UTF-8', 
    'verifypeer' => false, 
    'verifyhost' => false, 
    'soap_version' => SOAP_1_2, 
    'trace' => 1, 
    'exceptions' => 1, 
    'connection_timeout' => 30, 
    'stream_context' => $context, 
    'cache_wsdl' => WSDL_CACHE_MEMORY 
); 

libxml_disable_entity_loader(false); 
$client = new \SoapClient("https://<host_ip_address>/webservice.asmx?wsdl", $params); 

ошибка, что я получаю:

ERROR: SoapFault exception: [WSDL] SOAP-ERROR: Parsing WSDL: Couldn't load from '<host_ip_address>/webservice.asmx?wsdl' : failed to load external entity "<host_ip_address>/webservice.asmx?wsdl" 

Я подтвердил, что были загружены следующие модули:

php --info 

Soap Client => enabled 
... 
XML Support => active 
... 
OpenSSL support => enabled 
... 

И мой файл php.ini в корневой папке приложения содержит:

google_app_engine.enable_functions = "libxml_disable_entity_loader" 
extension = “curl.so” 

Мой проект GAE также имеет выставление счетов. Любые советы о том, что я могу сделать для успешного создания SoapClient, очень ценятся. Я могу подключиться к веб-сервису через CURL и SoapUI, поэтому я предполагаю, что нет ничего плохого в веб-сервисе.

+0

Должен ли '' заменяться фактическим IP-адресом или именем хоста сервера, на котором размещена служба SOAP? – snakecharmerb

+0

в качестве альтернативы, если вы скрываете '' от SO по соображениям конфиденциальности, можете ли вы посетить 'https: // /webservice.asmx? Wsdl' в своем веб-браузере? Он возвращает файл 'wsdl'? – snakecharmerb

+0

Привет @snakecharmerb ... Спасибо за ваши материалы. Да, я маскировал хост и ip-адрес для соображений конфиденциальности, и да, я смог получить файл wsdl, если я перейду к URL-адресу из браузера. – EthanS

ответ

0

Попробуйте это:

<?php 
declare(strict_types=1); // PHP 7.1 

class SoapAgent extends \SoapClient 
{ 
    protected const WSDL_PATH = '/webservice.asmx?wsdl'; 
    protected const USER_AGENT = 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)'; 
    protected const SOAP_TIMEOUT = 300; // Increase this value if SOAP timeouts occur. 

    // options for ssl for unverified SSL certs 
    // allow_self_signed certs 
    protected const CTX_OPTS = 
    [ 
     'http' => ['user_agent' => self::USER_AGENT], 
     'ssl' => 
     [ 
      'verify_peer' => false, // Do not verify the cert 
      'verify_peer_name' => false, // Or the name of the cert 
      'allow_self_signed' => true // Allow self signed certs 
     ] 
    ]; 


    public function __construct(string $uri) 
    { 
     assert(func_num_args() === 1); 

     /** 
     * Workaround for a particularly nasty bug that 'sometimes' 
     * creates a racing condition internally 
     * for SOAP client constructors that use OpenSSL in Ubuntu. 
     * 
     * @link: https://bugs.launchpad.net/ubuntu/+source/php5/+bug/1160336 
     * 
     */ 
     libxml_disable_entity_loader(false); 

     // Get the SOAP stream context 
     $ctx = stream_context_create(self::CTX_OPTS); 

     // SOAP 1.2 client options 
     $options = 
     [ 
      'Content-Type' => 'application/soap+xml;charset=UTF-8', 
      'encoding' => 'UTF-8', 
      'verifypeer' => false, 
      'verifyhost' => false, 
      'soap_version' => SOAP_1_2, 
      'features' => SOAP_WAIT_ONE_WAY_CALLS |  SOAP_SINGLE_ELEMENT_ARRAYS, 
      'compression' => SOAP_COMPRESSION_ACCEPT |  SOAP_COMPRESSION_GZIP | SOAP_COMPRESSION_DEFLATE, 
      'trace' => true, 
      'exceptions' => true, 
      'cache_wsdl' => WSDL_CACHE_NONE, 
      'cache_wsdl_ttl' => 0, 
      'connection_timeout' => self::SOAP_TIMEOUT, 
      'stream_context' => $ctx 
     ]; 

     // Even though we pass these in as option settings (above) -- sometimes 
     // they are being ignored so we force this into the INI settings as well. 
     ini_set('soap.wsdl_cache_enabled', (string)$options['cache_wsdl']); 
     ini_set('soap.wsdl_cache_ttl', (string)$options['cache_wsdl_ttl']); 
     ini_set('default_socket_timeout', (string)$options['connection_timeout']); 

     // Set the file path for where we are going to store the WSDL. 
     $wsdlFile = sys_get_temp_dir() . '/' . $uri . '.wsdl'; 

     // Format the uri by affixing `https://` to the uri 
     $uri = "https://{$uri}/" . self::WSDL_PATH; 

     // We perform our own WSDL caching in case there are errors we can actually look at the file itself. 
     $wsdlXML = null; 

     // Does the WSDL file already exist? 
     if (!file_exists($wsdlFile)) { 

      // Download the WSDL for the URI provided 
      $wsdlXML = file_get_contents($uri, false, $options['stream_context']); 

      // If we had trouble getting the WSDL then the URI from the user is probably bad. 
      if (!isset($wsdlXML) || $wsdlXML === false || !is_string($wsdlXML)) { 
       new \Exception('Unable to load WSDL from: '. $uri); 
      } 

       // Save the WSDL file. 
       file_put_contents($wsdlFile, $wsdlXML); 
      } 


      // Call the PHP internal constructor for this using the downloaded file 
      // to perform the actual WDSL configuration. 
      parent::__construct($wsdlFile, $options); 
    } 
} 

Вы должны быть в состоянии сделать это:

$soapClient = new SoapAgent('<host_ip_address>');

Примечание: Код PHP 7.1, но должно быть достаточно легко санк вниз к другой версия.

Смежные вопросы