Mostrando entradas con la etiqueta XML. Mostrar todas las entradas
Mostrando entradas con la etiqueta XML. Mostrar todas las entradas

viernes, 6 de febrero de 2015

Crear un WebService con PHP

Si trabajamos con PHP, una tarea con la casi seguro que nos encontraremos habitualmente es con la de construir un servicio web que exponga una serie de datos. Esto es muy sencillo de hacer en PHP, y vamos a ver como se hace.

Antecedentes
Supongamos que vamos a realizar un webservice que se conecte a una base de datos MySQL para lanzarle consultas y devolver los resultados. Esto será válido para la mayoría de casos con que nos encontramos, independientemente de que después debamos ampliar el servicio con otros métodos (como por ejemplo incluir seguridad, encriptación, etc).

Lo primero que se nos puede ocurrir, es crear una serie de métodos en el WebService de forma que cada uno reciba sus parámetros, monte las consultas, y las lance contra la base de datos para terminar devolviendo los resultados. Esto es correcto, pero vamos a crear una técnica más potente.

En vez de hacer un método por cada consulta a lanzar, vamos a tener un sólo método. Este, recibirá un nombre de opción a ejecutar, y según esa opción, lanzará una u otra consulta. Es más, no tendremos que tener las consultas dentro del propio WebService, sino que nos basaremos para configurarlas en un fichero XML. Esto nos va a permitir disponer de un código muy limpio y claro, con muy poco mantenimiento posterior, y configuraremos las posibles opciones y sus consultas relacionadas en un fichero XML, de forma que para crear, modificar, o eliminar nuevos métodos, no modificaremos el servicio web, sino únicamente el XML. Veamos cómo.

Fichero de configuración
Vamos a crear un fichero XML de configuración que contendrá los métodos de que dispondrá el servicio web. Posteriormente, dicho servicio recibirá el método a ejecutar, su lista de parámetros, y devolverá los resultados.

El fichero podría ser el siguiente:
<?xml version="1.0" encoding="utf-8" ?>
<OpcionesDisponibles>
  <opcion>
    <nombre>GetPaises</nombre>
    <SQL>SELECT cod_pais,pais FROM paises order by pais</SQL>
  </opcion>
  <opcion>
    <nombre>GetPais</nombre>
    <SQL>SELECT cod_pais,pais FROM paises WHERE cod_pais='#PARAMETRO_1#'</SQL>
  </opcion>
</OpcionesDisponibles>
Como se puede ver, es extremadamente simple, y nos permitirá ampliar, modificar, o reducir el servicio web sin tener que modificarlo.

El WebService
Una vez que sabemos lo que queremos, y que tenemos nuestro fichero de configuración de métodos definido, sólo nos queda crear el servicio web.

Nuestro servicio recibirá tres parámetros: la opción a ejecutar, la lista de parámetros relativas a esa función, y el formato de resultado que deseamos. Así pues, manos a la obra:
<?php
  // Recoger parámetros de entrada. Se permite GET y POST
  $paramOpcion = $_REQUEST['opcion'];
  $paramLista = $_REQUEST['listaParametros'];
  $formato = strtolower($_REQUEST['format']) == 'xml' ? 'xml' : 'json';

  // Obtener consulta SQL a ejecutar
  $sql = getSQL($paramOpcion);
  $sql = aplicarParametrosSQL($sql,$paramLista);

  // Lanzar consulta a la base de datos
  if ($sql == '')
    die ('Opcion incorrecta');
  else
  {    
    $datos = getArrayDatos($sql);
    echo formatData($datos,$formato); 
  }


  // Dado un nombre de opción, buscar en el xml su SQL correspondiente
  function getSQL($nombreOpcion)
  {
    $xmlOpciones = simplexml_load_file('opciones.xml');
    $sql = ""; 
    foreach ($xmlOpciones->opcion as $opcion)
    {
      $nombre = $opcion->nombre;
      if ($nombre == $nombreOpcion)
      {
        $sql = $opcion->SQL;
        break;
      }
    }
    return $sql;
  }

  // Aplicar parámetros de la sentencia SQL
  function aplicarParametrosSQL($sql, $listaPametros)
  {    
    if ($listaPametros != '')
    {
      $arrParam = explode('#',$listaPametros);
      for ($i=0; $i<count($arrParam); $i++)
      {
        $nomParam = '#PARAMETRO_'.($i+1).'#';
        $valor = $arrParam[$i];
        $sql = str_replace($nomParam, $valor, $sql);
      }
    }
    return $sql;
  }

  function getArrayDatos($sql)
  {
    $db = mysql_connect('servidor_base_datos','usuario','clave') or die('No se pudo conectar con la base de datos');
    mysql_select_db('base_de_datos',$db) or die('No se pudo seleccionar la base de datos.');
    $resul = mysql_query($sql,$db) or die('Consulta incorrecta:  '.$sql);

    /* create one master array of the records */
    $datos = array();
    if(mysql_num_rows($resul)) 
    {
     while($row = mysql_fetch_assoc($resul)) 
     {
      $datos[] = $row;
     }
    }

    /* disconnect from the db */
    @mysql_close($db);    

    /* Return data array */
    return $datos;        
  }

  function formatData($data,$format='json')
 {
    if($format == 'json' || $format == 'jsonp') 
    {
      header('Content-type: application/json');
      if (isset($_REQUEST['callback']))   // Peticiones ajax
        return $_REQUEST['callback'].'('.json_encode($data).')';
      else
        return json_encode($data);
    }
    else
    {
      header('Content-type: text/xml');
      $xml = new SimpleXMLElement('<response/>');
      return array2xml($data, $xml);
    }
  }

  function array2xml($array, $xml = false)
  {
    if($xml === false)
    {
      $xml = new SimpleXMLElement('<root/>');
    }
    foreach($array as $key => $value)
    {
      if(is_array($value))
      {
        //array2xml($value, $xml->addChild($key));
        array2xml($value, $xml->addChild('item'));
      }
      else
      {
        $xml->addChild($key, htmlspecialchars($value));
      }
    }
    return $xml->asXML();
  }

?>
Y eso es todo. Potente, ¿verdad?. Ahora sólo debemos modificar el fichero XML a nuestro gusto para adaptarlo a nuestras necesidades (ojo, recordar introducir algún sistema de seguridad, y a ser posible, excluir el fichero XML en el fichero robots.txt de nuestro servidor para que no sea indexado).

En otra entrada veremos como consumir un webservice.

Crear un WebService con .NET

Si trabajamos con .NET, una tarea con la casi seguro que nos encontraremos habitualmente es con la de construir un servicio web que exponga una serie de datos. Esto es muy sencillo de hacer en .NET, y vamos a ver como se hace.

Antecedentes
Supongamos que vamos a realizar un webservice que se conecte a una base de datos SQL Server para lanzarle consultas y devolver los resultados. Esto será válido para la mayoría de casos con que nos encontramos, independientemente de que después debamos ampliar el servicio con otros métodos (como por ejemplo incluir seguridad, encriptación, etc).

Lo primero que se nos puede ocurrir, es crear una serie de métodos en el WebService de forma que cada uno reciba sus parámetros, monte las consultas, y las lance contra la base de datos para terminar devolviendo los resultados. Esto es correcto, pero vamos a crear una técnica más potente.

En vez de hacer un método por cada consulta a lanzar, vamos a tener un sólo método. Este, recibirá un nombre de opción a ejecutar, y según esa opción, lanzará una u otra consulta. Es más, no tendremos que tener las consultas dentro del propio WebService, sino que nos basaremos para configurarlas en un fichero XML. Esto nos va a permitir disponer de un código muy limpio y claro, con muy poco mantenimiento posterior, y configuraremos las posibles opciones y sus consultas relacionadas en un fichero XML, de forma que para crear, modificar, o eliminar nuevos métodos, no modificaremos el servicio web, sino únicamente el XML. Veamos cómo.

Fichero de configuración
Vamos a crear un fichero XML de configuración que contendrá los métodos de que dispondrá el servicio web. Posteriormente, dicho servicio recibirá el método a ejecutar, su lista de parámetros, y devolverá los resultados.

El fichero podría ser el siguiente:
<?xml version="1.0" encoding="utf-8" ?>
<OpcionesDisponibles>
  <opcion>
    <nombre>GetPaises</nombre>
    <SQL>SELECT cod_pais,pais FROM paises order by pais</SQL>
  </opcion>
  <opcion>
    <nombre>GetPais</nombre>
    <SQL>SELECT cod_pais,pais FROM paises WHERE cod_pais='#PARAMETRO_1#'</SQL>
  </opcion>
</OpcionesDisponibles>
Como se puede ver, es extremadamente simple, y nos permitirá ampliar, modificar, o reducir el servicio web sin tener que modificarlo.

El WebService: La clase mágica
Una vez que sabemos lo que queremos, y que tenemos nuestro fichero de configuración de métodos definido, sólo nos queda crear el servicio web.

Nuestro servicio recibirá tres parámetros: la opción a ejecutar, la lista de parámetros relativas a esa función, y el formato de resultado que deseamos. Así pues, manos a la obra:
using System;
using System.Data;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Xml;

public class WS_Clase
{
  static string ficheroOpciones = HttpContext.Current.Server.MapPath("~/") + "\\opciones.xml";

  /// <summary>
  /// Ejecutar y devolver un XML resultado de ejecutar una sentencia SQL configurada en un fichero XML.
  /// </summary>
  /// <param name="nombre"></param>
  /// <param name="listaParametros"></param>
  /// <returns></returns>
  public static XmlDocument GetOpcion(string nombre, string listaParametros)
  {
    try
    {
      // Buscar opcion en el fichero de parametros para obtener la SQL a ejecutar
      DataSet ds = new DataSet();
      ds.ReadXml(ficheroOpciones);
      DataTable dt = new DataTable();
      dt = ds.Tables[0];
      string SQL = string.Empty;

      for (int i = 0; i < dt.Rows.Count; i++)
      {
        if (Convert.ToString(dt.Rows[i]["nombre"]).ToUpper() == nombre.ToUpper())
        {
          SQL = Convert.ToString(dt.Rows[i]["SQL"]);
          break;
        }
      }
      if (SQL == string.Empty)
        throw new Exception("Opción no disponible: " + nombre);

      // Asignar parametros
      string[] parametros;
      parametros = listaParametros.Split('|');
      for (int i = 0; i < parametros.Length; i++)
      {
        SQL = SQL.Replace("#PARAMETRO_" + Convert.ToString(i + 1) + "#", parametros[i]);
      }

      // Ejecutar SQL
      dt = AccesoDatos.GetDataTable(SQL);

      System.Xml.XmlDocument x = DataTableToXmlDocument(dt);
      dt.Dispose();
      ds.Dispose();
      return x;

    }
    catch (Exception ex)
    {
      throw new Exception(ex.Message);
    }
  }

  public static int SetOpcion(string nombre, string listaParametros)
  {
    try
    {
      // Buscar opcion en el fichero de parametros para obtener la SQL a ejecutar
      DataSet ds = new DataSet();
      ds.ReadXml(ficheroOpciones);
      DataTable dt = new DataTable();
      dt = ds.Tables[0];
      string SQL = string.Empty;

      for (int i = 0; i < dt.Rows.Count; i++)
      {
        if (Convert.ToString(dt.Rows[i]["nombre"]).ToUpper() == nombre.ToUpper())
        {
          SQL = Convert.ToString(dt.Rows[i]["SQL"]);
          break;
        }
      }
      if (SQL == string.Empty)
        throw new Exception("Opción no disponible: " + nombre);

      // Asignar parametros
      string[] parametros;
      parametros = listaParametros.Split('|');
      for (int i = 0; i < parametros.Length; i++)
      {
        SQL = SQL.Replace("#PARAMETRO_" + Convert.ToString(i + 1) + "#", parametros[i]);
      }

      // Ejecutar SQL
      int resul = AccesoDatos.ExecuteSQL(SQL);

      // Devolver resultado
      dt.Dispose();
      ds.Dispose();
      return resul;
    }
    catch (Exception ex)
    {
      throw new Exception(ex.Message);
    }
  }

  /// <summary>
  /// GetOpcion en formato JSON
  /// </summary>
  /// <param name="nombre"></param>
  /// <param name="listaParametros"></param>
  /// <returns></returns>
  public static String GetOpcionJSON(string nombre, string listaParametros)
  {
    try
    {
      // Buscar opcion en el fichero de parametros para obtener la SQL a ejecutar
      DataSet ds = new DataSet();
      ds.ReadXml(ficheroOpciones);
      DataTable dt = new DataTable();
      dt = ds.Tables[0];
      string SQL = string.Empty;

      for (int i = 0; i < dt.Rows.Count; i++)
      {
        if (Convert.ToString(dt.Rows[i]["nombre"]).ToUpper() == nombre.ToUpper())
        {
          SQL = Convert.ToString(dt.Rows[i]["SQL"]);
          break;
        }
      }
      if (SQL == string.Empty)
        throw new Exception("Opción no disponible: " + nombre);

      // Asignar parametros
      string[] parametros;
      parametros = listaParametros.Split('|');
      for (int i = 0; i < parametros.Length; i++)
      {
        SQL = SQL.Replace("#PARAMETRO_" + Convert.ToString(i + 1) + "#", parametros[i]);
      }

      // Ejecutar SQL
      dt = AccesoDatos.GetDataTable(SQL);

      string x = DataTableToJSONDocument(dt);
      dt.Dispose();
      ds.Dispose();
      return x;

    }
    catch (Exception ex)
    {
      throw new Exception(ex.Message);
    }
  }

  #region " Métodos privados "

  /// <summary>
  /// Configurar DataTable con nomenclatura estandar para hacer mas fácil la lectura desde aplicaciones cliente (siempre mismos campos).
  /// </summary>
  /// <param name="dt"></param>
  /// <returns></returns>
  private static DataTable DataTableToStandard(DataTable dt)
  {
    try
    {
      DataTable dtResultado = new DataTable(dt.TableName);
      dtResultado.Columns.Add("campo", typeof(System.String));
      dtResultado.Columns.Add("valor", typeof(System.String));

      DataRow dr;
      for (int i = 0; i < dt.Rows.Count; i++)
      {
        dr = dtResultado.NewRow();
        dr["campo"] = dt.Rows[i][0];
        dr["valor"] = dt.Rows[i][1];
        dtResultado.Rows.Add(dr);
      }

      return dtResultado;
    }
    catch (Exception ex)
    {
      throw ex;
    }
  }

  private static String DataTableToJSONDocument(DataTable dt)
  {

    string[] StrDc = new string[dt.Columns.Count];
    string HeadStr = string.Empty;
    for (int i = 0; i < dt.Columns.Count; i++)
    {
      StrDc[i] = dt.Columns[i].Caption;
      HeadStr += "\"" + StrDc[i] + "\":\"" + StrDc[i] + i.ToString() + "¾" + "\",";
    }

    HeadStr = HeadStr.Substring(0, HeadStr.Length - 1);

    StringBuilder Sb = new StringBuilder();

    Sb.Append("[");

    for (int i = 0; i < dt.Rows.Count; i++)
    {
      string TempStr = HeadStr;
      for (int j = 0; j < dt.Columns.Count; j++)
      {
        TempStr = TempStr.Replace(dt.Columns[j] + j.ToString() + "¾", dt.Rows[i][j].ToString().Trim());
      }
      //Sb.AppendFormat("{{{0}}},",TempStr);

      Sb.Append("{" + TempStr + "},");
    }

    Sb = new StringBuilder(Sb.ToString().Substring(0, Sb.ToString().Length - 1));

    if (Sb.ToString().Length > 0)
      Sb.Append("]");

    return StripControlChars(Sb.ToString());

  }

  public static string StripControlChars(string s)
  {
    return Regex.Replace(s, @"[^\x20-\x7F]", "");
  }

  /// <summary>
  /// Pasar DataTable a XML estandarizado para su devolución por el WebService.
  /// </summary>
  /// <param name="dt"></param>
  /// <returns></returns>
  private static XmlDocument DataTableToXmlDocument(DataTable dt)
  {
    XmlDocument xml = new XmlDocument();
    System.Text.StringBuilder sb = new System.Text.StringBuilder();

    sb.Append("<?xml version='1.0' encoding='utf-8' ?>");
    sb.Append("<DocumentElement>");

    foreach (DataRow dr in dt.Rows)
    {
      sb.Append("<Dato>");

      foreach (DataColumn dc in dt.Columns)
      {
        sb.Append("<" + dc.ColumnName + ">" + dr[dc].ToString() + "</" + dc.ColumnName + ">");
      }

      //foreach (DataColumn dc in dt.Columns)
      //  sb.Append("<" + dc.ColumnName + ">" + dr[dc].ToString() + "</" + dc.ColumnName + ">");

      sb.Append("</Dato>");
    }

    sb.Append("</DocumentElement>");
    xml.LoadXml(sb.ToString());

    return xml;
  }

  #endregion

}

El WebService: La interfaz
Una vez hemos definido la clase que hace lo que deseamos, simplemente exponemos el webservice:
using WS_Clase; // Nuestra clase creada antes
using System.Web;
using System.Web.Script.Services;
using System.Web.Services;
using System.Xml;

namespace eCliente_WebService
{
  /// <summary>
  /// Servicio web para el acceso a datos de la web de eCliente
  /// </summary>
  [WebService(Namespace = "http://nuestra_url")]
  [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
  [System.ComponentModel.ToolboxItem(false)]
  // Para permitir que se llame a este servicio web desde un script, usando ASP.NET AJAX, quite la marca de comentario de la línea siguiente. 
  // [System.Web.Script.Services.ScriptService]
  public class eCliente_WebService : System.Web.Services.WebService
  {
    [WebMethod]
    public string Test()
    {
      return "Hola desde el WebService de eCliente.";
    }

    [WebMethod]
    public XmlDocument GetOpcion(string nombre, string listaParametros)
    {
      return WS_Clases.GetOpcion(nombre, listaParametros);
    }

    [WebMethod]
    public int SetOpcion(string nombre, string listaParametros)
    {
      return WS_Clases.SetOpcion(nombre, listaParametros);
    }

    [WebMethod]
    [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
    public void GetOpcionJSON(string nombre, string listaParametros)
    {
      HttpContext.Current.Response.Write(WS_Clases.GetOpcionJSON(nombre, listaParametros));
    }


    [WebMethod]
    [ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]
    public void GetOpcionJSONAjax(string nombre, string listaParametros, string callback = "")
    {
      System.Text.StringBuilder sb = new System.Text.StringBuilder();
      if (callback != "")
      {
        sb.Append(callback + "(");
        sb.Append(WS_Clases.GetOpcionJSON(nombre, listaParametros));
        sb.Append(");");
      }
      else
        sb.Append(WS_Clases.GetOpcionJSON(nombre, listaParametros));

      Context.Response.Clear();
      Context.Response.ContentType = "application/json";
      Context.Response.Write(sb.ToString());
      Context.Response.End();
    }

  }
}

Y eso es todo. Potente, ¿verdad?. Ahora sólo debemos modificar el fichero XML a nuestro gusto para adaptarlo a nuestras necesidades (ojo, recordar introducir algún sistema de seguridad, y a ser posible, excluir el fichero XML en el fichero robots.txt de nuestro servidor para que no sea indexado).

En otra entrada veremos como consumir un webservice.

Lectura de XML con PHP

Con PHP es sumamente sencillo leer y parsear ficheros XML. Para ver como se hace, lo mejor es hacerlo con un ejemplo.

Supongamos el siguiente fichero XML, que puede ser utilizado por un WebService, y que contiene nombres de método para el WebService y la sentencia SQL que debe ejecutar en cada uno de ellos:
<?xml version="1.0" encoding="utf-8" ?>
<OpcionesDisponibles>
  <opcion>
    <nombre>GetPaises</nombre>
    <SQL>SELECT cod_pais,pais FROM paises order by pais</SQL>
  </opcion>
  <opcion>
    <nombre>GetPais</nombre>
    <SQL>SELECT cod_pais,pais FROM paises WHERE cod_pais='#PARAMETRO_1#'</SQL>
  </opcion>
</OpcionesDisponibles>
Ahora, supongamos que desde PHP deseamos tener una función que dado el nombre del método, nos devuelva la SQL a ejecutar. La solución es tan simple como la siguiente:
// Dado un nombre de opción, buscar en el xml su SQL correspondiente
function getSQL($nombreOpcion)
{
  $xmlOpciones = simplexml_load_file('opciones.xml');
  $sql = ""; 
  foreach ($xmlOpciones->opcion as $opcion)
  {
    $nombre = $opcion->nombre;
    if ($nombre == $nombreOpcion)
    {
      $sql = $opcion->SQL;
      break;
    }
  }
  return $sql;
}
Así de sencillo.

Consumir un WebService XML desde .NET

En esta entrada publicamos una función que nos permite consumir un webservice XML y pasarlo a un DataTable, de forma que podamos trabajar con los datos de manera muy sencilla. La función es la siguiente:
Public Shared Function GetDataTable_WebServiceXML(opcion As String, listaParametros As String) As Data.DataTable
  Try
    Dim url As String = "http://url.com/WebService.asmx/GetOpcion"
    url += "?nombre=" + opcion + "&parametros=" + listaParametros

    Dim request As HttpWebRequest
    Dim response As HttpWebResponse = Nothing
    Dim ds As New Data.DataSet

    request = DirectCast(WebRequest.Create(url), HttpWebRequest)
    response = DirectCast(request.GetResponse(), HttpWebResponse)
    ds.ReadXml(response.GetResponseStream())

    If ds.Tables.Count > 0 Then
      Return ds.Tables(0)
    Else
      Return New Data.DataTable
    End If

  Catch ex As Exception
    Throw New Exception(ex.Message)
  End Try
End Function
Con el código de esta pequeña función, obtendremos un datatable con los resultados obtenidos. Si fuera necesario podríamos modificarla para devolver un DataSet o directamente el contenido del XML.

Registros de SQL hacia XML/JSON

Nuestra aplicación de gestión en la empresa está desarrollada en .NET y utilizando base de datos SQL Server. Se trata de una aplicación de escritorio, y debido a ciertas necesidades, hemos construido un WebService para hacer disponibles ciertos datos desde el exterior, para que sean consumidos por la web de eCliente y por varias apps.

Hemos configurado el webservice para que devuelva los datos en el formato deseado, XML o JSON, así quien lo consuma podrá elegir cómo quiere los datos. En eCliente utilizamos .NET, por lo que se hace más sencillo obtener los resultados en un XML (directamente creamos un DataSet a partir de él se hace mucho más fácil su gestión), y en las apps lo consumimos con JSON.

En ambos casos nos hemos encontrado con un problema: tenemos registros que tienen caracteres que, bien hacen que se rompan el XML, o bien el HTML, debido a que contienen caracteres no permitidos para estos formatos.

Para evitar este problema, hemos creado una función escalar en SQL Server que nos reemplaza los caracteres no deseados para que el XML/JSON sea correcto. La función es la siguiente:
USE [BaseDatos]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[CampoToHTML] (@texto varchar(256)) returns varchar(max)
begin
   declare @resul varchar(max)
   set @resul = @texto
   set @resul = REPLACE(@resul, char(34), char(39))
   set @resul = REPLACE(@resul, 'ñ' COLLATE Latin1_General_CS_AS,'n')
   set @resul = REPLACE(@resul, 'á' COLLATE Latin1_General_CS_AS,'a')
   set @resul = REPLACE(@resul, 'é' COLLATE Latin1_General_CS_AS,'e')
   set @resul = REPLACE(@resul, 'í' COLLATE Latin1_General_CS_AS,'i')
   set @resul = REPLACE(@resul, 'ó' COLLATE Latin1_General_CS_AS,'o' )
   set @resul = REPLACE(@resul, 'ú' COLLATE Latin1_General_CS_AS,'u')
   set @resul = REPLACE(@resul, 'Ñ' COLLATE Latin1_General_CS_AS,'N')
   set @resul = REPLACE(@resul, 'Á' COLLATE Latin1_General_CS_AS,'A')
   set @resul = REPLACE(@resul, 'É' COLLATE Latin1_General_CS_AS,'E')
   set @resul = REPLACE(@resul, 'Í' COLLATE Latin1_General_CS_AS,'I')
   set @resul = REPLACE(@resul, 'Ó' COLLATE Latin1_General_CS_AS,'O')
   set @resul = REPLACE(@resul, 'Ú' COLLATE Latin1_General_CS_AS,'U')
   set @resul = REPLACE(@resul, '&' COLLATE Latin1_General_CS_AS,'y')
   return @resul
END
De esta forma, la consulta SQL la haríamos de la siguiente forma:
SELECT id,dbo.CampoToHTML(apellidos) FROM Clientes
Esto es todo.

Consumir un webservice desde PHP (XML/JSON)

Cuando trabajamos con PHP, es muy habitual encontrarnos con la necesidad de realizar la llamada a un webservice para obtener una serie de resultados para después trabajar con ellos. Existen múltiples formas de conseguir esto, y en este post vamos a mostrar dos posibilidades muy sencillas para conseguirlo. Mostraremos dos ejemplos, uno que recibe los resultados en formato XML y otro en formato JSON. Una vez recibidos los resultados, recorremos la información obtenida para mostrarla por pantalla.

Si el webservice devuelve resultados en XML
<?php
  // Llamada al WebService
  $client = new SoapClient("http://www.webservicex.net/country.asmx?WSDL");
  $result = $client->GetCountries();
  $xml = $result->GetCountriesResult;

  // procesar xml
  $xml = simplexml_load_string($xml);
  foreach($xml->Table as $table) 
  {
    $output .= "<p>$table->Name</p>";
  }
  print_r($output);
?>

Si el webservice devuelve resultados en JSON
<?php
// Función para llamar al webservice y devolver el resultado en un array
function callWebService($method)
{
  $url ='http://api.geonames.org/citiesJSON?north=44.1&south=-9.9&east=-22.4&west=55.2&lang=de&username=demo';
  $json = file_get_contents($url);
  $array = json_decode($json,true);
  return $array;
}
Esa misma función puede optimizarse en una sóla línea:
function callWebService($method)
{
  return json_decode(file_get_contents('http://api.geonames.org/citiesJSON?north=44.1&south=-9.9&east=-22.4&west=55.2&lang=de&username=demo'),true);;
}
La llamada podría se la siguiente:
$resul = callWebService();
foreach($resul['geonames'] as $city)
{
    $cities .= '<p>'.$city['name'].'</p>';    
}
print_r ($cities);

Espero os sea de utilidad. Si deseas obtener más información, puedes consultar la documentación de php.

martes, 1 de julio de 2014

SEPA (Zona Única de Pagos en Euros). Estándar de intercambio bancario

SEPA (Single Euro Payments Area) es un nuevo estándar para la comunicación con las entidades financieras, incluyendo lo relativo a domiciliaciones bancarias, transferencias y pagos, entre países de la Unión Europea.

La entrada en vigor de SEPA supone que se dejan de utilizar los cuadernos bancarios (CB 19, etc) actuales para las comunicaciones con el banco, para pasar a utilizar la nueva definición basada en el intercambio de ficheros XML. Me ha tocado trabajar duramente en nuestra aplicación para tenerlo todo listo y a tiempo, convirtiéndonos en una de las primeras empresas en utilizar el estándar, hasta tal punto de establecer un periodo de pruebas y colaboración con entidades bancarias para implantar la nueva normativa. He aprovechado para, al mismo tiempo, realizar toda la conversión de cuentas del formato tradicional CCC al nuevo IBAN/BIC, todo un reto que había de realizarse sin que nadie notara nada.

Una de las cosas que se deben tener en cuenta para implantar la normativa SEPA es que se debe disponer de un sistema de control de los documentos firmados por el cliente en los cuales autoriza a la empresa a que le realice cargos en su cuenta, ya que dichos documentos deben ser comunicados a la entidad bancaria en cada comunicación. Toda esta información y todo lo relativo a la normativa puede consultarse desde su página oficial.

jueves, 2 de enero de 2014

EIAC: Hacia un nuevo estandar

EIAC son las siglas de Estándar de Intercambio de Información entre Entidades Aseguradoras y Mediadores. Actualmente me encuentro trabajando en una empresa del mundo del seguro, y además contamos en ella con uno de los principales impulsores y creadores de este proyecto. En este sector es complicado trabajar con distintas compañías, dado que cada una funciona de una forma diferente al no haber un estándar común, lo que hace que cada aseguradora tome sus propias decisiones en cuanto a las comunicaciones con sus corredores. Unas funcionan con ficheros excel, otras con ficheros planos, otras sólo a través de su web (aquí entran en juego otros problemas, con distintos navegadores y versiones de Java, que hacen que unas web funcionen y otras no, lo que obliga a tener distintos navegadores con distintas configuraciones, pero eso es otro tema). Se hace muy difícil mantener un software de comunicación con las distintas compañías ya que no existe nada común.


Con la intención de resolver estos problemas nace la idea de crear este estándar, que impulsamos con fuerza desde nuestra empresa. Para realizar el estándar contamos con la colaboración de Tirea, en cuyas oficinas de Madrid se llevan a cabo reuniones entre corredores, aseguradoras y empresas de software del sector para llegar a los acuerdos necesarios para sacar adelante un estándar.

La idea es disponer de una forma única de solicitar y recibir información, utilizando el intercambio de ficheros XML, del estilo al que se utilizan en otras áreas como las interconexiones bancarias (con el formato SEPA que ya se ha comentado en este blog). Además, vamos un paso más allá y no queremos quedarnos sólo con el estándar, sino que se quiere poner en marcha una zona común de intercambio (cloud, plataforma en la nube como se llama ahora) que vele por que se cumplen todos los requisitos y esquemas del estándar en el intercambio de información.

Por estos días, estoy encargado, además de colaborar en la definición del estándar, en ir implantando el mismo en nuestro software de gestión.

Prácticamente todas las aseguradas, corredores, y empresas de software del sector se encuentran al día respecto a la definición de este estándar que ya se está convirtiendo en una realidad. La información relativa al proyecto es abierta y pública, y puede encontrarse pulsando aquí.

 

Copyright @ 2015 Tosblama