desde - consumir svc php
Invocación del servicio WCF con PHP(con seguridad federada) (3)
Estoy intentando invocar un servicio WCF (.NET) desde PHP. Es un poco más complicado que simplemente usar un SoapClient
ya que el servicio utiliza un WS2007FederationHttpBinding
para autenticarse.
Aquí está el código que estoy usando en este momento. Ni siquiera he agregado credenciales porque no estoy seguro de cómo, pero a pesar de eso, ni siquiera estoy en el punto en el que obtengo errores de acceso denegado.
$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);
¿A qué WSDL debería estar apuntando?
-
https://slc.centershift.com/Sandbox40/StoreService.svc ?wsdl
Parece ser muy corto, pero incluye una referencia a (observe elwsdl0
)https://slc.centershift.com/Sandbox40/StoreService.svc ?wsdl=wsdl0
-
https://slc.centershift.com/Sandbox40/StoreService.svc ?singleWsdl
Parece tener todo en ella.
-
¿Necesito especificar SOAP 1.2? Cuando lo hago, obtengo un tiempo de espera de conexión (
[HTTP] Error Fetching http headers
). Cuando no lo hago, se usa el valor predeterminado de SOAP 1.1 y obtengo 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''
[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''
[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''
. ¿Esto es porque todavía no estoy autenticado, o porque estoy usando la versión incorrecta de SOAP?¿Cómo autenticar en PHP? Aquí está el código correspondiente de .NET / C #. ¿Necesito poner de alguna manera estos como encabezados SOAP? O estoy pensando que todo está mal, y necesito hacer algún tipo de autenticación antes de que incluso llame al método (por lo que leo, se supone que debo recuperar un token y luego usarlo para todas las futuras llamadas a métodos). Creo que veo un ejemplo de esto en una respuesta aquí en Stack Overflow .
Si llamo a $client->__getFunctions()
, usando WSDL y cualquiera de las versiones SOAP, $client->__getFunctions()
una lista válida de todas las funciones, así que asumo que cualquiera de estas está bien y mi problema real es la autenticación.
Otros programadores con los que he hablado pasaron tiempo intentando que esto funcionara, pero abandonaron e implementaron un proxy en .NET. Pasan sus parámetros de PHP a su propio servicio .NET no seguro, que a su vez llama a este servicio seguro. Funciona, pero me parece locamente ineficiente y contraproducente, ya que el propósito de WCF es soportar todos los tipos de clientes (¡incluso los que no son HTTP!).
He leído Cómo crear un WSFederationHttpBinding en MSDN, pero no me ayudó.
Puede usar esta URL para WSDL https://slc.centershift.com/Sandbox40/StoreService.svc?singleWsdl . Este WSDL tiene todas las definiciones.
Tienes que usar 1.2 porque este servicio web funciona con la versión SOAP 1.2. Lo intenté con 1.1 y 1.2 y ambos dieron un error. 1.1 es error de versión, 1.2 es error de tiempo de espera. Creo que hay un error en este servidor de prueba. Lo utilicé con svcutil para generar código, pero también produjo un error. Normalmente debería obtener información y generar el ejemplo de código para llamar al servicio.
Normalmente, puede agregar parámetros de autenticación con SoapHeader o agregar directamente a las opciones en el consorcio SoapClient (si la autenticación del servicio es la autenticación básica). Escribo abajo el código de acuerdo a tu captura de pantalla. Pero da tiempo de espera después de una larga espera.
$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
funciona porque imprime funciones definidas en WSDL. No hay problemas para obtener información WSDL en la primera llamada. Pero el problema real es la comunicación. PHP obtiene WSDL, genera la solicitud de SOAP requerida, luego se envía al servidor, pero el servidor no responde correctamente. El servidor SOAP siempre da una respuesta incluso si los parámetros o el cuerpo de la solicitud no son correctos.Debe comunicarse con el proveedor de servicios, creo que pueden dar una respuesta clara a sus preguntas.
Después de haber trabajado con .NET WS de PHP antes, creo que necesitaría crear objetos de clases en PHP que coincidan con los nombres que espera .NET. El WSDL debería decirle los tipos que está esperando. Espero que esto te ayude en tu camino hacia adelante!
Si la llamada SOAP funciona desde una aplicación C #, puede usar Wireshark (con el filtro ip.dst == 204.246.130.80
) para ver la solicitud real que se está realizando y luego construir una solicitud similar desde php.
Verifique esta respuesta para ver cómo puede hacer una llamada SOAP personalizada.
También existe la opción de hacer solicitudes de curl sin procesar, ya que podría ser más fácil construir su cuerpo xml, pero luego tendría que analizar la respuesta usted mismo con simplexml.