Qué son los WebServices
Los WebServices son un mecanismo muy útil para integrar aplicaciones a través del protocolo HTTP, y de ese modo, aprovechar las capacidades de terceros dentro de nuestras propias aplicaciones.
Un ejemplo muy común es de las pasarelas de pago, como ser PayPal o MercadoPago.
Se basan siempre en la existencia de dos procesos:
- El cliente (Consumidor)
- El servidor (Productor)
A nivel técnico existen dos operaciones que pueden realizarse a través de WebServices:
- Consumirlos
- Exponerlos
Uno de los protocolos que pueden utilizar los WebServices es SOAP (Otro muy común es REST).
Consumirlos usando PHP es bastante simple, para ello se utiliza la clase SoapClient
.
Cómo obtener la localización del visitante usando su IP
Para este ejemplo usaremos el WebService de cdyne.com para obtener información geográfica en base a la IP buscada.
<?php $url = "http://ws.cdyne.com/ip2geo/ip2geo.asmx?wsdl"; try { $client = new SoapClient($url, [ "trace" => 1 ] ); $result = $client->ResolveIP( [ "ipAddress" => $argv[1], "licenseKey" => "0" ] ); print_r($result); } catch ( SoapFault $e ) { echo $e->getMessage(); } echo PHP_EOL;
En este caso, este script debería ser corrido desde CLI.
Por ejemplo, si lo guardás como «ws.php», al ejecutar php ws.php 210.45.151.101
obtendrás la salida:
stdClass Object ( [ResolveIPResult] => stdClass Object ( [City] => Huainan [StateProvince] => 01 [Country] => China [Organization] => [Latitude] => 32.6264 [Longitude] => 116.9969 [AreaCode] => 0 [TimeZone] => [HasDaylightSavings] => [Certainty] => 90 [RegionName] => [CountryCode] => CN ) )
Como podrás observar, la respuesta del método ResolveIP
es un objeto de tipo StdClass
.
StdClass
es una clase genérica de PHP (Algo medio raro y, casi diría que un abuso de la naturaleza interpretada del lenguaje). Esta clase no tiene métodos ni propiedades definidas, pero sirve como una especie de contenedor al que se le puede asignar arbitrariamente todo lo que uno quiera (En rigor de verdad, esto puede hacerse con cualquier clase de PHP, sólo que es preferible no hacerlo).
Básicamente, al construir el cliente a partir de la definición de un WSDL están disponibles todos los servicios expuestos como métodos propios (como si estuviesen accesibles en forma local, a pesar de que la verdadera llamada es remota).
Es interesante notar esto, si ves la línea $result = $client->ResolveIP( [ "ipAddress" => $argv[1], "licenseKey" => "0" ] );
podrás notar que se está invocando al método ResolveIP
sobre un objeto de clase SoapClient
.
La clase SoapClient
es una clase estándar de PHP, mientras que el método ResolveIP
sólo tiene sentido dentro de este WebService. Si te estás preguntando cómo puede una clase estándar reconocer métodos desconocidos te diría que deberías darle una mirada al tema de los métodos mágicos de PHP (O tomar el curso de PHP Orientado a Objetos).
Como te imaginarás, si existe la clase SoapClient
… debe existir la clase SoapServer
(Tema de otro post).
En el curso de PHP WebServices estudiamos este tema en mayor profundidad, mientras tanto, si te quedó alguna duda podés dejarla en un comentario.
- Cómo enviarencabezados SOAP desde PHP - 09/12/2024
- Por qué PHP 8 no satisface el requisito ^7.3 de composer - 09/12/2024
- Cómo usar PHPUnit - 03/12/2024
Tengo una duda, como se le puede fijar el outgoing ws-security desde php? necesito acceder a una ruta que requiere unas firmas de seguridad especifica, si puedes compartir una documentación o darme algún consejo lo agradezco mucho, porque estuve revisando en la documentación a ver si tenia que enviarlo en la array de options, pero allí no aparecé nada
Hola Max, el tema ws-security es algo que aún no está muy bien resuelto en php (en forma nativa al menos).
Te puedo referir a este video que hice hace un tiempo sobre autenticación vía headers SOAP https://youtu.be/bbuxem9Ldtg que te puede dar algunas ideas.
Suerte!
Hola soy nuevo en esto de consumir soap tengo una duda que no logro resolver al hacer mi peticion por algunos metodos si la informacion biene de esta forma
hola
mundo
no tengo problemas para convertirlos a un arreglo y trabajarlo, quedandome algo asi:
object(stdClass)#2 (1) { [«xResult»]=> object(stdClass)#3 (2) { [«x1»]=> string(4) «hola» [«x2»]=> string(5) «mundo» } }
array(2) {
[«x1»]=>
string(4) «hola»
[«x2»]=>
string(5) «mundo»
}
pero otros métodos me regresan la información de esta forma
…
hola
mundo
y no logro acceder a los campos que ocupo, pues me los regresa como si fuera una sola cadena y no puedo separarlos como quiero, cualquier comentario lo agradecería mucho
Hola Gabriel:
¿Cómo estás? Te sugiero probar el webservice con el que estás trabajando por fuera de PHP para comprender bien cómo invocar los métodos y ver sus respuestas. Puedes usar una herramienta tipo https://www.soapui.org/
Hola mchojrin,
Uso la función
$client = new SoapClient(«rutinas/some.wsdl», array(‘login’=> «xxxxxx»,’password’=> «xxxxxx»));
$hoy=date(‘d-m-Y’);
$res=$client->ubicaciones( array(‘StartDate’=> $hoy,’EndDate’=> $hoy,’count’=>’MEXICO’));
Hasta aquí tengo respuesta, el detalle es que faltan algunos campos, esto lo se porque al consultar desde SOAPUI esos campos si los veo, la única diferencia es que el archivo wsdl que importo a PHP camio la linea a false o de lo contrario lanza un error
Fatal error: Uncaught SoapFault exception: [WSDL] SOAP-ERROR: Parsing WSDL: Unknown required WSDL extension
También uso curl_init de esta manera los campos en cuestión si aparecen, pero tengo el problema de lidiar con la respuesta XML, tiene algún POST sobre la respuesta XML?
Habría que ver por qué da error al importar el WSDL… ¿será que el archivo está mal formado? Tal vez podrías descargarlo y analizarlo con alguna herramienta tipo http://www.wsdl-analyzer.com/
Para ver temas de XML puedes consultar https://academy.leewayweb.com/como-recorrer-un-archivo-xml-usando-php/
Aunque te recomiendo intentar arreglar el problema de SOAP… intentar interpretar un XML de un webservice puede ser una tarea realmente compleja…
Una pregunta mi web service se llama wsprueba.wsdl, pero al subirlo a mi hosting y acceder a a la descripción del web service, con la url: http://miurl.co.co/carpetadondesealojaelws/wsprueba.wsdl.asmx?wsdl me dice arroja el error 404 y al usar el php de ejemplo tuyo me dice no es posible accede a la url, y no se como hacer esto, estoy recién aprendiendo web servicie.
Hola Miguel!
Gracias por tu pregunta 🙂
Por lo qe veo que comentas me inclino a pensar que hay un problema con las URLs. Tal vez tengas un archivo .htaccess o similar mal configurado? En todo caso, prueba ingresar a la URL http://miurl.co.co/carpetadondesealojaelws/wsprueba.wsdl.asmx (Es decir, sin el ?wsdl) a ver qué sucede.
Si ni así puedes entrar es casi seguro que sea lo que te comento, si no es eso habría que mirar más en profundidad.
Suerte!
una consulta, a mi me retorna al hacer tal cual como haces el $result en forma de cadena, toda la respuesta, del servicio SOAP como podria acceder a cada uno de los campos o en todo caso como podria devolver el $result en forma de std class como en tu caso para acceder a cada uno de los campos, saludos
Saludos, para consumir un web Services (wsdl) e integrarlo en una aplicaciòn desarrollada con symfony, dispone de algùn ejemplo?
Para Symfony específicamente podrías usar https://github.com/BeSimple/BeSimpleSoapBundle aunque me suena algo demasiado complicado… ¿probaste con el SOAPClient que viene con PHP?
Hola muchas gracias por la explicacion, tengo una duda como se podria obtener el valor por ejemplo de [City] => Huainan este ultimo Huainan, estoy trabajando con un ejemplo similar pero no este caso
saludos
Hola Daniel:
Gracias por tu pregunta. Muy acertada por cierto :).
Voy a modificar el artículo para que quede más claro, mientras tanto, la forma de acceder a la campo City sería:
echo $result->ResolveIPResult->City;
Esto funciona así porque $result es un objeto de clase StdClass (La clase «genérica» de PHP), si te fijas la salida del print_r notarás que tiene una propiedad que se llamana ResolveIPResult (también de clase StdClass) que tiene una propiedad City, en este caso Huainan.
Puedes leer más sobre StdClass en el sitio de php.net: http://php.net/manual/es/reserved.classes.php.
¿Me expliqué correctamente?
Excelente publicación, quede impactado con tantas cosas que aun no se
Gracias Juan! Me aegra que te haya servido 🙂
Es así, siempre hay más para aprender.