soap generico

Iniciado por adla, 28 Noviembre 2020, 21:14 PM

0 Miembros y 1 Visitante están viendo este tema.

adla

hola,

estoy buscando algo generico en VB6 que sirva para todos los servicios web del mundo de esta forma, he probado todo lo que he visto por la red pero solo me ha funcionado una consulta con un servicio para la conversin de grados C a F y ademas he tenido que cambiar cosas porque eran antiguo, aun asi no es generico solo funciona con ese ejemplo y no tiene usuario y contraseña.. No se si es posible lo que digo.

Url del servicio: https://....

Usuario: usu
Clave: 123

Consulta: <?xml version..>

[boton:pulsa para enviar consulta y obtener respuesta]

Respuesta: <...

gracias.

Serapis

Con toda la diversificación de tecnologías, realmente crees que va a existir una librería "que sirva para todos los servicios web del mundo" ???. Es muy ingenuo por tu parte...

BlackZeroX

#2
Cita de: Serapis en 29 Noviembre 2020, 16:46 PM
Con toda la diversificación de tecnologías, realmente crees que va a existir una librería "que sirva para todos los servicios web del mundo" ???. Es muy ingenuo por tu parte...

ejem ejem para SOAP/Rest si ejem ejem de hecho eso mismo me dije que ingenuo soy pero me puse a leer un poco los RFC de la 3w y vi que todo era solo ''texto'' (Hablando de forma abstracta) enviado por un protocolo X... y es que necesitaba hacer en donde laboro un "Consumidor" de servicios genérico que ejecutara cualquier tipo de servicio REST/SOAP bajo HTTP/HTTPS, vaya cada 2 semanas los modifican (a;adiendo o removiendo que no se deciden los tipos) y necesitaba ser lo mas eficiente posible en ver mis series y tener poco estrés laboral y si estuviera recodificando los clientes a cada momento se me acumularían cada 15 días que me llegara algo a consumir.

El truco esta en usar SOCKETS y conectarte al servicio como un vil cliente HTTP/HTTPS y enviar peticiones viles como un cliente común y corriente después parseas los datos obtenidos con un parser XML o JSON o el tipo de dato que envies y con eso ya tienes un cliente GENERICO de servicios WEB.

Esta es mi versión para JAVA (Nunca quise manejar JAVA pero es el lenguaje que ya me da de comer), se que es un foro de VB6 al rato me instalo el VB6 y genero una versión pero igual les sirve para entender el protocolo de servicios SOAP por que a la primera asusta...

La siguiente clase la hice de esta forma y no use FRAMEWORKS de JAVA por que los frameworks no me permitían capturar los request/response de un POOL de hilos ya que compartían el mismo cache haci que me tuve que bajar a crear mi cliente pero que no estuviera bajo JAXB ya que de igual forma requería tener una catalogo de endpoints, describir los métodos en BDD etc, etc, en fin que es genérico hoy en día y consume lo que desee en la secuencia que desee a tal grado que puedo consumir un servicio mas rápido que con los frameworks, en fin solo les comparto esta clase el resto es a imaginación, obviamente el request y response se manejan en otras clases las cuales no axeso por que no es el tema de mis parsers.

Debajo del código describo como funciona.

Código (java) [Seleccionar]


package mx.com.common.service;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLConnection;
import java.rmi.RemoteException;
import java.util.Date;
import java.util.Date;

import javax.annotation.Generated;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSocketFactory;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import mx.com.common.utils.ElapseTime;

/**
* Clase para generar clientes a SOAP
*
* @author Miguel Angel Ortega Avila
*/
@SuppressWarnings("all")
public class SoapServiceClient implements ServiceClient {

private final static Logger LOG = LogManager.getLogger(SoapServiceClient.class);

private String user;
private final String pass;
private final String endpoint;
private final ElapseTime elapseTime;

private static SSLSocketFactory sslSocketFactory;

private int timeout;
private Date startTime = null;
private SOAPBody currentBody;
private String currentRequest;
private String currentResponse;

@Generated("SparkTools")
public SoapServiceClient(String user, final String pass, final String endpoint, final int timeout) {
this.endpoint = endpoint;
this.user = user;
this.pass = pass;
this.elapseTime = ElapseTime.getInstance();
this.timeout = timeout;
}

public String getCurrentRequest() {
return currentRequest;
}

public String getCurrentResponse() {
return currentResponse;
}

public SOAPMessage execute(String request) throws RemoteException {
URL url;
URLConnection conexion = null;
currentRequest = request;
currentResponse = null;
try {
elapseTime.start();
startTime = new Date();
url = new URL(this.endpoint);
conexion = url.openConnection();
if (url.getProtocol().equalsIgnoreCase("https")) {
((HttpsURLConnection) conexion).setSSLSocketFactory(sslSocketFactory);
}
((HttpURLConnection) conexion).setRequestProperty("Content-Type", "text/xml");
((HttpURLConnection) conexion).setRequestMethod("POST");
((HttpURLConnection) conexion).setConnectTimeout(this.timeout);
((HttpURLConnection) conexion).setReadTimeout(this.timeout);
} catch (final MalformedURLException e) {
throw new RemoteException("WS-SOAPService - Endpoint erroneo", e);
} catch (final ProtocolException e) {
throw new RemoteException("WS-SOAPService - Error al consumir servicio", e);
} catch (final IOException e) {
throw new RemoteException("WS-SOAPService - Error al consumir servicio", e);
}

HttpURLConnection httpURLConnection = (HttpURLConnection) conexion;
conexion.setDoOutput(true);
OutputStreamWriter out = null;
StringBuilder sb = new StringBuilder();
int returnCode;
BufferedReader buff = null;
try {
// Obligatorio para algunas versiones de SOAP (Emulacion).
httpURLConnection.setRequestProperty("SOAPAction", "");
out = new OutputStreamWriter(httpURLConnection.getOutputStream());
out.write(request);
out.flush();
returnCode = httpURLConnection.getResponseCode();
InputStream conexionIn;
if (returnCode >= 200 && returnCode < 300) {
conexionIn = httpURLConnection.getInputStream();
} else {
conexionIn = httpURLConnection.getErrorStream();
}
buff = new BufferedReader(new InputStreamReader(conexionIn));
String inputline;
while ((inputline = buff.readLine()) != null) {
sb.append(inputline);
}
httpURLConnection.disconnect();
currentResponse = sb.toString();
} catch (final SocketTimeoutException e) {
throw new RemoteException(e.getMessage(), e);
} catch (final IOException e) {
throw new RemoteException(e.getMessage(), e);
} finally {
elapseTime.stop();
if (buff != null)
try {
buff.close();
} catch (IOException e) {
LOG.error("WS-SOAPService - Error al cerrar Stream", e);
}
if (out!= null) {
try {
out.close();
} catch (IOException e) {
LOG.error("WS-SOAPService - Error al cerrar Stream", e);
}
}
}
InputStream is = new ByteArrayInputStream(sb.toString().getBytes());
SOAPMessage soapResponse;
SOAPPart part;
SOAPEnvelope env;
SOAPBody body;
SOAPHeader head;
try {
soapResponse = MessageFactory.newInstance().createMessage(null, is);
soapResponse.removeAllAttachments();
part = soapResponse.getSOAPPart();
part.detachNode();
env = part.getEnvelope();
env.detachNode();
body = env.getBody();
body.detachNode();
head = env.getHeader();
if (head != null)
head.detachNode();
} catch (final IOException e) {
throw new RemoteException("(HTTP " + returnCode + ") - " + e.getMessage(), e);
} catch (final SOAPException e) {
throw new RemoteException("(HTTP " + returnCode + ") - " + e.getMessage(), e);
} finally {
if (is != null)
try {
is.close();
} catch (IOException e) {
LOG.error("WS-SOAPService - Error al cerrar Stream", e);
}
}
if (body != null && body.hasFault()) {
throw new RemoteException(body.getFault().getTextContent(), null);
}
return soapResponse;
}

public String getHeaderSecurityXML() {
StringBuilder strbl = new StringBuilder();
strbl.append(
"<wsse:Security xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\" xmlns:SOAP-ENV=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\" SOAP-ENV:encodingStyle=\"\" actor=\"\" mustUnderstand=\"0\" SOAP-ENV:mustUnderstand=\"0\">");
strbl.append(
"<wsse:UsernameToken xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" wsu:id=\"UsernameToken\" xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\">");
strbl.append(
"<wsse:Username xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\">");
strbl.append(user).append("</wsse:Username>");
strbl.append(
"<wsse:Password Type=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText\" xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\">");
strbl.append(pass).append("</wsse:Password>");
strbl.append("</wsse:UsernameToken>");
strbl.append("</wsse:Security>");
return strbl.toString();
}

public String getUser() {
return user;
}

public String getPass() {
return pass;
}

public int getTimeout() {
return timeout;
}

@Override
public long getElapsedTime() {
return this.elapseTime.getElapsedTime();
}

@Override
public Date getStartTime() {
return this.startTime;
}
}



La teoría es la siguiente para vb6 y cualquier lenguaje.

Necesitamos un cliente básico para HTTP/HTTPS o el protocolo transporte, simularlo con sockets o alguna librería básica (https://www.chilkatsoft.com/refdoc/xChilkatHttpResponseRef.html) que permita este protocolo del servicio SOAP.

El resto ya es solo trabajo de los Request y Response

(Instalar la versión Open Source)
https://www.soapui.org/downloads/soapui/

Si se desea consumir un servicio SOAP solo debemos conocer el request y response (Usaremos SOAPUI para esto, explicar aquí el formato es complicado por ello es mejor usar esta herramienta, solo hay que ir a File -> New Soap Project ingresar el endpoint y consumes un método del servicio para obtener el request).

Una vez obtenido el request solo hay que enviarlo por nuestro cliente en vb6.

Si deseamos anexar usuario y contraseña se debe poner los siguientes headers a el request (wsse:Username y wsse:Password):

El método del Enpoint se debe consumir de la siguiente forma suponiendo que el endpoint es:

http://www.webservicex.net/globalweather.asmx?wsdl
y tiene dos métodos llamados
hola1
metodoX

y quiero llamar a metodoX

Se llamaría bajo HTTP
Se consume bajo POST
Anexar a la llamada el header "Content-Type" con el valor "text/xml"
Anexar a la llamada el header "SOAPAction" con valor vacío ""
Envio el request siguiente el cual indica que se debe ejecutar "metodoX"

Código (xml) [Seleccionar]

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:mod="http://blackzerox.com.mx">
<soapenv:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:SOAP-ENV="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" SOAP-ENV:encodingStyle="" actor="" mustUnderstand="0" SOAP-ENV:mustUnderstand="0">
<wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:id="UsernameToken" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:Username xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">BlackZeroX</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">MiContrasenia123456789</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<mod:metodoX>
<objeto1>
<campo1></campo1>
<campo2></campo2>
<objetoAnidado>
<objetoAnidadoID></objetoAnidadoID>
</objetoAnidado>
<systemId></systemId>
</objeto1>
<nombre>Miguel Angel</nombre>
<apellidoM>Avila</apellidoM>
<apellidoP>Ortega</apellidoP>
<expresiones>
<suma>
<![CDATA[
1+5
]]>
</suma>
<default>
<![CDATA[
<8)
]]>
</default>
<obsolete>no</obsolete>
<value>69</value>
</expresiones>
</mod:metodoX>
</soapenv:Body>
</soapenv:Envelope>


y al enviar por sockets responderia algo asi

Código (xml) [Seleccionar]

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<metodoXResponse xmlns="http://blackzerox.com.mx">
<Response xmlns=">
<productOrderID></productOrderID>
<responseStatus>
<rejectCode>XXX</rejectCode>
<rejectDescription>descripcion XXX metodoX</rejectDescription>
<status>true</status>
</responseStatus>
</Response>
</metodoXResponse>
</soapenv:Body>
</soapenv:Envelope>


Si puedo hacer correr un día de estos en mi equipo VB6 armo un cliente genérico en VB6.

SOAP y REST son bajo la misma teoria... o muy parecida.

Saludos.
The Dark Shadow is my passion.