Подтвердить что ты не робот

Вызов службы WCF с помощью PHP (с интегрированной безопасностью)

Я пытаюсь вызвать службу WCF (.NET) из PHP. Это немного сложнее, чем просто использовать SoapClient, поскольку служба использует WS2007FederationHttpBinding для аутентификации.

Вот код, который я использую в данный момент. Я даже не добавил учетные данные, поскольку я не уверен, как, но независимо, я даже не в том месте, где я получаю доступ к отказам в ошибках.

$wsdl = "https://slc.centershift.com/sandbox40/StoreService.svc?wsdl";
$client = new SoapClient($wsdl,array(
         //'soap_version'=>SOAP_1_2 // default 1.1, but this gives 'Uncaught SoapFault exception: [HTTP] Error Fetching http headers'
        ));
$params = array();
$params['SiteID'] = 123;
$params['GetPromoData'] = false;

$ret = $client->GetSiteUnitData(array('GetSiteUnitData_Request'=>$params));
print_r($ret);
  • На какой WSDL я должен указывать?

  • Нужно ли указывать SOAP 1.2? Когда я это сделаю, я получаю таймаут соединения ([HTTP] Error Fetching http headers). Когда я не использую, используется значение по умолчанию для SOAP 1.1, и я получаю [HTTP] Cannot process the message because the content type 'text/xml; charset=utf-8' was not the expected type 'application/soap+xml; charset=utf-8'. Это потому, что я еще не аутентифицирован, или потому, что я использую неправильную версию SOAP?

  • Как проверить подлинность в PHP? Имеет соответствующий код .NET/С#. Нужно ли мне как-то ставить их как заголовки SOAP? Или я думаю о том, что все это неправильно, и мне нужно сделать некоторую аутентификацию, прежде чем я даже вызову метод (из того, что я прочитал, я должен был получить токен назад, а затем использовать его для всех будущих вызовов метода - я думаю, что я см. пример этого в ответе здесь о переполнении стека.

Если я вызываю $client->__getFunctions(), используя либо WSDL, либо SOAP-версию, Im получает список всех функций, поэтому я предполагаю, что это одно из них, и моя настоящая проблема - это аутентификация.

Другие программисты, с которыми я говорил, потратили время, пытаясь заставить это работать, но отказались и вместо этого внедрили прокси в .NET. Они передают свои параметры с PHP на свою незащищенную службу .NET, которая, в свою очередь, вызывает этот безопасный сервис. Он работает, но кажется безумно неэффективным для меня и контрпродуктивным, поскольку цель WCF заключается в поддержке всех типов клиентов (даже не-HTTP-протоколов!).

Я прочитал Как создать WSFederationHttpBinding в MSDN, но он не помог.

4b9b3361

Ответ 1

Проработав с использованием .NET WS от PHP, прежде чем я полагаю, что вам нужно будет создавать объекты из классов в PHP, которые соответствуют именам, ожидаемым .NET. WSDL должен рассказать вам о типах, которые он ожидает. Я надеюсь, что это поможет вашему пути!

Ответ 2

  • Вы можете использовать этот URL для WSDL https://slc.centershift.com/Sandbox40/StoreService.svc?singleWsdl. Этот WSDL имеет все определения.

  • Вы должны использовать 1.2, потому что этот веб-сервис работает с версией SOAP 1.2. Я попробовал его с 1.1 и 1.2, и обе они дали ошибку. 1.1 - ошибка версии, 1.2 - ошибка таймаута. Я думаю, что на этом тестовом сервере есть ошибка. Я использовал его с svcutil для генерации кода, но он тоже ошибся. Нормальный он должен получать информацию и генерировать пример кода для вызова службы.

  • Обычно вы можете добавлять параметры аутентификации с помощью SoapHeader или напрямую добавлять в опции в SoapClient consruct (если аутентификация службы является базовой аутентификацией). Я пишу ниже код в соответствии с вашим снимком экрана. Но он дает время ожидания после долгого ожидания.

    $wsdl = "https://slc.centershift.com/sandbox40/StoreService.svc?wsdl";
    $client = new SoapClient($wsdl,array('trace' => 1,'soap_version'   => SOAP_1_2));
    
    $security = array(
    'UserName' => array(
        'UserName'=>'TestUser',
        'Password'=>'TestPassword',
        'SupportInteractive'=>false
     )
    );
    
    $header = new SoapHeader('ChannelFactory','Credentials',$security, false);
    $client->__setSoapHeaders($header);
    
    
    
    $params = array();
    $params['SiteID'] = 100000000;
    $params['Channel'] = 999;
    try {
        $ret = $client->GetSiteUnitData($params);
        print_r($ret);
    }catch(Exception $e){
      echo $e->getMessage();
    }
    

    __getFunctions работает, потому что он печатает функции, определенные в WSDL. Нет никакой проблемы с получением информации WSDL при первом вызове. Но реальной проблемой является общение. PHP получает WSDL, генерирует требуемый SOAP-запрос, затем отправляет сервер, но сервер не отвечает правильно. Сервер SOAP всегда дает ответ, даже если параметры или тело запроса неверны.

    Вам следует связаться с поставщиком услуг, я думаю, что они могут дать четкий ответ на ваши вопросы.

Ответ 3

Если вызов SOAP работает из приложения С#, вы можете использовать Wireshark (с фильтром ip.dst == 204.246.130.80), чтобы просмотреть фактический запрос, а затем построить аналогичный запрос с php.

Отметьте этот ответ, чтобы узнать, как вы можете выполнить пользовательский вызов SOAP.

Также есть возможность делать сырые запросы на завивки, так как может быть проще создать ваше тело xml, но тогда вам придется самостоятельно проанализировать ответ с помощью simplexml.