* ---
* Actualización 2018-16-20: Se actualiza el ejemplo, código e imágenes.
* ---
Que tal Colegas.
Este artículo es para mostrarles como podemos invocar cualquier Web Service desde Visual FoxPRO.
Primero quisiera comentar, que NO soy un experto en ésto de los WEB service's, pero he tomado algo de experiencia en el uso de los mismos. En éste artículo trataré de explicarlo con palabras simples.
Es importante leer al respecto, siempre es sencillo encontrar información en
Wikipedia.
Vamos comenzando por la lógica de "ejecución" de un web service:
1. Creamos la petición de ejecución de una función del Web Service, ésto se llama XML REQUEST.
2. Enviamos el REQUEST al web service, la cual es una URL que termina con wsdl.
3. Obtenemos un XML RESPONSE, que es el resultado de haber invocado la función específica del WS.
Vamos por partes:
Para saber como es el REQUEST, utilizo una aplicación Open Source llamada soapUI, la cual pueden descargar desde:
http://www.soapui.org/
Lo descargamos, al abrir el soapUI vemos ésto:
La URL del web service es:
http://www.gencfd.com/wsEjemplo/index.php?wsdl
Con ésto, soapUI interperta las funciones que existen en ése WebService, y nos crea un ejemplo de REQUEST por cada una de ellas, en éste caso observaremos como el REQUEST de la función SUMA:
Hasta aquí, tenemos cubierto el paso 1 de la ejecución de un Web Service, el dos es simple.. damos clic en el botón de "PLAY" y se cumple el segundo paso, al mismo tiempo que obtenermos el XML RESPONSE:
Bien, como hacemos ésto con FoxPRO:
Al conocer la estructura del XML Request, pues lo creamos con FoxPRO, usen el método que a ustedes les parezca mejor, en lo personal me agrada la utileria Free de
Chilkat, pero para el ejemplo crearé el Request con TEXT.. ENDTEXT
He creado una clase para consumir WS, en ella muestro el ejemplo anterior en código, está comentada por lo que creo no es necesario hablar más al respecto.
Va el código:
oWS = CREATEOBJECT( "VFP_WebService","http://www.gencfd.com/wsEjemplo/index.php?wsdl")
lcRespuesta = oWS.Suma(10,8)
IF oWS.iStatus != 0
MESSAGEBOX(oWS.sError,16,"Error al ejecutar WS")
ELSE
MESSAGEBOX(lcRespuesta,64,"EjecutandoWS desde VFP - PortalFOX")
ENDIF
* -- Ahora usando el ActiveX de Chilkat --
* -- **http://www.chilkatsoft.com/ChilkatXml.asp** --
lcRespuesta = oWS.Suma_Chilkat(10,8)
IF oWS.iStatus != 0
MESSAGEBOX(oWS.sError,16,"Error al ejecutar WS")
ELSE
MESSAGEBOX(lcRespuesta,64,"EjecutandoWS desde VFP usando Chilkat - PortalFOX")
ENDIF
DEFINE CLASS VFP_WebService AS CUSTOM
* --- Definimos las propiedades ---
sError = ""
iStatus = 0
sURL_WS = ""
* --- Definimos la función del WebService ---
FUNCTION Suma(tnI, tnJ)
* --- Paso 1. Creo el XML Request ---
lcXMLRequest = this.CreaRequest(tnI, tnJ)
lsXMLResponse = ADDBS(SYS(2023)) + SYS(2015) + [.xml]
* --- Paso 2. Ejecuto el WS | Paso 3. Obtengo el Response ---
this.iStatus = this.EjecutaWS( this.sURL_WS, lcXMLRequest , lsXMLResponse )
IF this.iStatus != 0 && Ocurrió un error el cual está especificado en sError.
RETURN ""
ENDIF
lcXMLResponse = FILETOSTR(lsXMLResponse)
* --- Parseamos el XML Response ---
* --- Para el ejemplo está así, manejando texto, ustedes deben manejar XML (falta de tiempo, perdón) ---
lcRespuestaWS = STREXTRACT(lcXMLResponse ,[<res xsi:type="xsd:integer">],[</res>])
this.borraArchivo(lsXMLResponse)
RETURN lcRespuestaWS
ENDFUNC
*---------------------------------------------------
FUNCTION EjecutaWS(tcURL_WSDL, tcFileRequest , tsFileResponse )
*---------------------------------------------------
TRY
oHTTP = CREATEOBJECT('Msxml2.ServerXMLHTTP.6.0')
oHTTP.OPEN("POST", tcURL_WSDL, .F.)
oHTTP.setRequestHeader("User-Agent", "EjecutandoWS desde VFP - PortalFOX")
oHTTP.setRequestHeader("Content-Type", "text/xml;charset=utf-8")
oHTTP.SEND(tcFileRequest)
CATCH TO loErr
this.sError = "Error: " + TRANSFORM(loErr.ErrorNo) + " Mensaje: " + loErr.Message
this.iStatus = -1
ENDTRY
IF this.iStatus != 0
RETURN -1
ENDIF
* --- Si el status es diferente a 200, ocurrió algún error de conectividad con el WS ---
IF oHTTP.STATUS = 200
lcRespuestaWS = oHTTP.responseText
* --- Se genera el XML del response | Este es el paso 3!! ---
STRTOFILE(STRCONV(lcRespuestaWS ,9),tsFileResponse)
this.iStatus = 0
this.sError = ""
RETURN 0
ELSE
this.sError = "Error: No se logró la conexión con el Web Service."
this.iStatus = -1
RETURN -1
ENDIF
ENDFUNC
*---------------------------------------------------
*---------------------------------------------------
FUNCTION CreaRequest(tnI, tnJ)
*---------------------------------------------------
TEXT TO lcXMLRequest TEXTMERGE PRETEXT 7 NOSHOW
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:suma">
<soapenv:Header/>
<soapenv:Body>
<urn:suma soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<i xsi:type="xsd:integer"><<tnI>></i>
<j xsi:type="xsd:integer"><<tnJ>></j>
</urn:suma>
</soapenv:Body>
</soapenv:Envelope>
ENDTEXT
RETURN lcXMLRequest
ENDFUNC
*---------------------------------------------------
*---------------------------------------------------
FUNCTION CreaRequest_Chilkat(tnI, tnJ)
*---------------------------------------------------
loXml = CreateObject('Chilkat.Xml')
loXml.Encoding = "UTF-8"
loXml.Tag = "soapenv:Envelope"
loXml.AddAttribute("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance")
loXml.AddAttribute("xmlns:xsd","http://www.w3.org/2001/XMLSchema")
loXml.AddAttribute("xmlns:soapenv","http://schemas.xmlsoap.org/soap/envelope/")
loXml.AddAttribute("xmlns:urn","urn:suma")
loXml = loXml.NewChild("soapenv:Header","")
loXml.GetRoot2()
loXml = loXml.NewChild("soapenv:Body","")
loXml = loXml.NewChild("urn:suma","")
loXml.AddAttribute("soapenv:encodingStyle","http://schemas.xmlsoap.org/soap/encoding/")
loXml = loXml.NewChild("i",tnI)
loXml.AddAttribute("xsi:type","xsd:integer")
loXml.GetParent2()
loXml = loXml.NewChild("j",tnJ)
loXml.AddAttribute("xsi:type","xsd:integer")
loXml.GetRoot2()
RETURN loXML.getxml()
ENDFUNC
*---------------------------------------------------
FUNCTION GetChilkatPath
*---------------------------------------------------
* Esta función obtiene el resultado de evaluar
* un Chilkat Xml Path. Para mas referencia
* revisar: http://www.chilkatsoft.com/refdoc/xChilkatXmlRef.html
LPARAMETERS etPath,spXml
loXml = CreateObject('Chilkat.Xml')
lnSuccess = loXml.LoadXmlFile(spXML)
IF (lnSuccess = 0) THEN
this.sError = "Error de parse en el archivo xml"+ loXml.LastErrorText
this.iStatus = -999
RETURN ""
ENDIF
loXml.GetRoot2()
lcTemp = loXml.ChilkatPath(etPath)
loXML = .null.
RELEASE loXML
RETURN IIF(ISNULL(lcTemp),"",lcTemp)
ENDFUNC
*---------------------------------------------------
*---------------------------------------------------
FUNCTION Suma_Chilkat(tnI, tnJ)
* --- Paso 1. Creo el XML Request ---
lcXMLRequest = this.CreaRequest_Chilkat(tnI, tnJ)
lsXMLResponse = ADDBS(SYS(2023)) + SYS(2015) + [.xml]
* --- Paso 2. Ejecuto el WS | Paso 3. Obtengo el Response ---
this.iStatus = this.EjecutaWS( this.sURL_WS, lcXMLRequest , lsXMLResponse )
IF this.iStatus != 0 && Ocurrió un error el cual está especificado en sError.
RETURN ""
ENDIF
lcRespuestaWS = this.GetChilkatPath("/C/SOAP-ENV:Envelope|SOAP-ENV:Body|ns1:sumaResponse|res|*",lsXMLResponse )
this.borraArchivo(lsXMLResponse )
RETURN lcRespuestaWS
ENDFUNC
*---------------------------------------------------
FUNCTION BorraArchivo(tsFile)
*---------------------------------------------------
IF FILE(tsFile)
DELETE FILE (tsFile)
ENDIF
ENDFUNC
*---------------------------------------------------
*---------------------------------------------------
* Evento constructor
PROCEDURE Init
*---------------------------------------------------
LPARAMETERS tcURLWS
this.sURL_WS = tcURLWS
this.iStatus = 0
this.sError = ""
ENDPROC
*---------------------------------------------------
ENDDEFINE
Pueden descargar el código desde
aquí.
Suerte con sus Web Services!!
Baltazar Moreno
http://disxii.com
VFP9SP2 - Win7
Guadalajara, Jalisco, México