2015-10-01 39 views
19

Sto provando a richiamare un servizio WCF (.NET) da PHP. È un po 'più complicato del semplice utilizzo di un SoapClient poiché il servizio utilizza un WS2007FederationHttpBinding per l'autenticazione.Invocazione del servizio WCF con PHP (con sicurezza federata)

Ecco il codice che sto utilizzando al momento. Non ho nemmeno aggiunto le credenziali perché non sono sicuro di come, ma a prescindere, non sono nemmeno al punto in cui ricevo errori di accesso negato.

$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. Quale WSDL dovrei essere rivolto a?

  2. Devo specificare SOAP 1.2? Quando lo faccio, ottengo un timeout di connessione ([HTTP] Error Fetching http headers). Quando non lo faccio, viene utilizzato il default di SOAP 1.1 e ottengo un [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'. È perché non sono ancora autenticato, o perché sto usando la versione SOAP sbagliata?

  3. Come autenticarsi in PHP? Ecco il corrispondente codice .NET/C#. Devo in qualche modo mettere questi come intestazioni SOAP? O sto pensando a tutto sbagliato, e ho bisogno di fare un qualche tipo di autenticazione prima ancora di chiamare il metodo (da quello che ho letto, dovrei recuperare un token e poi usarlo per tutte le chiamate future al metodo - I sembra di vedere un esempio di questo in an answer here on Stack Overflow.

Se chiamo $client->__getFunctions(), utilizzando WSDL e SOAP entrambe le versioni, sto diventando una lista valida di tutte le funzioni, quindi immagino che uno di questi è il mio vero problema è l'autenticazione

Altri programmatori con cui ho parlato hanno dedicato del tempo a cercare di farlo funzionare, ma hanno rinunciato e hanno implementato un proxy in .N ET. Passano i loro parametri da PHP al loro servizio .NET non protetto, che a sua volta chiama questo servizio sicuro. Funziona, ma mi sembra follemente inefficiente e controproducente, in quanto lo scopo di WCF è supportare tutti i tipi di client (anche quelli non-HTTP!).

Ho letto How to: Create a WSFederationHttpBinding su MSDN, ma non ha aiutato.

+0

O? Wsdl o? SingleWsdl andrà bene. Il primo fa riferimento a più documenti suddivisi per scopo, il secondo ha tutto in un unico punto. Wsdl specifica la versione soap in uso, quindi sembra strano che dopo aver scaricato wsdl sia ancora necessario sapere quale versione di soap usare. Suggerirei che la libreria sia immaturo/di scarsa qualità se queste informazioni di base devono essere fornite in aggiunta al wsdl e non mi aspetto che la federazione funzioni con esso. Suggerisco di trovare una libreria di sapone diversa/migliore. – MattC

+0

@MattC Grazie per il commento. Buono a sapersi sul WSDL, ma si spera che la soap library non sia un problema (è il PHP nativo). Ho controllato nuSoap, ma non sembrava offrire alcun vantaggio. –

+0

Davvero non voglio sembrare snarky, @ShaneN, ma essere integrato in PHP non è una garanzia di qualità. Vedi per es. il crappy 'mail()'. Non ho lavorato con SOAP da PHP, quindi non posso aiutarti. – Palec

risposta

0
  1. È possibile utilizzare questo URL per WSDL https://slc.centershift.com/Sandbox40/StoreService.svc?singleWsdl. Questo WSDL ha tutte le definizioni.

  2. È necessario utilizzare 1.2 perché questo servizio Web funziona con la versione SOAP 1.2. Ho provato con 1.1 e 1.2 ed entrambi hanno errore. 1.1 è un errore di versione, 1.2 è un errore di timeout. Penso che ci sia un errore in questo server di prova. L'ho usato con svcutil per generare codice, ma ha generato anche l'errore. Normalmente dovrebbe ottenere informazioni e generare l'esempio di codice per chiamare il servizio.

  3. In genere è possibile aggiungere i parametri di autenticazione con SoapHeader o aggiungere direttamente alle opzioni nel comando SoapClient (se l'autenticazione del servizio è l'autenticazione di base). Scrivo sotto il codice in base al tuo screenshot. Ma dà un timeout dopo una lunga attesa.

    $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 opere, perché stampe funzioni definite nel WSDL. Non ci sono problemi con il recupero delle informazioni WSDL alla prima chiamata. Ma il vero problema è la comunicazione. PHP ottiene WSDL, genera la richiesta SOAP richiesta quindi invia al server, ma il server non risponde correttamente. Il server SOAP fornisce sempre una risposta anche se i parametri o il corpo della richiesta non sono corretti.

    Si dovrebbe comunicare con il fornitore di servizi, penso che possano dare una risposta chiara alle vostre domande.

+0

Grazie mille per la risposta. Sfortunatamente il fornitore di servizi non è disposto a fornire aiuto. Sostengono che il loro servizio funziona per i client .NET, quindi non hanno motivo di indagare sul fatto che non funzioni per altri tipi di client. In sostanza, ci costringono a utilizzare uno stack Microsoft, che non siamo disposti a fare solo per loro. –

0

Se la chiamata SOAP lavora da un'applicazione C#, è possibile utilizzare Wireshark (con il filtro ip.dst == 204.246.130.80) per visualizzare la richiesta effettiva compiuti e poi costruire una richiesta simile da php.

Controllare this answer per vedere come è possibile effettuare una chiamata SOAP personalizzata.

C'è anche l'opzione di fare richieste di ricciolo crudo, dal momento che potrebbe essere più semplice creare il tuo corpo xml, ma poi dovresti analizzare la risposta da solo con simplexml.

+0

L'ho provato, ma la richiesta è stata eseguita su SSL, quindi qualsiasi carico utile del messaggio è crittografato. C'è un modo per caricare un certificato in modo da poterlo decifrare, e l'ho provato, ma non ha funzionato per me (penso di aver bisogno della loro chiave privata, che non avevo) –

+0

Se non funziona su un http connessione, quindi il modo più semplice per visualizzare i pacchetti è impostare un proxy per la connessione e utilizzare [Fiddler] (http://www.telerik.com/fiddler/web-traffic-recording) come proxy per acquisire e visualizzare il dati. – Catalin

1

Dopo aver lavorato con .NET WS da PHP, credo che sia necessario creare oggetti da classi in PHP che corrispondano ai nomi previsti da .NET. Il WSDL dovrebbe dirvi i tipi che si aspetta. Spero che questo aiuti con il tuo percorso in avanti!