Ir al contenido


Foto

Probando lazarus con los comprobantes fiscales digitales del sat


  • Por favor identifícate para responder
39 respuestas en este tema

#1 axesys

axesys

    Advanced Member

  • Moderadores
  • PipPipPip
  • 640 mensajes
  • LocationLos Mochis

Escrito 31 marzo 2010 - 08:05

Pues eso aprovechando que voy a estar de vacaciones me dio por hacer un programita en lazarus que me genere un comprobante fiscal digital con las especificaciones del sat.

Bueno para empezar ya descargue e instale lazarus.

Ahora según leo en las páginas del sat tengo que seguir estos pasos

1. Usar este archivo xsd como lo dice aquí para crear un xml el cual después tengo que convertir a una cadena original con este xslt

2. Esa cadena original se convierte a un sello digital usando unos archivos .cer, .key y una contraseña que están aquí

3. El sello digital se obtiene de aplicar el hash md5 en la cadena original, al hash obtenido se encripta con el algoritmo RSA usando el archivo .key y la contraseña del archivo Cer_Sello.zip, los bytes encriptados se deben convertir a letras con una codificación que se llama Base64 por lo que dice aquí.

4. Por último el archivo .cer se abre con el algoritmo x509, se obtiene su serie y se le agrega como un atributo "noCertificado" al xml, luego se codifica en Base64 los bytes y se agrega la cadena obtenida al xml como un atributo "Certificado", al final tambien se agrega otro atributo llamado "sello" que va tener la cadena en base64 obtenida en el paso anterior con lo que nos queda un xml firmado.

Bueno eso es lo que se hasta ahorita así que si alguien sabe algo más haber si lo puede compartir aquí. Mientras tanto yo voy a tratar de hacerlo y voy a ir subiendo lo que me vaya saliendo de los pasos anteriores.

  • 0

#2 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.448 mensajes
  • LocationMéxico

Escrito 31 marzo 2010 - 08:12

Que interesante amigo axesys, gracias por compartir.

Salud OS
  • 0

#3 Héctor Randolph

Héctor Randolph

    501st Legion

  • Moderadores
  • PipPipPip
  • 664 mensajes
  • LocationMéxico

Escrito 31 marzo 2010 - 09:07

Bueno, eso es básicamente lo que se tiene que hacer para crear un comprobante fiscal digital (CFD). De hecho el SAT utiliza el mismo algoritmo que acabas de describir para firmar cualquier documento digitalmente. En el caso particular de los CFD's solamente se sella la cadena original más no todo el documento y en lugar de firma electrónica avanzada se llama certificado para sellos digitales.

Con respecto a los algoritmos de encriptación yo utilicé la biblioteca OpenSSL con una adaptación hecha para Delphi que puedes descargar desde aquí .  Pero como OpenSSL está desarrollada con lenguaje C yo creo que lo podrás utilizar en Lazarus sin problemas.

Con esta bilbioteca tienes funciones para leer certificados x509, tienes los algoritmos RSA, MD5, Base64 y puedes leer las llaves privadas aunque no directamente en el formato que te envía el SAT debes convertirlas antes de abrirlas con OpenSSL.

Veo que vas avanzado con el proyecto ya que una buena parte consiste en documentarse y entender de qué se trata el asunto, ahora solo falta llevarlo al código.

Saludos
  • 0

#4 axesys

axesys

    Advanced Member

  • Moderadores
  • PipPipPip
  • 640 mensajes
  • LocationLos Mochis

Escrito 01 abril 2010 - 02:23

Gracias Hector ahora mismo checo haber si puedo hacer jalar la biblioteca que comentas con lazarus.


Saludos
  • 0

#5 axesys

axesys

    Advanced Member

  • Moderadores
  • PipPipPip
  • 640 mensajes
  • LocationLos Mochis

Escrito 02 abril 2010 - 02:14

Pues aquí les comparto lo que logre hacer con la biblioteca que recomendo hector.

Primero descargue el openssl para windows de aquí, luego tuve que convertir el archivo .key como comento hector con openssl usando este comando que encontre aquí


delphi
  1. openssl pkcs8 -inform DER -in AAA010101AAA_0408021316S.key -out AAA010101AAA.key.pem



Despues agregue la bioblioteca de la liga que puso hector nomas que no me compilaba hasta que le cambie el modo a delphi en las opciones del compilador y de la misma página copie este ejemplo para usar el hash md5 y el algoritmo rsa además de otras funciones que estan en este otro ejemplo.

Para la parte de codificar en base64 encontre este ejemplo que usa la unidad base64 que ya trae lazarus.

Y para el ejemplo de cadena original use la que se encuentra en esta página del sat.

En el archivo adjunto viene el código de todo esto ya junto que convierte la cadena original siguiente:
||A|1|2005-09-02T16:30:00|1|ISP900909Q88|Industrias del Sur Poniente, S.A. de C.V.|Alvaro Obregón|37|3|Col. Roma Norte|México|Cuauhtémoc|Distrito Federal|México|06700|Pino Suarez|23|Centro|Monterrey|Monterrey|Nuevo Léon|México|95460|CAUR390312S87|Rosa María Calderón Uriegas|Topochico|52|Jardines del Valle|Monterrey|Monterrey|Nuevo León|México|95465|10|Caja|Vasos decorados|20|200|1|pieza|Charola metálica|150|150|IVA|52.5||

En este sello digital:
p7hGSgj1aHWWkibqXWj3PL03HgwqONdjOaWjvH1ayRPx/ZPOuocxXBnLNteNpZBMsw+vjJhT7eElrkdO/+5VOu0Eai/zjwbZgSsOOEhjSzIkL0s35d9w/CcqDDj1zsmlOnQr5y9d+8cOZoPHP07r5jq10IhNQcPw4RhXo+CV71k=

Ahora voy a buscar haber como le hago para manejar los xml así que si alguien tiene alguna información al respecto haber si la puede compartir  :cheesy:.

Archivos adjuntos


  • 0

#6 axesys

axesys

    Advanced Member

  • Moderadores
  • PipPipPip
  • 640 mensajes
  • LocationLos Mochis

Escrito 02 abril 2010 - 03:01

Buscando información de como usar los xml para los cfd di con este post que les comparto por si alguien quiere hacerlo en delphi.


Saludos
  • 0

#7 Héctor Randolph

Héctor Randolph

    501st Legion

  • Moderadores
  • PipPipPip
  • 664 mensajes
  • LocationMéxico

Escrito 02 abril 2010 - 01:40

Amigo Axesys debo felicitarte por lo mucho que has avanzado en tan poco tiempo. Estoy algo sorprendido ya que estás a un paso de resolver este asunto de los comprobantes fiscales digitales. Lo mejor de todo es que estás utilizando Lazarus y herramientas OpenSource me alegro mucho.

Debo señalar que en el momento en que a mi me tocó hacer esta investigación encontré poca información en la red y además quienes ya habían logrado echar a andar los comprobantes fiscales se negaban a compartir sus avances e incluso encontré personas que cobran por darte asesoría. Es verdad que el conocimiento tiene su precio yo no digo que no deba ser así, en ocasiones la información pertenece a la empresa para la cual trabajas y no puedes publicarla, por eso siempre es bueno encontrar personas como tú que no teman a compartir con los demás sus experiencias e incluso subir el código fuente por si alguien lo necesita.

Saludos y gracias.
  • 0

#8 axesys

axesys

    Advanced Member

  • Moderadores
  • PipPipPip
  • 640 mensajes
  • LocationLos Mochis

Escrito 02 abril 2010 - 08:49

Gracias a ti hector porque sin la liga de la biblioteca para usar openssl a lo mejor y hubiera tardado más.

Ahora estoy probando unas bibliotecas para manipular xml que al igual que openssl estan hechas en c y tambien se pueden acceder desde delphi usando una adaptación que encontre aquí.

Luego les cuento como me fue.


Saludos
  • 0

#9 axesys

axesys

    Advanced Member

  • Moderadores
  • PipPipPip
  • 640 mensajes
  • LocationLos Mochis

Escrito 03 abril 2010 - 05:42

Ahora les comparto como generar la cadena original usando la biblioteca para windows de libxslt, el xml a convertir lo copie de aquí porque el archivo de muestra que esta en la página del sat con la cadena original de ejemplo es para la versión 1 y no funciona con el xslt que mencione en el primer post.

Nota: Para que me dejara subir el archivo borre la biblioteca libeay32.dll que ya viene en el primer ejemplo que subi.


Saludos

Archivos adjuntos


  • 0

#10 felipep

felipep

    Newbie

  • Miembros
  • Pip
  • 3 mensajes

Escrito 03 abril 2010 - 10:44

Hey, he estado trabajando en lo mismo, pero en la cadena que colocas, a mi me aparece los siguiente

iCflad7c1gqlRSa1yy507ZtdtJ+WPGmx5duoqHaOkSymecQMJmLBjD6r3G/7isuJKR6QUQXjYteM9ppXcQ3K/
hxAhCFAXYjA9PIjWruqvftyLUobRSxraWdaQw3pH4IFq1MxgThd15P5xxTkmcEz34rM23/fdyTTip8PUJugUTy

Y no me queda el mismo resultado, utlizando el mismo archivo pem...

Para codificar en base64 utilizo el siguiente algoritmo que encontré:



delphi
  1. function TFunciones.Encode64(S: string): string;
  2. const
  3.   Codes64 = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/';
  4. var
  5.   i: Integer;
  6.   a: Integer;
  7.   x: Integer;
  8.   b: Integer;
  9. begin
  10.   Result := '';
  11.   a := 0;
  12.   b := 0;
  13.   for i := 1 to Length(s) do
  14.   begin
  15.     x := Ord(s[i]);
  16.     b := b * 256 + x;
  17.     a := a + 8;
  18.     while a >= 6 do
  19.     begin
  20.       a := a - 6;
  21.       x := b div (1 shl a);
  22.       b := b mod (1 shl a);
  23.       Result := Result + Codes64[x + 1];
  24.     end;
  25.   end;
  26.   if a > 0 then
  27.   begin
  28.     x := b shl (6 - a);
  29.     Result := Result + Codes64[x + 1];
  30.   end;
  31. end;






  • 0

#11 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.448 mensajes
  • LocationMéxico

Escrito 03 abril 2010 - 12:13

Hola felipep bienvenido a DelphiAccess

Salud OS
  • 0

#12 luk2009

luk2009

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.040 mensajes
  • LocationSanto Domingo

Escrito 03 abril 2010 - 02:01

Bienvenido a DelphiAccess felipep y a este tu foro de Lazarus (y)
  • 0

#13 axesys

axesys

    Advanced Member

  • Moderadores
  • PipPipPip
  • 640 mensajes
  • LocationLos Mochis

Escrito 04 abril 2010 - 05:45

Hey, he estado trabajando en lo mismo, pero en la cadena que colocas, a mi me aparece los siguiente

iCflad7c1gqlRSa1yy507ZtdtJ+WPGmx5duoqHaOkSymecQMJmLBjD6r3G/7isuJKR6QUQXjYteM9ppXcQ3K/
hxAhCFAXYjA9PIjWruqvftyLUobRSxraWdaQw3pH4IFq1MxgThd15P5xxTkmcEz34rM23/fdyTTip8PUJugUTy

Y no me queda el mismo resultado, utlizando el mismo archivo pem...

Para codificar en base64 utilizo el siguiente algoritmo que encontré:


Hola felipep, mejor intenta con esta porque usando cadenas de pascal a veces se cortan yo por eso ahora mejor la uso con bytes



delphi
  1. function BinToBase64(const PDat: PBYTE; const DatLen: DWORD): string;
  2. const BaseTable: string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  3. var s, s1: string;
  4. i, p, len, n, Addnum: DWORD;
  5. PBin: PBYTE;
  6. begin
  7. result := '';
  8. S := '';
  9. addnum := 0;
  10. PBin := PDat;
  11. for i := 1 to DatLen do
  12. begin
  13. S := S + IntToHex(PBin^, 2);
  14. PBin := PBYTE(DWORD(PDat) + i);
  15. end;
  16. case (length(s) mod 3) of
  17. 0: addnum := 0;
  18. 1: begin
  19. s := s + '00';
  20. addnum := 2;
  21. end;
  22. 2: begin
  23. s := s + '0';
  24. addnum := 1;
  25. end;
  26. end;
  27. len := length(s) div 3;
  28. for i := 1 to len do
  29. begin
  30. s1 := midstr(S, i * 3 - 2, 3);
  31. p := strtoint('$' + s1);
  32. n := p div 64;
  33. result := result + basetable[n + 1];
  34. n := p mod 64;
  35. result := result + basetable[n + 1];
  36. end;
  37. if addnum = 1 then result := result + '==';
  38. if addnum = 2 then result[length(result)] := '=';
  39. end;       




Saludos
  • 0

#14 axesys

axesys

    Advanced Member

  • Moderadores
  • PipPipPip
  • 640 mensajes
  • LocationLos Mochis

Escrito 04 abril 2010 - 05:58

Esta versión incluye varias correcciones, como el que se pueda ejecutar varias veces porque antes no liberaba memoria y marcaba violaciones de acceso. Otra es un cambio para codificar en base64 usando bytes en lugar de cadenas porque sino se me regresaba incompleto el sello. Y uno más cuando se desifra con el algoritmo rsa ahora en lugar de usar arreglos fijos se usan dinamicos ya que si estaban fijos al aumentar los conceptos se regresaba mal el sello.

Tambien incluye para leer y escribir el xml con el sello, el numero y certificado público el cual se puede validar en esta aplicación del sat.


Saludos

Archivos adjuntos


  • 0

#15 German

German

    Member

  • Miembros
  • PipPip
  • 40 mensajes

Escrito 04 abril 2010 - 07:52

La FCL incluye por defecto un modulo para codificar/decodificar en base64 orientado a flujos de bytes (packages\fcl-base\src\base64.pp).

Tambien incluye los headers par opssl (packages\openssl\src\openssl.pas).

No olviden pegarle un visazo siempre a la RTL y a la FCL que estan llenas de sorpresas.

Saludos.
  • 0

#16 felipep

felipep

    Newbie

  • Miembros
  • Pip
  • 3 mensajes

Escrito 04 abril 2010 - 10:54

Hola, muchas gracias por tu respuesta... He estado estudiando detenidamente los archivos que mandaste y han sido de gran ayuda.

Sólo tengo un problema que espero me puedas ayudar---  La función StrPCopy funciona con arreglos char; sin embargo la tienes con un arreglo de bytes y me marca error ¿Cómo pudiste hacerla jalar así?

Luego, las funciones LoadXMLFile(Doc, xmlOrigen) y WriteXMLFile(Doc, xmlDestino) no jalan en Delphi ¿De qué librería se obtienen?

Yo intenté con Nodo := Doc.DocumentElement.ChildNodes[1], pero no funciona con IDOMNode... De cualquier forma esto se puede resolver escribiendo directo en el XML con XMLDocument.

Y por último, si pudieras ayudarme, te lo agradecería tremendamente: en la función que mandaste para codificar de bin a base64, le debes poner un parámetro PByte, pero GetSello entrega ya sea un array de char o, en tu caso (sea como sea que lo hayas logrado hacer jalar), un arreglo de bytes... De cualquier forma sigo trabajando en esto...

Te agradezco mucho toda la ayuda que haz subido, ya que poca gente publicaría un trabajo así.

Saludos ;)
  • 0

#17 axesys

axesys

    Advanced Member

  • Moderadores
  • PipPipPip
  • 640 mensajes
  • LocationLos Mochis

Escrito 04 abril 2010 - 11:19

Hola, muchas gracias por tu respuesta... He estado estudiando detenidamente los archivos que mandaste y han sido de gran ayuda.

Sólo tengo un problema que espero me puedas ayudar---  La función StrPCopy funciona con arreglos char; sin embargo la tienes con un arreglo de bytes y me marca error ¿Cómo pudiste hacerla jalar así?

Luego, las funciones LoadXMLFile(Doc, xmlOrigen) y WriteXMLFile(Doc, xmlDestino) no jalan en Delphi ¿De qué librería se obtienen?

Yo intenté con Nodo := Doc.DocumentElement.ChildNodes[1], pero no funciona con IDOMNode... De cualquier forma esto se puede resolver escribiendo directo en el XML con XMLDocument.

Y por último, si pudieras ayudarme, te lo agradecería tremendamente: en la función que mandaste para codificar de bin a base64, le debes poner un parámetro PByte, pero GetSello entrega ya sea un array de char o, en tu caso (sea como sea que lo hayas logrado hacer jalar), un arreglo de bytes... De cualquier forma sigo trabajando en esto...

Te agradezco mucho toda la ayuda que haz subido, ya que poca gente publicaría un trabajo así.

Saludos ;)


Lo que pasa es que esta hecho para lazarus por eso a mi si me funciona. Si lo quieres para delphi checa este otro ejemplo de aquí de ahí copie el código de la función bin a base64.


Saludos
  • 0

#18 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.448 mensajes
  • LocationMéxico

Escrito 06 abril 2010 - 12:34

Yo aún tengo algunas dudas sobre los fundamentos legales para emitir facturas digitales, sería bueno analizar bien esa parte para evitar sorpresitas :)

Salud OS
  • 0

#19 axesys

axesys

    Advanced Member

  • Moderadores
  • PipPipPip
  • 640 mensajes
  • LocationLos Mochis

Escrito 06 abril 2010 - 02:40

Aquí esta toda la información

  1. Entramos a http://www.sat.gob.mx/
  2. Clic en “Comprobantes Fiscales”
  3. Clic en “Comprobantes Fiscales Digitales”
  4. Clic en “Información para contribuyentes que deseen emitir CFD por sus propios medios”
  5. Clic en “Orientación y Aclaraciones”
  6. Clic en “Lo más consultado”
  7. Clic en “Nueva versión del Anexo 20”



Saludos
  • 0

#20 axesys

axesys

    Advanced Member

  • Moderadores
  • PipPipPip
  • 640 mensajes
  • LocationLos Mochis

Escrito 06 abril 2010 - 10:36

Encontre un libro interesante Factura Electronica Guia Practica de Implementacion

Y unos blogs con experiencias de quienes ya usan esto
http://technosat.wordpress.com/
http://blog.tufactura.me/
http://www.kauli.info/


Saludos
  • 0




IP.Board spam blocked by CleanTalk.