Web Services Con PHP, para Poder Enviar Datos A Otro Sistema.
Web Services Con PHP, para Poder Enviar Datos A Otro Sistema.
Web Services Con PHP, para Poder Enviar Datos A Otro Sistema.
2
mostrar informacin, mientras que el XML se ocupa de la informacin propiamente dicha (el contenido). Este concepto es importante tenerlo en cuenta, ya que muchas personas al escuchar sobre XML piensan que es el sucesor de HTML. Ejemplo de un documento XML sobre informacin de autos: <?xml version="1.0" encoding="UTF-8"?> <vehiculos> <coche> <marca>Toyota</marca> <modelo>Corolla</modelo> <fechaCompra>2002</fechaCompra> </coche> <coche> <marca>Honda</marca> <modelo>Civic</modelo> <fechaCompra>2003</fechaCompra> </coche> </vehiculos> Seguramente este tipo de archivos no sea una novedad para la mayora de los que lean este artculo, ya que muchos documentos en Internet estn en formato XML. Igualmente explicaremos brevemente las secciones del mismo:
<?xml version="1.0" encoding="UTF-8"?> Todo documento XML debe comenzar indicando que es un documento XML, la versin del mismo y su codificacin. Es por eso que se utiliza el tag <?xml .... ?> . Todos los elementos a partir de aqu son definidos por el usuario. <vehiculos> Luego se indica un tag raiz (<vehiculos>) el cual contendr a los dems elementos. Es como en HTML el tag <HTML> .. </HTML>, que dentro de el se encuentran los dems tags. Se lo conoce generalmente como root del documento. <coche> Luego definimos un tag <coche> el cual contendr un coche en particular (en este caso solo incorpore 3 caractersticas de un coche: marca, modelo, y fecha de compra). <marca>Toyota</marca> <modelo>Corolla</modelo> <fechaCompra>2002</fechaCompra> Se definen 3 tags (marca, modelo, y fechaCompra), los cuales contienen los datos para un coche en particular. <vehiculos> <coche> <marca>..</marca> <modelo>..</modelo> <fechaCompra>..</fechaCompra> </coche> </vehiculos> En el documento podemos apreciar que todos los tags que son abiertos <marca> deben ser cerrados </marca>. Esto es una exigencia del XML.
Se pueden anidar tags <coche><marca></marca>..</coche>. Marca esta dentro del tag coche. El XML provee muchas otras posibilidades como puede ser que las etiquetas tengan atributos (<coche color="rojo">..</coche>), pero no nos detendremos en ellas ya que la idea es simplemente ofrecer los conceptos bsicos para
3
conocer de que se trata el mundo de los Web Services.
4
</soap:Body> Indica el final del cuerpo del mensaje. </soap:Envelope> Fin del mensaje SOAP.
5
</definitions> Fin del documento WSDL
UDDI - Universal Discovery Description and Integration Es un modelo de directorios para Web Services. Es una especificacin para mantener directorios estandarizados de informacin acerca de los Web Services, sus capacidades, ubicacin, y requerimientos en un formato reconocido universalmente. UDDI utiliza WSDL para describir las interfaces de los Web Services. Es un lugar en el cual podemos buscar cuales son los Servicios web disponibles, una especie de directorio en el cual podemos encontrar los Web Services publicados y publicar los Web Services que desarrollemos.
http://soapclient.com/uddisearch.html http://uddi.org/find.html
7
personas de todo el mundo, y que no est limitado a los Estados Unidos. Buscando entre gran cantidad de Web Services de Cotizaciones, o datos especficos de los Estados Unidos, encontr uno que poda ser implementado en cualquier pas, y era ni ms ni menos que los datos del clima para todo el mundo. Este Web Service tiene 9 mtodos que podemos utilizar (todos ellos se encuentran definidos en el archivo WSDL que se encuentra en http://live.capescience.com/wsdl/GlobalWeather.wsdl. Los mtodos son: getStation(), isValidCode(), listCountries(), searchByCode(), searchByCountry(), searchByLocation(), searchByName(), searchByRegion(), getWeatherReport(). Para el ejemplo solo utilizare el mtodo searchByCountry() y getWeatherReport(). En el ejemplo existen dos archivos: seleccionarLocalidad.php: el cual nos permitir seleccionar una localidad dado un pas (el pas esta dado por el valor de la variable $sPais). Este archivo PHP utiliza el mtodo del Web Service searchByCountry() mostrarPronostico.php: el cual mostrara el pronstico para la localidad seleccionada. Este archivo PHP utiliza el mtodo del Web Service getWeatherReport(). Si queremos ver un listado de los servicios publicados podemos ir a esta pgina:
CapeScience
En esta pgina nos permiten probar los mtodos de los Web Services en lnea, sin necesidad de un cliente SOAP, esto nos es de utilidad principalmente para ver como funciona cada uno de los mtodos. Como mencione anteriormente, toda la informacin del Web Service se encuentra definida dentro del documento WSDL, para este Web service se encuentra definida en CapeScience. Este documento en particular tiene 425 lneas, por lo que la lectura del mismo es bastante tediosa. No voy a explicar todo el archivo WSDL, sino que simplemente me detendr en las lneas que son de importancia para nuestra aplicacin (las que hacen referencia a los metodos searchByCountry() y getWeatherReport() ). Ahora veamos donde se encuentran las definiciones de los mtodos dentro del archivo: Mensajes de searchByCountry: entre las lineas 277 a 282 podemos apreciar que se encuentra lo siguiente:
277. 278. 279. 280. 281. 282. <message name="searchByCountryResponse"> <part name="return" type="xsd1:ArrayOfStation"/> </message> <message name="searchByCountry"> <part name="country" type="xsd:string"/> </message>
SearchByCountry: comencemos por la lnea 280 y dejaremos para despus las lneas 277 a 279.
280. <message name="searchByCountry">
8
mtodo que estbamos buscando.
281. <part name="country" type="xsd:string"/>
Aqu se define que existe un parmetro para dicho mtodo que se llama country (pas) y es del tipo string.
282. </message>
Fin del mtodo seachByCountry Ejemplo de un mensaje real con el parmetro country seteado en argentina:
<nu:searchByCountry> <country xsi:type="xsd:string">argentina</country> </nu:searchByCountry>
SearchByCountryResponse: Ahora analicemos el mtodo searchByCountryResponse, como su nombre indica, es la respuesta al metodo searchByCountry. Es decir cuando invocamos a searchByCountry, el servidor nos responder con un mensaje con el formato de searchByCountryResponse. Las respuestas, generalmente, tienen anexado al final Response al nombre del mtodo (esto se epecifica en el portType).
277. <message name="searchByCountryResponse">
El mtodo nos devuelve una variable return la cual es del tipo ArrayOfSation. Como vimos anteriormente, los documentos WSDL pueden definir sus propios tipos de datos, ArrayOfStation es un tipo de datos definido en este WSDL. Ver ms adelante la definicin del tipo de datos ArrayOfStation.
279. </message>
Fin del mtodo searchByCountryResponse. Como vimos anteriormente se hace referencia a un ArrayOfStation, para ver de que se trata esto debemos buscar este tipo de datos dentro del archivo WSDL. En las lneas comprendidas ente 148 y 157, podemos ver que se define este tipo de datos.
148. <xsd:complexType name="ArrayOfStation"> 149. <xsd:complexContent> 150. <xsd:restriction base="SOAP-ENC:Array"> 151. <xsd:sequence> 152. <xsd:element maxOccurs="unbounded" minOccurs="0" name="item" type="xsd1:Station"/> 153. </xsd:sequence> 154. <xsd:attribute ref="SOAP-ENC:arrayType" wsdl:arrayType="xsd1:Station[]"/> 155. </xsd:restriction> 156. </xsd:complexContent> 157. </xsd:complexType> 148. <xsd:complexType name="ArrayOfStation">
En esta lnea podemos ver que se define un tipo de datos complejo (complexType) con el nombre de ArrayOfStation, el tipo de datos que buscbamos.
149. <xsd:complexContent> 150. <xsd:restriction base="SOAP-ENC:Array"> 151. <xsd:sequence>
9
Esta lnea es la que ms nos interesa, ya que se indica precisamente como esta compuesto el array. Nos dice que tiene un mnimo de ocurrencias de 0 (MinOccurs= 0 ), es decir, que puede no tener elementos. Un mximo de ocurrencias no limitado (maxOccurs=unbounded), es decir que podemos tener todos los element os que queramos. Y al finalizar nos indica el tipo de datos del array, que es Station. Por desgracia ahora tenemos que ver que tipo de datos es Station. Como podemos ver un dato se define a partir de otro, hasta llegar a los tipos de datos bsicos.
153. </xsd:sequence>
Nos quedaba pendiente definir el tipo de datos Station, nuevamente, al buscar en el cdigo encontramos entre las lneas 134 a 147 la definicin de este tipo de datos.
134. <xsd:complexType name="Station"> 135. <xsd:sequence> 136. <xsd:element maxOccurs="1" minOccurs="1" 137. < xsd:element maxOccurs="1" minOccurs="1" 138. < xsd:element maxOccurs="1" minOccurs="1" 139. < xsd:element maxOccurs="1" minOccurs="1" 140. < xsd:element maxOccurs="1" minOccurs="1" 141. < xsd:element maxOccurs="1" minOccurs="1" 142. < xsd:element maxOccurs="1" minOccurs="1" 143. < xsd:element maxOccurs="1" minOccurs="1" 144. < xsd:element maxOccurs="1" minOccurs="1" type="xsd:string"/> 145. <xsd:element maxOccurs="1" minOccurs="1" 146. </xsd:sequence> 147. </xsd:complexType> 134. <xsd:complexType name="Station">
name="icao" nillable="true" type="xsd:string"/> name="wmo" nillable="true" type="xsd:string"/> name="iata" nillable="true" type="xsd:string"/> name="elevation" type="xsd:double"/> name="latitude" type="xsd:double"/> name="longitude" type="xsd:double"/> name="name" nillable="true" type="xsd:string"/> name="region" nillable="true" type="xsd:string"/> name="country" nillable="true" name="string" nillable="true" type="xsd:string"/>
Indicamos que comenzamos con la definicin del tipo secuencia (es decir que todos los elementos que se definen dentro estn incluidos en el tipo de datos Station). Existen otro tipo que no es secuencia (sequence), y se llama choice (eleccin), en el cual se selecciona entre uno de los elementos dentro definidos (aquellos comprendidos entre <xsd:choice>y </xsd:choice>).
136. <xsd:element maxOccurs="1" minOccurs="1" name="icao" nillable="true" type="xsd:string"/> 137. <xsd:element maxOccurs="1" minOccurs="1" name="wmo" nillable="true" type="xsd:string"/> 138. <xsd:element maxOccurs="1" minOccurs="1" name="iata" nillable="true" type="xsd:string"/>
Se definen 3 elementos los cuales son del tipo string, dichos elementos son: icao, wmo, e iata.
139. <xsd:element maxOccurs="1" minOccurs="1" name="elevation" type="xsd:double"/> 140. <xsd:element maxOccurs="1" minOccurs="1" name="latitude" type="xsd:double"/> 141. <xsd:element maxOccurs="1" minOccurs="1" name="longitude" type="xsd:double"/>
Se definen otros 3 elementos, en este caso son del tipo double. Estos son: elevation, latitude, y longitude.
10
142. 143. 144. 145. <xsd:element <xsd:element <xsd:element <xsd:element maxOccurs="1" maxOccurs="1" maxOccurs="1" maxOccurs="1" minOccurs="1" minOccurs="1" minOccurs="1" minOccurs="1" name="name" nillable="true" type="xsd:string"/> name="region" nillable="true" type="xsd:string"/> name="country" nillable="true" type="xsd:string"/> name="string" nillable="true" type="xsd:string"/>
Se definen los ltimos 4 elementos del tipo string. Los elementos aqu definidos son: name, region, country, y string.
146. </xsd:sequence> 147. </xsd:complexType>
Para aclarar el tipo de estructura de ArrayOfStation usaremos analogas con otros lenguajes de programacin:
// Delphi // Station = record icao : String; wmo : String; iata : String; elevation : String; latitude : String; longitude : String; name : String; region : String; country : String; string_ : String; end; ArrayOfSation : array of Station; // C# // struct Station { String icao; String wmo; String iata; String elevation; String latitude; String longitude; String name; String region; String country;
11
String string_; } Station[] ArrayOfStation;
Como vemos no es fcil seguir todo lo que esta definido dentro de un documento WSDL, por suerte muchas veces no nos tenemos que preocupar por todo esto ya que los mismos sitios donde se encuentran alojados los Web Services nos proveen de la informacin necesaria sin necesidad de tener que recurrir a ver los archivos WSDL. Tambin existen aplicaciones como son Altova XMLSPY que nos proveen de la informacin de manera grfica
Debemos incluir la librera NuSOAP. En este ejemplo asumimos que el directorio donde se encuentra el archivo nusoap.php esta ubicado en el subdirectorio lib (a partir de donde esta nuestro script).
$oSoapClient = new soapclient('http://live.capescience.com/wsdl/GlobalWeather.wsdl', true);
Debemos instanciar la clase soapclient, ya que en esta ocasin utilizaremos solo el cliente que nos provee NuSOAP. Los parmetros enviados son la ubicacin del documento WSDL y true como segundo parametro (este ltimo parmetro indica que el primer documento es un WSDL) . Definimos un array con el pas para el cual se quieren obtener las localidades que tienen pronsticos disponibles. Volviendo al documento WSDL podemos ver que la variable que debemos enviar es country y que es del tipo string
$aParametros = array("country" => "argentina"); 280. <message name="searchByCountry"> 281. <part name="country" type="xsd:string"/> 282. </message> $aRespuesta = $oSoapClient->call("searchByCountry", $aParametros);
Llamamos al mtodo call del objeto soapclient. Al mismo le pasamos como parmetro
12
el nombre del mtodo que queremos ejecutar en el web service (searchByCountry) y los parmetros ($aParametros). En nuestra variable $aRespuesta tenemos un array con la respuesta del Web Service. Este array tiene el formato descripto en ArrayOfStation (el cual fue visto anteriormente). Es decir podemos acceder a las variables descriptas en ArrayOfStation de la siguiente manera: $aRespu esta[wmo], $aRespuesta[elevation], $aRespuesta[name], etc. Ahora que ya conocemos c&oacte;mo sera el procedimiento para consumir un Web Service, veamos un poco ms en profundidad los mtodos de soapclient que utilizamos: Al crear una instancia de soapclient, existen varios parmetros que podemos enviar para su creacin:
$oSoapClient = new soapclient( <url donde se encuentra el web service o WSDL>, [<booleana indicando si el primer parmetro es un WSDL>], [<entero con el Portame>], [<cadena proxyHost>], [<cadena proxyPort>], [<cadena nombre de usuario>], [<cadena password>], [<entero con el timeout de la conexin>], [<entero con el timeout de la respuesta>]);
Solo el primer parmetro es necesario (la ubicacin del Web Service o del documento WSDL del Web Service), todos los dems son opcionales. Al ejecutar el Web Service, existen varios parmetros que podemos enviar al mtodo:
call( <mtodo que queremos ejecutar en el servidor>, [<un array asociativo con los parmetros que debemos enviar (si existen)>], [<cadena con el espacio de nombres (namespace)>], [<cadena con el valor de la accin SOAP>], [<booleana indicando si esta presente los valores de SOAPVAL en los headers>], [<booleana la cual ya no se utiliza>], [<cadena con el style a usar cuando se realiza la serializacin de los parametros>], [<cadena que puede ser "encoded" o "literal" utilizada para serializacin de los parametros>]);
Cmo vemos existen muchos ms parametros de los que habiamos utilizado, pero como exigen un conocimiento ms profundo sobre los Web Services los cuales escapan a los alcances de este artculo no los trateremos aqu.
Utilizando NuSOAP IV
Cmo lo podemos usar?: Existen muchas formas en que podramos usar este Web Service, podemos dejar que el visitante seleccione su pas y localidad, y que nuestro sitio le retorne cual es el pronostico actual (solo deberamos incorporar un paso anterior al que se ofrece en el cdigo, el de seleccin del pas). Otro uso que podemos darle es el de mostrar cual es el clima actual para una localidad determinada (lo mismo que hacen muchos diarios en sus cabeceras). Si decidimos
13
implementar la segunda opcin debemos tener especial cuidado en como lo hacemos, ya que si por cada peticin que haga el usuario debemos conectarnos con el servidor que ofrece el web service, esto provocara una gran demora para el usuario, y una sobrecarga innecesaria del servidor. Para solucionar esto podemos guardar en un archivo de texto o en una base de datos, el clima actual, para leerlo desde all. Este archivo, o base de datos, la actualizaramos cada un tiempo prudencial (como puede ser una hora o ms). Otros Web Services: Actualmente existen gran cantidad de Web Services, gratuitos y no. En el sitio de XMethods pueden encontrar gran cantidad de ellos. Sin ir ms lejos Google ofrece un web service para realizar bsquedas (solo hay que registrarse en http://www.google.com/apis/) y nos permitir realizar 1000 consultas por da (creo que puede ser ms que interesante para muchos). Conclusin: Los Web Services son un tema apasionante, ya que brindan gran funcionalidad y posibilidad de realizar cambios y mejorar nuestras aplicaciones. Un mismo web service puede ser consumido tanto por aplicaciones que se ejecutan en un servidor y entregan cdigo html al cliente, como por aplicaciones que corren directamente en la mquina del cliente. Como vemos las posibilidades son infinitas, es slo cuestin de comenzar a experimentar. Apndice: Cdigo de seleccionarLocalidad.php
/** * Codigo para consumir un servicio web (Web Service) por medio de NuSoap. * La distribucion del codigo es totalmente gratuita y no tiene ningun tipo de restriccion. * Se agradece que mantengan la fuente del mismo. */ $sPais = "argentina"; // Nombre del pais que queremos el listado de localidades // Inclusion de la libreria nusoap (la que contendra toda la conexin con el servidor // require_once('lib/nusoap.php'); $oSoapClient = new soapclient('http://live.capescience.com/wsdl/GlobalWeather.wsdl', true); if ($sError = $oSoapClient->getError()) { echo "No se pudo realizar la operacin [" . $sError . "]"; die(); } $aParametros = array("country" => $sPais); $respuesta = $oSoapClient->call("searchByCountry", $aParametros); // Existe alguna falla en el servicio? if ($oSoapClient->fault) { // Si echo 'No se pudo completar la operacin'; die(); } else { // No $sError = $oSoapClient->getError(); // Hay algun error ? if ($sError) { // Si echo 'Error:' . $sError; die(); }
14
} ?> <html> <body> <form action="mostrarPronostico.php" method="post" name="frmLocalidades" id="frmLocalidades"> <table width="400" border="0" cellspacing="0" cellpadding="0"> <tr> <td colspan="2"><div align="center">Seleccione una localidad</div></td> </tr> <tr> <td width="61"> </td> <td width="339"> </td> </tr> <tr> <td>Localidad:</td> <td><select name="codLocalidad" id="codLocalidad"> $aElemento) echo "<option value='".$aElemento["wmo"]."'>".$aElemento["name"]."</option>"; ?> </select></td> </tr> <tr> <td> </td> <td> </td> </tr> <tr> /td> td><input type="submit" name="Submit" value="Quiero ver el pronostico"></td> /tr> /table> /form> /body> </html>
Utilizando NuSOAP V
Cdigo de mostrarPronostico.php
<?php /** * Codigo para consumir un servicio web (Web Service) por medio de NuSoap * La distribucion del codigo es totalmente gratuita y no tiene ningun tipo de restriccion. * Se agradece que mantengan la fuente del mismo. */ // Le indicamos a PHP que no muestre los Notices (por si el servicio no retorna datos) // (esto se puede evitar preguntando si hay datos antes de mostrarlos) error_reporting(1); // Inclusion de la libreria nusoap (la que contendra toda la conexin con el servidor //require_once('lib/nusoap.php'); $oSoapClient = new soapclient('http://live.capescience.com/wsdl/GlobalWeather.wsdl', true); if ($sError = $oSoapClient->getError()) { echo "No se pudo realizar la operacin [" . $sError . "]"; die(); } // Viene de un POST => Selecciono una ciudad if ($_SERVER["REQUEST_METHOD"] == "POST") { $aParametros = array("code" => $_POST["codLocalidad"]); $aRespuesta = $oSoapClient->call("getWeatherReport", $aParametros); } // Existe alguna falla en el servicio?
15
if ($oSoapClient->fault) { // Si echo 'No se pudo completar la operacin'; die(); } else { // No $sError = $oSoapClient->getError(); // Hay algun error ? if ($sError) { // Si echo 'Error:' . $sError; }
} ? ><html> <body> <table width="367" border="0" cellspacing="0" cellpadding="0"> <tr> <td colspan="2"><div align="center">Datos del tiempo</div></td> </tr> <tr> <td width="147"> </td> <td width="220"> </td> </tr> <tr> <td>Nombre:</td> <td><?=$aRespuesta["station"]["name"];?></td> </tr> <tr> <td>Elevacin:</td> <td><?=$aRespuesta["station"]["elevation"]; ?></td> </tr> <tr> <td>Fecha y Hora:</td> <td><?=$aRespuesta["timestamp"];?></td> </tr> <tr> <td>Pas:</td> <td><?=$aRespuesta["station"]["country"];?></td> </tr> <tr> <td>Latitud:</td> <td><?=$aRespuesta["station"]["latitude"];?></td> </tr> <tr> <td>Longitud:</td> <td><?=$aRespuesta["station"]["longitude"];?></td> </tr> <tr> <td>Presin:</td> <td><?=$aRespuesta["pressure"]["string"];?></td> </tr> <tr> <td>Temperatura:</td> <td><?=$aRespuesta["temperature"]["string"];?></td> < /tr> <tr> <td>Visibilidad:</td> <td><?=$aRespuesta["visibility"]["distance"];?> mts.</td> </tr> </table> </body> </html>
16