PDA

Ver la Versión Completa : Consumir Webservice


darkerbyte
10-11-2012, 20:11:55
Hola mi gente del club.

Necesito desarrollar una app que se comunique con un servidor, le envíe ciertos arrays de caracteres para obtener una factura electrónica.
Este servidor no recibe XML sino cadenas de datos "normales", lo cual en teoría debe facilitar la programación. Además se puede obtener un PDF y una imagen de código de barras bidimensional.

Ya me estuve documentando pero no encontré mucha información útil, por eso acudo a su invaluable ayuda.

Ya usé el WSDL importer que proporciona Delphi 7 para obtener la unidad WSDL que la que muestro a continuación:



// ************************************************************************ //
// The types declared in this file were generated from data read from the
// WSDL File described below:
// WSDL : https://www.fel.mx/ConexionRemotaCFDI32/ConexionRemota32.asmx?WSDL
// Encoding : utf-8
// Version : 1.0
// (09/11/2012 02:11:37 p.m. - 1.33.2.5)
// ************************************************************************ //

unit ConexionRemota32;

interface

uses InvokeRegistry, SOAPHTTPClient, Types, XSBuiltIns;

type

// ************************************************************************ //
// The following types, referred to in the WSDL document are not being represented
// in this file. They are either aliases[@] of other types represented or were referred
// to but never[!] declared in the document. The types from the latter category
// typically map to predefined/known XML or Borland types; however, they could also
// indicate incorrect WSDL documents that failed to declare or import a schema type.
// ************************************************************************ //
// !:string - "http://www.w3.org/2001/XMLSchema"


ArrayOfString = array of WideString; { "https://www.fel.mx/ConexionRemotaCFDI" }

// ************************************************************************ //
// Namespace : https://www.fel.mx/ConexionRemotaCFDI
// soapAction: https://www.fel.mx/ConexionRemotaCFDI/%operationName%
// transport : http://schemas.xmlsoap.org/soap/http
// binding : ConexionRemota32Soap
// service : ConexionRemota32
// port : ConexionRemota32Soap
// URL : https://www.fel.mx/ConexionRemotaCFDI32/ConexionRemota32.asmx
// ************************************************************************ //
ConexionRemota32Soap = interface(IInvokable)
['{E4A3238C-F777-D8FE-02E9-DAF81F6A193C}']
function GenerarCFDIv32(const datosUsuario: ArrayOfString; const datosReceptor: ArrayOfString; const datosCFDI: ArrayOfString; const etiquetas: ArrayOfString; const conceptos: ArrayOfString;
const informacionAduanera: ArrayOfString; const retenciones: ArrayOfString; const traslados: ArrayOfString; const retencionesLocales: ArrayOfString; const trasladosLocales: ArrayOfString
): ArrayOfString; stdcall;
function GenerarCodigoBidimensional(const datosUsuario: ArrayOfString; const UUID: WideString): ArrayOfString; stdcall;
function CancelarCFDI(const datosUsuario: ArrayOfString; const ListaACancelar: ArrayOfString): ArrayOfString; stdcall;
function EnviarCFDI(const datosUsuario: ArrayOfString; const UUID: WideString; const email: WideString): ArrayOfString; stdcall;
function ObtenerPDF(const datosUsuario: ArrayOfString; const UUID: WideString): ArrayOfString; stdcall;
function ObtenerNumeroCreditos(const datosUsuario: ArrayOfString): ArrayOfString; stdcall;
end;

function GetConexionRemota32Soap(UseWSDL: Boolean=System.False; Addr: string=''; HTTPRIO: THTTPRIO = nil): ConexionRemota32Soap;


implementation

function GetConexionRemota32Soap(UseWSDL: Boolean; Addr: string; HTTPRIO: THTTPRIO): ConexionRemota32Soap;
const
defWSDL = 'https://www.fel.mx/ConexionRemotaCFDI32/ConexionRemota32.asmx?WSDL';
defURL = 'https://www.fel.mx/ConexionRemotaCFDI32/ConexionRemota32.asmx';
defSvc = 'ConexionRemota32';
defPrt = 'ConexionRemota32Soap';
var
RIO: THTTPRIO;
begin
Result := nil;
if (Addr = '') then
begin
if UseWSDL then
Addr := defWSDL
else
Addr := defURL;
end;
if HTTPRIO = nil then
RIO := THTTPRIO.Create(nil)
else
RIO := HTTPRIO;
try
Result := (RIO as ConexionRemota32Soap);
if UseWSDL then
begin
RIO.WSDLLocation := Addr;
RIO.Service := defSvc;
RIO.Port := defPrt;
end else
RIO.URL := Addr;
finally
if (Result = nil) and (HTTPRIO = nil) then
RIO.Free;
end;
end;


initialization
InvRegistry.RegisterInterface(TypeInfo(ConexionRemota32Soap), 'https://www.fel.mx/ConexionRemotaCFDI', 'utf-8');
InvRegistry.RegisterDefaultSOAPAction(TypeInfo(ConexionRemota32Soap), 'https://www.fel.mx/ConexionRemotaCFDI/%operationName%');
RemClassRegistry.RegisterXSInfo(TypeInfo(ArrayOfString), 'https://www.fel.mx/ConexionRemotaCFDI', 'ArrayOfString');

end.




Ya la importé en la unidad de mi proyecto, como pueden ver, hay 5 funciones, ahorita estoy intentando con ObtenerNumeroCreditos, que es la más básica. Esta me devuelve el numero de créditos que el usuario aun dispone para facturar, 1 crédito = 1 factura.
En el API nos indican que el parámetro de entrada USUARIO es un array de 3 pocisiones con id, usuario y contraseña respectivamente.

Pero de aquí no sé como seguir la verdad :confused: Lo que se me ocurrió fue esta función:


procedure TForm1.Button1Click(Sender: TObject);
var
resultado, usuario : ArrayofString;
i : integer;
fel : ConexionRemota32Soap;
begin
i:=0;
SetLength(usuario,3);
usuario[0]:='DEMO323416FEL';
usuario[1]:='DEMO323416FEL';
usuario[2]:='Link2701$';

resultado := fel.ObtenerNumeroCreditos(usuario);
Memo1.Lines.Add(resultado[0]);


Me compila pero me genera una excepcion por violación de dirección :(
Jiji ya se que ando bien perdido por eso les pido ayuda.
Un saludo y muchas gracias de antemano

darkerbyte
10-11-2012, 23:19:27
Estoy probando un camino un poco diferente.
Ahora coloqué en mi form un componente de tipo tHTTPRIO y al que le di la dirección del WSDL y automaticamente obtuvo los siguientes parámetros:


converter: HTTPRIO1.Converter1
-> options: [soSendMultiRefObj,soTryAllSchema,soRootRefNodesToBody,soCacheMimeResponse,soUTF8EncodeXML]
HTTPwebNode: HTTPRIO1.HTTPWebNode1
Name: HTTPRIO1
Port: ConexionRemota32Soap
Service: ConexionRemota32
WSDLLocation: https://www.fel.mx/ConexionRemotaCFDI32/ConexionRemota32.asmx?WSDL


Y modifiqué el método así:


procedure TForm1.Button1Click(Sender: TObject);
var
resultado, usuario : ArrayofString;
i : integer;
fel : ConexionRemota32Soap;
begin
i:=0;
SetLength(usuario,3);
usuario[0]:='DEMO320024FEL';
usuario[1]:='DEMO320024FEL';
usuario[2]:='Link2801$';
SetLength(resultado,1);
resultado := (HTTPRIO1 as ConexionRemota32Soap).ObtenerNumeroCreditos(usuario);
Memo1.Lines.Add(resultado[0]);
end;


Ahora, cuando lo ejecuto me manda este error:


Project Fel.exe raised exception class EREmotableException with message
'Server was unable to process request. --->
Object reference no set to an instance of an object'
Process stoped. Use Step or Run to continue


Si mi hipótesis no es incorrecta, ya se esta conectando al servidor pero el servidor esta regresando un error.
Pero no se si el error es mío por mandale parámetros incorrectos en la llamada del método ó estoy haciendo otra cosa mal.

Gracias de nuevo por su ayuda

CSIE
11-11-2012, 14:19:23
Sería algo como así

var
fel : ConexionRemota32Soap;
resultado, usuario : ArrayofString;
begin
fel := GetConexionRemota32Soap(true, '', nil);
SetLength(usuario,3);
usuario[0]:='DEMO320024FEL';
usuario[1]:='DEMO320024FEL';
usuario[2]:='Link2801$';
resultado := fel.ObtenerNumeroCreditos(usuario);
if High(resultado) > 0 then
Memo1.Lines.Add(resultado[0]);
end;

edorantes
17-11-2012, 00:41:45
Me mada este error
les dejo la url
s3.subirimagenes.com:81/imagen/previo/thump_8127733error.png

Alguna idea
intente con esto
procedure TForm1.Button1Click(Sender: TObject);

var

resultado, usuario : ArrayofString;

i : integer;

fel : ConexionRemota32Soap;



begin

i:=0;

SetLength(usuario,3);

usuario[0]:='DEMO323416FEL';

usuario[1]:='DEMO323416FEL';

usuario[2]:='Link2701$';



fel := GetConexionRemota32Soap(true,'',nil);

resultado := fel.ObtenerNumeroCreditos(usuario);

Memo1.Lines.Add(resultado[0]);
end;

CSIE
17-11-2012, 08:42:16
Consultando en https://www.fel.mx/ConexionRemotaCFDI32/ConexionRemota32.asmx?op=ObtenerNumeroCreditos se puede ver que el array usuario espera dos elementos y parece que también devuelve dos elementos.

¿Estas seguro de lo que defines en el array USUARIO?

Si es asi, prueba a cambiar esto


SetLength(resultado,2);
fel := GetConexionRemota32Soap(false,'',nil);

darkerbyte
17-11-2012, 20:59:50
Gracias a todos los amigos que se tomaron tiempo para responder:
Ya logramos que se haga la conexión de manera exitosa y consumir el webservice.
A continuación pongo cómo quedó el método:


procedure TForm1.Button1Click(Sender: TObject);
var
resultado, usuario: ArrayofString;
i: integer;
fel: ConexionRemota32Soap;

begin

Memo1.Lines.Clear;
SetLength(usuario,3);
usuario[0]:='DEMO323016FEL';
usuario[1]:='DEMO323016FEL';
usuario[2]:='Link2701$';


fel := GetConexionRemota32Soap(true,'',nil);
resultado := fel.ObtenerNumeroCreditos(usuario);
for i := 0 to High(resultado) do
Memo1.Lines.Add(resultado[i]);
end;



Vamos a ver que tal nos va ahora tratando de obtener el PDF y el PNG del código de barras. Lo posteamos por si a alguien le sirve nuestro método.