Я в основном новичок в SOAP, поэтому я сделал небольшой тестовый скрипт для подключения к серверу моего клиента. У них есть команда GetMessage, которая не требует ввода или аутентификации и предназначена только для проверки возможности подключения:
<?php ini_set('soap.wsdl_cache_enabled',0); ini_set('soap.wsdl_cache_ttl',0); $url = "https://test.mycustomer.com/api/TestService.svc?wsdl"; $client = new SoapClient($url, array("trace" => 1, "exception" => 0)); $result = $client->GetMessage(NULL); echo "<pre>".print_r($result, true)."</pre>"; if($result->GetMessageResult->Status == "Success") { echo "Item deleted!"; } ?>
Если я запустил это в командной строке, я получаю:
Fatal error: Uncaught SoapFault exception: [HTTP] Could not connect to host in /var/www/my.stage.com/htdocs/common/soaptest.php:8 Stack trace: #0 [internal function]: SoapClient->__doRequest('<?xml version="...', 'http://459265-d...', 'http://tempuri....', 1, 0) #1 [internal function]: SoapClient->__call('GetMessage', Array) #2 /var/www/my.stage.com/htdocs/common/soaptest.php(8): SoapClient->GetMessage(NULL) #3 {main} thrown in /var/www/my.stage.com/htdocs/common/soaptest.php on line 8
И из браузера я получаю:
PHP Notice: 'SoapClient::__doRequest() [soapclient.--dorequest]: php_network_getaddresses: getaddrinfo failed: Name or service not known'
В WSDL для этой службы здесь отображается строка «459265»:
<wsdl:service name="TestService"> <wsdl:port name="BasicHttpBinding_ITestService" binding="tns:BasicHttpBinding_ITestService"> <soap:address location="http://459265-dev1/api/TestService.svc"/> </wsdl:port> <wsdl:port name="BasicHttpsBinding_ITestService" binding="tns:BasicHttpsBinding_ITestService"> <soap:address location="https://test.mycustomer.com/api/TestService.svc"/> </wsdl:port> </wsdl:service>
Так что мой вопрос в том, что правильно? Должен ли WSDL иметь локальный URL-адрес, который я не могу получить из своей коробки?
Немного больше информации, когда я делаю var_dump на __getFunctions и __getTypes, я получаю
array(2) { [0]=> string(53) "GetMessageResponse GetMessage(GetMessage $parameters)" [1]=> string(53) "GetMessageResponse GetMessage(GetMessage $parameters)" } array(5) { [0]=> string(21) "struct GetMessage { }" [1]=> string(55) "struct GetMessageResponse { string GetMessageResult; }" [2]=> string(8) "int char" [3]=> string(17) "duration duration" [4]=> string(11) "string guid" }
Что вы хотите сделать, это обернуть свой код в блок try{}, catch{}
. Например,
<?php try { ini_set('soap.wsdl_cache_enabled',0); ini_set('soap.wsdl_cache_ttl',0); $url = "https://test.mycustomer.com/api/TestService.asmx?wsdl"; $client = new SoapClient($url, array("trace" => 1, "exception" => 0)); $result = $client->GetMessage(NULL); echo "<pre>".print_r($result, true)."</pre>"; if($result->GetMessageResult->Status == "Success") { echo "Item deleted!"; } } catch (SoapFault $exception) { echo $exception->getMessage(); } ?>
Как говорится в ошибке, Fatal error: Uncaught SoapFault exception: [HTTP] Could not connect to host in ....
, поэтому вам нужно поймать исключение в любом случае. Надеюсь это поможет.
Решили, частично. Проблема заключается в объявлении службы wsdl, где у него есть два порта для одной и той же привязки (см. Выше). В SoapClient php $ location для __doRequest исходит из первого привязки (простите меня, если я использую неправильную терминологию), а url для этого – локальный url, который недоступен для меня. Поэтому я сделал это:
class MySoapClient extends SoapClient { public function __doRequest($request, $location, $action, $version, $one_way = 0) { $response = parent::__doRequest($request, "https://test.mycustomer.com/api/TestService.svc", $action, $version, $one_way); return($response); } }
Расширение SoapClient и переопределение __doRequest, я смог установить $ location в URL, который, как я знал, будет работать. Рань снова и получил приветственное сообщение – yipee! Не отличное решение, так как мне пришлось бы расширять новый клиент для каждой службы, но чтобы исправить все, что мне нужно сделать, это вынуть жесткий код, заменить локальный домен в $ location внешним доменом, а затем позвонить __doRequest с этим, и он будет работать со всеми службами.