Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invoking WCF service with PHP (with federated security)

Tags:

I’m trying to invoke a WCF service (.NET) from PHP. It’s a little more complicated than just using a SoapClient since the service uses a WS2007FederationHttpBinding to authenticate.

Here’s the code I’m using at the moment. I haven’t even added credentials as I’m not sure how, but regardless, I’m not even at the point where I’m getting access denied errors.

$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);
  1. Which WSDL should I be pointing to?

    • https://slc.centershift.com/Sandbox40/StoreService.svc?wsdl
      Seems to be very short, but includes a reference to (note the wsdl0) https://slc.centershift.com/Sandbox40/StoreService.svc?wsdl=wsdl0
    • https://slc.centershift.com/Sandbox40/StoreService.svc?singleWsdl
      Seems to have everything in it.
  2. Do I need to specify SOAP 1.2? When I do, I get a connection timeout ([HTTP] Error Fetching http headers). When I don’t, the default of SOAP 1.1 is used and I get a [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'. Is this because I’m not authenticated yet, or because I’m using the wrong SOAP version?

  3. How to authenticate in PHP? Here’s the corresponding .NET/C# code. Do I need to somehow put these as SOAP headers? Or am I thinking about it all wrong, and I need to do some kind of authentication before I even call the method (from what I read, I’m supposed to get a token back and then use it for all future method calls – I think I see an example of this in an answer here on Stack Overflow.

If I call $client->__getFunctions(), using either WSDL and either SOAP version, I’m getting a valid list of all functions, so I assume either of these is fine and my real issue is the authentication.

Other programmers I’ve talked to had spent time trying to get this to work, but gave up and instead implemented a proxy in .NET. They pass their parameters from PHP to their own unsecured .NET service, which in turn calls this secure service. It works, but seems crazily inefficient to me, and counter-productive, as the purpose of WCF is to support all types of clients (even non-HTTP ones!).

I’ve read How to: Create a WSFederationHttpBinding on MSDN, but it didn’t help.

like image 986
Shane N Avatar asked Oct 01 '15 16:10

Shane N


2 Answers

  1. You can use this URL for WSDL https://slc.centershift.com/Sandbox40/StoreService.svc?singleWsdl. This WSDL has all definitions.

  2. You have to use 1.2 because this webservice works with SOAP 1.2 version. I tried it with 1.1 and 1.2 and both of them gived error. 1.1 is version error, 1.2 is timeout error. I think there is an error at this test server. I used it with svcutil to generate code but it gived error too. Normaly it should get information and generate the code example to call service.

  3. Normally you can add authenticate parameters with SoapHeader or directly add to options in SoapClient consruct (if service authentication is basic authentication). I write below code according to your screenshot. But it gives timeout after long wait.

    $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 works, because it prints functions defined in WSDL. There is no problem with getting WSDL information at first call. But real problem is communication. PHP gets WSDL, generates required SOAP request then sends to server, but server is not responding correctly. SOAP server always gives a response even if parameters or request body are not correct.

    You should communicate with service provider, I think they can give clear answer to your questions.

like image 182
lazek Avatar answered Sep 19 '22 12:09

lazek


Having worked with consuming .NET WS from PHP before I believe you would need to create objects from classes in PHP that matches the names that .NET is expecting. The WSDL should tell you the types it is expecting. I hope this assist with your path forward!

like image 33
Brad Thomas Avatar answered Sep 19 '22 12:09

Brad Thomas