Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Validar firma de factura electrónica (formato Facturae) (https://www.clubdelphi.com/foros/showthread.php?t=56079)

iMia 25-01-2015 23:29:28

Como te he comentado, he reescrito todos los tipos de nuevo, sin nada de los namespaces.
A ver si manana te poongo el codigo completo del tipo facturae, para que veas lo simple (y mal para otros casos) que lo he dejado.

lithium76 25-01-2015 23:42:48

Sería de gran utilidad, muchas gracias.. aquí está una parte del mío (la de los nodos principales, todo no me deja por excesivamente largo) tal como salen del Data Binding por si queda más claro lo que quería decir

Código Delphi [-]
const
  TargetNamespace = 'http:....Facturae';

implementation

{ Global Functions }

function GetFacturae(Doc: IXMLDocument): IXMLFacturae;
begin
  Result := Doc.GetDocBinding('Facturae', TXMLFacturae, TargetNamespace) as IXMLFacturae;
end;

function LoadFacturae(const FileName: string): IXMLFacturae;
begin
  Result:= LoadXMLDocument(FileName).GetDocBinding('Facturae', TXMLFacturae, TargetNamespace) as IXMLFacturae;
end;

function NewFacturae: IXMLFacturae;
begin
  Result := NewXMLDocument.GetDocBinding('Facturae', TXMLFacturae, TargetNamespace) as IXMLFacturae;
end;

{ TXMLFacturae }

procedure TXMLFacturae.AfterConstruction;
begin
  RegisterChildNode('FileHeader', TXMLFileHeaderType);
  RegisterChildNode('Parties', TXMLPartiesType);
  RegisterChildNode('Invoices', TXMLInvoicesType);
  RegisterChildNode('Extensions', TXMLExtensionsType);
  RegisterChildNode('Signature', TXMLSignatureType_ds);
  inherited;
end;

iMia 26-01-2015 08:37:45

Como verás lo he simplificado al máximo. y escribo el xml casi de forma literal

Código:

/// Tipo TFacturae
type
  TFacturae = class
  private
    fFileHeader:  TFileHeader;
    fParties:    TParties;
    fInvoices:    TInvoices;
//    fExtensions:  TExtensions;
  public
    constructor Create;
    ///
    function ToXml: IXMLDOMElement;
    ///
    property FileHeader: TFileHeader  read fFileHeader  write fFileHeader;
    property Parties:    TParties    read fParties    write fParties;
    property Invoices:  TInvoices    read fInvoices    write fInvoices;
//    property fExtensions: TExtensions  read fExtensions  write fExtensions;
  end;

{ TFacturae }

  XMLNode_eFact_32_Facturae                                    = 'fe:Facturae';
    XMLNode_eFact_32_FileHeader                                  = 'FileHeader';
    XMLNode_eFact_32_SchemaVersion                                  = 'SchemaVersion';
    XMLNode_eFact_32_Modality                                    = 'Modality';
    XMLNode_eFact_32_InvoiceIssuerType                            = 'InvoiceIssuerType';

constructor TFacturae.Create;
begin
  fFileHeader := TFileHeader.Create;
  fParties    := TParties.Create;
  fInvoices  := TInvoices.Create;
end;

function TFacturae.ToXml: IXMLDOMElement;
var
  XMLDoc: IXMLDOMDocument;
  XMLElement: IXMLDOMElement;
begin
  XMLDoc := CoFreeThreadedDOMDocument30.Create;
  try
    XMLElement := XMLDoc.createElement( XMLNode_eFact_32_Facturae );
    if XMLElement <> nil then
    begin
      XMLElement.AppendChild(Self.fFileHeader.ToXml);
      XMLElement.AppendChild(Self.fParties.ToXml);
      XMLElement.AppendChild(Self.fInvoices.ToXml);
    end;
    result := XMLElement;
  finally
  end;
end;


type
  TFileHeader = class
  private
    fSchemaVersion:    string; // (E)
    fModality:          string; // (E)
    fInvoiceIssuerType: string; // (E)
//    fThirdParty:              TThirdParty;
    fBatch:            TBatch;
//    fFactoringAssignmentData: TFactoringAssignmentData;
  public
    constructor Create;

    function ToXml: IXMLDOMNode;

    property SchemaVersion:    string read fSchemaVersion      write fSchemaVersion;
    property Modality:              string read fModality          write fModality;
    property InvoiceIssuerType: string read fInvoiceIssuerType  write fInvoiceIssuerType;
    property Batch:                  TBatch read fBatch              write fBatch;
  end;

{ FFileHeaderType }

  C_SchemaVersion_3_2 = '3.2';

  C_Modality_Individual = 'I';

  C_PersonTypeCode_Fisica  = 'F';
  C_PersonTypeCode_Juridica = 'J';

  C_ResidenceTypeCodeType_R = 'R';  /// - Residente en España
  C_ResidenceTypeCodeType_U = 'U';  /// - Residente en la UE

  C_InvoiceIssuerType_Emisor        = 'EM';

constructor TFileHeader.Create;
begin
  fSchemaVersion      := C_SchemaVersion_3_2_1;
  fModality          := C_Modality_Individual;
  fInvoiceIssuerType  := C_InvoiceIssuerType_Emisor;
  fBatch              := TBatch.Create;
end;

function TFileHeader.ToXml: IXMLDOMNode;
var
  XMLElement: IXMLDOMElement;
begin
  XMLElement := NewElementNode( nil, XMLNode_eFact_32_FileHeader );
  if XMLElement <> nil then
  begin
    XMLElement.appendChild(NewTextNode(XMLElement, XMLNode_eFact_32_SchemaVersion, Self.fSchemaVersion, 0));
    XMLElement.appendChild(NewTextNode(XMLElement, XMLNode_eFact_32_Modality, Self.fModality, 0));
    XMLElement.appendChild(NewTextNode(XMLElement, XMLNode_eFact_32_InvoiceIssuerType, Self.fInvoiceIssuerType, 0));
    XMLElement.appendChild(Self.fBatch.ToXml);
  end;
  result := XMLElement;
end;

...

p.d.: Està hecho para Delphi5...

lithium76 26-01-2015 16:17:53

Perdón pero he andado liado y no he podido responder antes... Pues es un gran trabajo, interesante la aproximación que has hecho al problema y la manera que has encontrado de resolverlo.. Me lo miraré más a fondo a ver si consigo rehacer mi código también . una lástima que el binding no consiga hacerlo directamente :( ¡Muchísimas gracias!

olbeup 27-01-2015 15:15:01

Yo tenía el mismo problema y lo resolví aquí, con la ayuda de Al González

Un saludo.

lithium76 27-01-2015 16:15:36

¡Muchas gracias, olbeup! ¡Muy amable! Gran aporte este post que has puesto.. Una pregunta, si me permites, tu no trabajas a partir de la interface del Data Binding, no? ¿ Son todo IXMLNode's, que vas colocando según correspndo no?

olbeup 28-01-2015 08:37:59

Cita:

Empezado por lithium76 (Mensaje 488189)
¡Muchas gracias, olbeup! ¡Muy amable! Gran aporte este post que has puesto.. Una pregunta, si me permites, tu no trabajas a partir de la interface del Data Binding, no? ¿ Son todo IXMLNode's, que vas colocando según correspndo no?

Si, desde el IXMLDocument que es el principal y los IXMLNotes el resto.

Un saludo.

Kribbeling 04-02-2015 21:33:23

Cita:

Empezado por iMia (Mensaje 488108)
Como verás lo he simplificado al máximo. y escribo el xml casi de forma literal

Código:

/// Tipo TFacturae
type
  TFacturae = class
  private
    fFileHeader:  TFileHeader;
    fParties:    TParties;
    fInvoices:    TInvoices;
//    fExtensions:  TExtensions;
  public
    constructor Create;
    ///
    function ToXml: IXMLDOMElement;
    ///
    property FileHeader: TFileHeader  read fFileHeader  write fFileHeader;
    property Parties:    TParties    read fParties    write fParties;
    property Invoices:  TInvoices    read fInvoices    write fInvoices;
//    property fExtensions: TExtensions  read fExtensions  write fExtensions;
  end;

{ TFacturae }

  XMLNode_eFact_32_Facturae                                    = 'fe:Facturae';
    XMLNode_eFact_32_FileHeader                                  = 'FileHeader';
    XMLNode_eFact_32_SchemaVersion                                  = 'SchemaVersion';
    XMLNode_eFact_32_Modality                                    = 'Modality';
    XMLNode_eFact_32_InvoiceIssuerType                            = 'InvoiceIssuerType';

constructor TFacturae.Create;
begin
  fFileHeader := TFileHeader.Create;
  fParties    := TParties.Create;
  fInvoices  := TInvoices.Create;
end;

function TFacturae.ToXml: IXMLDOMElement;
var
  XMLDoc: IXMLDOMDocument;
  XMLElement: IXMLDOMElement;
begin
  XMLDoc := CoFreeThreadedDOMDocument30.Create;
  try
    XMLElement := XMLDoc.createElement( XMLNode_eFact_32_Facturae );
    if XMLElement <> nil then
    begin
      XMLElement.AppendChild(Self.fFileHeader.ToXml);
      XMLElement.AppendChild(Self.fParties.ToXml);
      XMLElement.AppendChild(Self.fInvoices.ToXml);
    end;
    result := XMLElement;
  finally
  end;
end;


type
  TFileHeader = class
  private
    fSchemaVersion:    string; // (E)
    fModality:          string; // (E)
    fInvoiceIssuerType: string; // (E)
//    fThirdParty:              TThirdParty;
    fBatch:            TBatch;
//    fFactoringAssignmentData: TFactoringAssignmentData;
  public
    constructor Create;

    function ToXml: IXMLDOMNode;

    property SchemaVersion:    string read fSchemaVersion      write fSchemaVersion;
    property Modality:              string read fModality          write fModality;
    property InvoiceIssuerType: string read fInvoiceIssuerType  write fInvoiceIssuerType;
    property Batch:                  TBatch read fBatch              write fBatch;
  end;

{ FFileHeaderType }

  C_SchemaVersion_3_2 = '3.2';

  C_Modality_Individual = 'I';

  C_PersonTypeCode_Fisica  = 'F';
  C_PersonTypeCode_Juridica = 'J';

  C_ResidenceTypeCodeType_R = 'R';  /// - Residente en España
  C_ResidenceTypeCodeType_U = 'U';  /// - Residente en la UE

  C_InvoiceIssuerType_Emisor        = 'EM';

constructor TFileHeader.Create;
begin
  fSchemaVersion      := C_SchemaVersion_3_2_1;
  fModality          := C_Modality_Individual;
  fInvoiceIssuerType  := C_InvoiceIssuerType_Emisor;
  fBatch              := TBatch.Create;
end;

function TFileHeader.ToXml: IXMLDOMNode;
var
  XMLElement: IXMLDOMElement;
begin
  XMLElement := NewElementNode( nil, XMLNode_eFact_32_FileHeader );
  if XMLElement <> nil then
  begin
    XMLElement.appendChild(NewTextNode(XMLElement, XMLNode_eFact_32_SchemaVersion, Self.fSchemaVersion, 0));
    XMLElement.appendChild(NewTextNode(XMLElement, XMLNode_eFact_32_Modality, Self.fModality, 0));
    XMLElement.appendChild(NewTextNode(XMLElement, XMLNode_eFact_32_InvoiceIssuerType, Self.fInvoiceIssuerType, 0));
    XMLElement.appendChild(Self.fBatch.ToXml);
  end;
  result := XMLElement;
end;

...

p.d.: Està hecho para Delphi5...

Muy Buenas ,

Esta es mi primera (bueno segunda) vez , no se si lo hago correctamente, en cualquier caso gracias.

Veo que has implementado codigo para la facturae, podrias pasarme algun ejemplo o las clases, muchas gracias .

Kribbeling 04-02-2015 21:48:54

Cita:

Empezado por iMia (Mensaje 488011)
Manuel, muchas gracias por tu rapidisima respuesta...
Estoy intentando mirar de firmar unicamente el XML con Xades (nada de PDFs), y voy a buscar primero si lo puedo hacer sin componentes. Mirare a traves de alguna dll o algo asi. Ya que puedo generar el xml y en las plataformas de envio del xml a las administraciones publicas, dentro hay la opción de firmar gratuitamente con sus applets... por eso mirar de no pagar y repercutir el gasto a mis "ClientesDeGorra"
Si no al final acabare con SBB...
ademas la app esta hecha con Delphi 5... casi nada...



Buenas ,
No lo he mirado bien pero en ftp://ftp.zlatkovic.com/libxml/Delphi/ creo que tienes un ejemplo para firmar xml con las libXML y openssl.

Yo estoy empezando con todo este tema y si me pudieras pasar algun ejemplo o algo te lo agradeceria , x cierto creo que ya te lo he pedido en otro post.

Muchas gracias y un saludo .

iMia 11-02-2015 16:01:09

Para el tema de la firma... desde delphi sólo con componentes de terceros $$ o €€ ...

Yo lo voy a solucionar de otra forma...

La AEAT/Ministerio/estado/etc... da las clases para firmar... pero en JAVA.... :(

Pues a hacerlo en java y hacer un shellexecute...

Empiezo las pruebas de firma... iré comentando....

MasDelphi 11-02-2015 16:33:17

Buenas tardes.
También estoy en la misma situación que iMia y Manuel. Actualmente he logrado hacer la factura con el formato xml y validado por la página del ministerio.
El problema es que no logro validar la firma, he visto los componentes de SecureBlackBox, pero no son compatibles con Delphi 5. Actualmente estoy probando con OpenSSL, pero no he llegado a obtener buenos resultados.
Gracias por vuestra ayuda y consejos.

newtron 11-02-2015 16:48:23

Cita:

Empezado por iMia (Mensaje 488681)
Para el tema de la firma... desde delphi sólo con componentes de terceros $$ o €€ ...

Yo lo voy a solucionar de otra forma...

La AEAT/Ministerio/estado/etc... da las clases para firmar... pero en JAVA.... :(

Pues a hacerlo en java y hacer un shellexecute...

Empiezo las pruebas de firma... iré comentando....

Estupendo. Cualquier ayuda en ese sentido se agradece.

iMia 11-02-2015 16:55:55

Cita:

Empezado por Kribbeling (Mensaje 488442)
Buenas ,
No lo he mirado bien pero en ftp://ftp.zlatkovic.com/libxml/Delphi/ creo que tienes un ejemplo para firmar xml con las libXML y openssl.

Yo estoy empezando con todo este tema y si me pudieras pasar algun ejemplo o algo te lo agradeceria , x cierto creo que ya te lo he pedido en otro post.

Muchas gracias y un saludo .

Lo he mirado, esta bién , pero no me sirve... :(
No firma xml en formato Xades enveloped, que es el que se necesita para la efactura.
Como he comentado en el mensaje de encima, la única forma gratuita es con las clases de la AEAT, pero son clases java. hay que crear un programa en java (.jar) que use esas clases para firmar con 3 parametros, el xml, el certificado y el ficherode salida (".xml" firmado ... ".xsig") y llamarlo con un shell execute....

iMia 11-02-2015 17:31:56

Aquí estan las clases en java para firmar...

http://oficinavirtual.mityc.es/compo...des/index.html

iMia 12-02-2015 09:09:57

Cita:

Empezado por aposi
Cita:

Empezado por iMia
Cita:

Empezado por aposi
Hola iMia,
he visto que generas el xml para la Efactura.
Me podrias passar un ejemplo de com lo generas? es que nunca he trabajado con xml y con el XML Data Binding tengo algunos problemas.
Si fueras tanamable de passar como generas el arxivo y si tienes solucionado el tema de la firma estaria muy agradecido

Hola aposi,

No es complicado, es laborioso, por que yo me he creado las clases de cada tipo de dato, (manualmente, ya que con el Databinding no se puede, ya que el extractor de clases a partir del xsd no funciona bien si hay referencias externas) y en cada clase he creado el metodo ToXML que genera los nodos.
Todas las clases anidadas, de esa forma al crear el objeto "padre" se crean todas las clases "hijas" y solo hay que rellenarlas con datos y llar al método TOXML que devuelve los nodos del XML.

mira el código que puse...

a partit de aquí crear las clases TFileHeader, TParties, etc...

Me podrias passar el codigo que te has creado si no es mucha molestia?

Hombre... ya he puesto lo básico, para tener un punto de patida... que ya es pero que mucho...;)
Para ponerme en el camino yo solito, sin orientación, tardé un par de semanas... y un par de semanas en tener la serialización fina y a mi gusto... por que la herramineta que he comentado que sí serializa no era de mi gusto lo que dejaba...
He dado pistas y codigo para tener más de la mitad de la faena hecha... y utilizando el serializador, sería toda la faena hecha... pero para hacerla hay que leer mucho y comprender bien que hay que hacer...
Si te pongo todo el código y te doy hecho todo mi trabajo... ¿me pagas lo mismo que mi empresa por ese mes de trabajo? :rolleyes:

Casimiro Notevi 12-02-2015 10:14:03

Cita:

Empezado por iMia (Mensaje 488709)
Si te pongo todo el código y te doy hecho todo mi trabajo... ¿me pagas lo mismo que mi empresa por ese mes de trabajo? :rolleyes:

No es necesario ese tipo de comentarios, si quieres compartir tu código lo compartes y si no quieres, entonces mejor no digas nada. Aquí compartimos código y todo ese código es fruto de nuestro trabajo, encontrarás programas completos que se han compartido, utilidades, trucos, código de toda clase y tipo, algunos han costado poco hacerlo y otros son trabajo de meses o años.
Pero por eso estamos aquí, para compartir nuestros conocimientos, no para decirle a los demás que "a mí me costó un mes de trabajo, ¿me lo pagarás?"
Espero que lo hayas compartido, y en caso contrario, este no es tu sitio.

iMia 12-02-2015 10:52:18

Cita:

Empezado por Casimiro Notevi (Mensaje 488712)
No es necesario ese tipo de comentarios, si quieres compartir tu código lo compartes y si no quieres, entonces mejor no digas nada. Aquí compartimos código y todo ese código es fruto de nuestro trabajo, encontrarás programas completos que se han compartido, utilidades, trucos, código de toda clase y tipo, algunos han costado poco hacerlo y otros son trabajo de meses o años.
Pero por eso estamos aquí, para compartir nuestros conocimientos, no para decirle a los demás que "a mí me costó un mes de trabajo, ¿me lo pagarás?"
Espero que lo hayas compartido, y en caso contrario, este no es tu sitio.

Estoy comentando, explicando los pasos que he hecho, compartiendo , aportando mis pocos conocimientos con los demás, explicando los problemas que me he econtradom, para que los demás no los tengan que sufrir, poniendo parte del código que he hecho ...
Pero me insiste en que se lo pase todo... un foro es para compartir, que es lo que estoy haciendo, para ayudar y encaminar, que es lo que he hecho, para ahorrar horas de investigación, que es lo que he hecho... No para hacerle el trabajo a los demás... por que "como nunca he trabajo con XML"... leches, ni yo antes tampoco... pero ahora sí... por que he leido, investigado, he probado, me he equivocado, vamos, que he aprendido... y no por que me lo han dado hecho sin tener yo que hacer ningún esfuerzo...y sabes de sobras que en todos los foros, de este tipo de gente hay mucha... que sus únicas aportaciones son pedir código y luego silencio...

P.D.: Si no soy bienvenido, y a parte de aportar mi reducida experiencia y problemas que me he encontrado, estoy obligado a poner todo el codigo... pues tambien se dice... y me largo por donde he venido... sin problemas...

Casimiro Notevi 12-02-2015 11:00:38

A ver, iMia, tienes razón, peeero... me refiero a "las formas", te entiendo perfectamente, somos los primeros que ante casos de ese tipo, no hacemos el trabajo a los demás. Pero no le decimos que nos ha costado un mes de trabajo y que nos lo pague.
Lo que hacemos es indicarle un tutorial, preguntarle en qué parte tiene problemas, qué cosas es la que no entiende, etc. o sea, ayudar a encaminarlo.
Desde luego, que el que llega y dice: "tengo que hacer esto, pasadme el código", lo mandamos a tomar.........

iMia 12-02-2015 11:19:05

Yo tambien entiendo tu postura como moderador, que conste.
Pero después de indicarle 2 veces, que mire lo que he puesto, que ya he puesto código, lo que he explicado , por donde ir, qué utilizar para que no tenga que hacer casi nada... me sigue insistiendo... es que, se vé claramente que ni se ha leido las 40 páginas del esquema de la eFactura, ni lo compara con el codigo que he puesto, es que si hubiese hecho un minimo esfuerzo, vería claramente por donde seguir...
Por eso me he "encendido" un poco... por que no pregunta... "tengo un problema aquí o allí..." si no que... "me puedes pasar tu codigo"...
Tampoco creo que le haya dicho DIRECTAMENTE... "me lo vas a pagar?"... en el sentido que quiero que me lo pague.. si no que le he intentado hacer ver que lo que pide tiene un coste de tiempo (y el tiempo es oro...) , muy grande para pedir todo e insistir, con emoticonos, para que no fuese una respuesta seca...

Casimiro Notevi 12-02-2015 11:27:20

Tienes razón, porque algunos no quieren aprender, sino que le den el trabajo hecho.
Disculpa si he sido un poco bruto, es que es difícil entender "el tono" de lo que ha escrito otra persona cuando no puedes verle la cara, su expresión, sus gestos, etc.


La franja horaria es GMT +2. Ahora son las 12:21:39.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi