Consumiendo webservices SOAP desde PHP

Recientemente nos han llegado un par de proyectos en los que debemos consumir webservices SOAP para obtener datos. La verdad es que hacía bastante tiempo que no los veía en mi trabajo habitual. Hace algunos años eran muy habituales para casi cualquier cosa que implicase comunicación con fuentes externas, sin embargo los últimos años habían caído un poco en desuso para cosas sencillas puesto que complicaban bastante un trabajo que con una simple petición HTTP y un XML básico se podría resolver. Precisamente ésta ha sido siempre una de las mayores críticas al protocolo SOAP, el elevado consumo de ancho de banda para una sencilla petición.

Hasta ahora siempre había utilizado nusoap para realizar llamadas SOAP desde PHP, sin embargo  me encontré con un problema al acceder a un servicio de un importante medio de comunicación internacional. La llamada con nusoap no devolvía resultados mientras que desde el sistema de pruebas html todo funcionaba correctamente.

Después de darle mil vueltas y no encontrar ningún error (otras peticiones al mismo servicio sí que funcionaban) me dí cuenta que PHP ya tiene un conjunto de funciones SOAP nativas, con lo que no necesitaría nusoap. La duda era saber si funcionaría bien, como así fue. Tras añadir la extensión adecuada surge una pequeña incompatibilidad. No puedes usar nusoap y las funcionas nativas en la misma instalación de PHP. Dicho de otro modo, si activas la extensión SOAP, nusoap dejará de funcionar y comenzará a lanzar mensajes de error ya que muchas de las funciones que utiliza tienen el mismo nombre que las nativas, que serían entonces nombres reservados. Si tienes alguna aplicación que utilice nusoap en la misma máquina tendrás que migrarla también para que utilice las funciones nativas.

El ejemplo de hoy será una sencilla llamada a un servicio que nos devuelve un listado de noticias.

El proceso es muy sencillo, necesitas la url del webservice, el método al que vas a llamar y los parámetros a pasarle y, como en cualquier servicio SOAP, te devolverá un XML.

$servicio="http://dominio.com/noticias?wsdl"; //url del servicio
$parametros=array(); //parametros de la llamada
$parametros['idioma']="es";
$parametros['usuario']="manolo";
$parametros['clave']="tuclave";$client = new SoapClient($servicio, $parametros);
$result = $client->getNoticias($parametros);//llamamos al métdo que nos interesa con los parámetros

Con estas sencillas instrucciones ya tenemos en $result el XML resultado de la llamada al servicio. Como trabajar con el XML es un poco engorroso, lo convertimos a un array asociativo de manera que nos sea más sencillo procesar los datos, para ello utilizamos la función obj2array que indico a continuación.

$result = obj2array($result);
$noticias=$result['resultado']['noticias'];
$n=count($noticias);

//procesamos el resultado como con cualquier otro array
for($i=0; $i<$n; $i++){
    $noticia=$noticias[$i];
    $id=$noticia['id'];
    //aquí iría el resto de tu código donde procesas los datos recibidos
}

function obj2array($obj) {
  $out = array();
  foreach ($obj as $key => $val) {
    switch(true) {
        case is_object($val):
         $out[$key] = obj2array($val);
         break;
      case is_array($val):
         $out[$key] = obj2array($val);
         break;
      default:
        $out[$key] = $val;
    }
  }
  return $out;
}

En la segunda línea nos quedamos con los elementos del array que nos interesa procesar. Si no sabes qué devuelve tu webservice puedes hacer un var_dump($result) y verás todo el resultado. En nuestro caso, como es una secuencia de noticias, nos quedamos con el elemento que tiene esas noticias.

Como os habréis dado cuenta, no me he preocupado del control de errores al llamar al webservice.  Eso os lo dejo como ejercicio a vosotros, que es agosto y no me apetece 😛 . En el manual de PHP está toda la información.

Y eso es todo amigos, hoy ha sido un ejemplo sencillo pero muy útil cuando necesitas utilizar SOAP.

82 comentarios en “Consumiendo webservices SOAP desde PHP

  1. hola amigos podrian ayudarme!!!! yo necesito consumir un servicio web con symfony 1.4.8 pero he seguido sus sugerencias y no me funciona.
    Bueno en si no puedo obtener los parametros.
    Aqui les posteo mi codigo

    $client=new SoapClient(“http://200.110.68.244/Academico/VerificaUsuarioWebPort?WSDL”, array());
    $res=$client->getVerificaUsuarioWeb(‘oobando’,’1234567′);
    var_dump($res);

  2. gracias Osus por contestar, entonces ese es problema?
    pero ese metodo tambien esta creado…..
    mira ahora yo apliq este codigo donde no llamo metodo alguno

    $client=new SoapClient(“http://200.110.68.244/Academico/VerificaUsuarioWebPort?WSDL”,array(‘oobando’,’1234567′));
    var_dump($client->__getFunctions());

    y me muestra en la pagina lo sgte:
    array(2) { [0]=> string(71) “obtenerResultadoResponse obtenerResultado(obtenerResultado $parameters)” [1]=> string(65) “actualizaClaveResponse actualizaClave(actualizaClave $parameters)” }

  3. Amigo Osus….muchas gracias por tu comentario me ayudo de mucho
    ahora ya revise bien y tenias mucha razon
    el metodo al q tenia q llamar era obtenerResultado
    aqui dejo posteado el codigo q ahora si funciona

    $parametros=array(
    ‘user’,’usuario’,
    ‘passw’,’clave’
    );

    $client=new SoapClient(“http://200.110.68.244/Academico/VerificaUsuarioWebPort?WSDL”,array());
    $res=$client->obtenerResultado($parametros);
    var_dump($res);

  4. Amigo Osus….muchas gracias por tu comentario me ayudo de mucho
    ahora ya revise bien y tenias mucha razon
    el metodo al q tenia q llamar era obtenerResultado
    aqui dejo posteado el codigo q ahora si funciona

    $parametros=array(
    ‘user’,’usuario’,
    ‘passw’,’clave’
    );

    $client=new SoapClient(“http://200.110.68.244/Academico/VerificaUsuarioWebPort?WSDL”,array());
    $res=$client->obtenerResultado($parametros);
    var_dump($res);

  5. hola Osus podria ayudarme a solucionar el problema q tengo….he seguido sus indicaciones y al momento de probar el consumo de mi webservice en php me sale lo sgte en la pantalla

    object(stdClass)#47 (1) { [“return”]=> bool(false) }

    le agradeceria muchisimo si pudiera colaborar conmigo

  6. otra preguntita….los parametros del array debo llamarlo con el mismo nombre q han sido creados en los metodos de mi webservice o puedo llamarlos con otro nombre?

  7. Hola,

    tengo la duda de donde va el metodo (en que parte se llama) de respuesta.
    Por ejemplo mi metodo principal es GetOC y el metodo que me trae las respuestas es GetOCResult

    En el ejemplo solo llamas al metodo principal

  8. @Carlos,

    En el ejemplo,
    $result = $client->getNoticias($parametros);
    $result contiene la respuesta al método. No hay un metodo GetOCResult como tal.
    Haz un var_dump($result) y verá lo que te devuelve tu método.

  9. Hola Osus, despues de leer todos los comentarios observo que este tema no se ha cerrado y que te haz tomado la molestia de contestar, de antemano muchas gracias.

    Yo quiero consultar contigo el siguiente problema,
    $client = new SoapClient($servicio);
    $result = $client->getArticulo(“JTA16P1”);
    var_dump($result);

    Tengo como resultado un NULL y no se que puede estar mal, si el metodo retorna una cadena.

    Ya verifique que el metodo exista en el WS pero no entiendo que me falta hacer para consumir correctamente el web service.

    Saludos.

  10. Es es el resultado del Web Service

    Valor de __getFunctions()
    array(1) { [0]=> string(40) “void getArticulo(anyType $strIdArticulo)” }

    Valor de getArticulo()
    NULL

    Saludos

  11. Saludos…
    Tengo un problema tengo un wsdl que contiene headers y dentro de este esta las credenciales para consumir el sw..username y password…mi pregunta es como seteo estos valores desde php..
    Gracias de antemano…

    Claro que aparte los metodos tienen sus propios parametros..como son login y password…que estan dentro del body..

  12. Hola Osus o quien pueda ayudarme!!

    Se que ha pasado mucho desde la creación del blog, pero apenas estoy viendo este tema y no puedo hacer que me funcione.

    Estoy tratando de consumir un ws de .net desde PHP y ya hice todo lo que mensionas pero me sale el siguiente error(warning) y no me da ningun resultado y no se por que:

    Warning: SOAP-ERROR: Parsing WSDL: Couldn’t load from ‘https://localhost:8082/ws/Service1.asmx?WSDL’ : failed to load external entity “https://localhost:8082/ws/Service1.asmx?WSDL” in C:\xampp\htdocs\test\prueba6.php on line 20

    Ojalá alguien pueda orientarme…

      1. Al ponerlo en el navegador veo el xml bien…



        ……. ETC

        De hecho por eso estoy desorientada ya que funciona bien, al consumirlo con .net funciona todo bien, pero al intentarlo en php de varias formas siempre me da el mismo mensaje.
        Y ya no se que revisar… es por ello que pido ayuda…

        1. @Editor,
          Lo siento al parecer no puedo mostrar el codigo que me muestra… Pero veo correcto el archivo… y no se como hacer que cargue el wsdl…

          Alguna sugerencia? Estoy Totalmente desorientada…

          1. @Isabel,
            El error está en que desde php no carga bien el wsdl.
            ¿Qué pasa si haces un file_get_contents(“https://localhost:8082/ws/Service1.asmx?WSDL”);

  13. Ya logre consumirlo, muchisimas gracias… no estoy segura de que fue en realidad pero les comparto lo que hice por si sirve de algo…
    -Verifique que la ruta del wsdl estuviera exacta(según yo estaba igual, pero copie y pegue directa del url por si las dudas)
    -Revise que el openssl estuviera activo, (active y desactive).
    -Verifique que soap estuviera activo.

    Al final de todo ya funcionó… espero ahora si a trabajar…

    Gracias Editor por la ayuda… tus comentarios me hicieron ponerme a probar todo eso… y no dejarlo…

      1. Hola, puedes revisar lo que tienes activo o no con el phpinfo(), dependiendo de como tienes tu php, si usas xampp por ejemplo, desde el menu puedes encontrarlo.

        En algunos servidores publicos por ejemplo con tu dominio y el archivo info.php (ejemplo http://www.tudominio.com/info.php).

        Pero en general lo puedes ver en la información de tu servidor.

  14. Hola buen día,
    Estoy consumiendo un webservice en php, pero obtengo el siguiente error:
    “Fatal error: Uncaught SoapFault exception: [HTTP] Could not connect to host in C:\wamp\www\test.ph”; alguien sabe a que se debe? ya cheque que este activo el soap, la URI del WS esta activa, no se que pudiera ser.

  15. Hola buenas, no se si esta cerrado este tema pero mi consulta es .
    Que pasa si el webservice al que quiero llamar es un webservice de login
    o sea para ser mas explicitos es el webservice de un ERP el cual esta piublicado para dar acceso al servidor

  16. Hola amigo
    A ver si me pueden ayudar, soy muy nuevo en esto y me cuenta mucho trabajo, estoy tratando de consumir un WS con el tutorial pero solo se queda en blanco. Espero me puedan ayudar.

    doProceso($parametros);//llamamos al métdo que nos interesa con los parámetros
    var_dump($result);
    ?>

  17. Hola, muy buen tutorial.
    Me podrías orientar un poco, eh intentado consumir un servicio web, sin embargo, no envía los parámetros que agrego, llega la petición vacía.
    🙁

  18. Hola disculpen alguin podria ayudarme, necesitaba consumir el web services de una tienda en linea, queiro que el stock de una tienda en linea de uno de mis proveedores aparezca en mi tienda en linea y para ello debo consumir su web service si alguien tiene un proyecto similar le agradeceria mucho su apoyo, de ante mano muchas gracias.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *