Top Banner
Facturación Digital Comprobante Fiscal Digital por Internet Descripción del proceso paso a paso para poder generar tus propios Comprobantes Fiscales (CFDI), con ejemplos explicados y comentados usando JAVA 2010 Departamento de Informacion y de Sistemas Universidad de Montemorelos 19/10/2010
27

46935137 Facturacion Digital

Oct 25, 2014

Download

Documents

juanm611
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: 46935137 Facturacion Digital

Facturación Digital Comprobante Fiscal Digital por Internet Descripción del proceso paso a paso para poder generar tus propios Comprobantes Fiscales (CFDI), con ejemplos explicados y comentados usando JAVA

2010

Departamento de Informacion y de Sistemas Universidad de Montemorelos

19/10/2010

Page 2: 46935137 Facturacion Digital

Contenido FACTURACION DIGITAL .................................................................................................................. 2

Introduccion .................................................................................................................................. 2

Algunas definiciones ...................................................................................................................... 2

Contenido del Anexo 20 Anexo 20 de la Primera Resolución de Modificaciones a la Resolución

Miscelánea Fiscal para 2010, publicada el 14 de septiembre de 2010. ........................................ 3

Pasos para la creación de un CFDI .................................................................................................. 4

PASO 1: Crear estructura de clases y documentación básica ....................................................... 4

Algunas notas aclaratorias y recomendaciones: ...................................................................... 7

Fuente y sitios recomendados: ............................................................................................... 8

PASO 2: Generar Cadena Original del CFDI SIN TimbreFiscalDigital ............................................. 8

Reglas Generales para la generación de la Cadena Original .................................................... 8

Secuencia de Formación de la Cadena Original ....................................................................... 9

Algunas notas aclaratorias y recomendaciones: .................................................................... 13

Fuente y sitios recomendados: ............................................................................................. 13

PASO 3: Generar Sello Digital ................................................................................................... 13

Procedimiento...................................................................................................................... 14

Algunas notas aclaratorias y recomendaciones: .................................................................... 16

Fuente y sitios recomendados: ............................................................................................. 16

PASO 4: Generar y validar XML del Comprobante ..................................................................... 17

Algunas notas aclaratorias y recomendaciones: ..................................................................... 23

Fuente y sitios recomendados: ............................................................................................. 24

PASO 5: Generar Cadena Original del Timbre Fiscal Digital ....................................................... 24

Ejemplo de cadena original de un timbre: ............................................................................ 24

Fuente y sitios recomendados: ............................................................................................. 25

PASO 6: Generar y validar XML del Timbre Fiscal Digital .......................................................... 25

Fuente y sitios recomendados: ............................................................................................. 25

PASO 7: Juntar (concatenar) el XML obtenido del Comprobante + XML del TimbreFiscalDigital 25

Fuente y sitios recomendados: ............................................................................................. 26

OTROS ..................................................................................................................................... 26

Page 3: 46935137 Facturacion Digital

FACTURACION DIGITAL

Introduccion Después de mucho leer, investigar en foros, entender el Anexo 20 del SAT y demás, esto es

lo que hemos logrado entender y que nos queda claro.

Aclaro que todo lo que se muestre a continuación está basado en la versión 3 de los

Comprobantes Digitales, que entrara en vigor a partir del 1/Enero/2011 y construido sobre

el lenguaje de programación JAVA.

Algunas definiciones CFDI: Comprobante Fiscal Digital por Internet

Anexo 20: Tu Biblia para la Facturacion Digital. Es un pdf hecho por el SAT donde esta

detallado y especificado los estándares y formatos que deben cumplir los CFD o CFDI

Cadena Original: El elemento a sellar. secuencia de datos formada con la información

contenida dentro del comprobante fiscal digital por internet, establecida en el Rubro II.A

“Estándar de comprobante fiscal digital por internet” de este anexo (Anexo 20).

Sello Digital: Resultado de la secuencia de algoritmos aplicados a la Cadena Original para

hacer que el Comprobante Fiscal tenga las características de: Infalsificable y Único.

XSD: Es un lenguaje de esquema utilizado para describir la estructura y las restricciones de

los contenidos de los documentos XML de una forma muy precisa, más allá de las normas

sintácticas impuestas por el propio lenguaje XML. En palabras que nosotros hemos

entendido, el XSD no es básicamente una plantilla donde se especifica la estructura, tipos

de datos y requisitos que debe cumplir un documento XML. Y se usa precisamente para

verificar si un documento XML cumple o no con los elementos de la plantilla.

Page 4: 46935137 Facturacion Digital

Contenido del Anexo 20 Anexo 20 de la Primera Resolución de

Modificaciones a la Resolución Miscelánea Fiscal para 2010, publicada el

14 de septiembre de 2010. Cuyo contenido trata de los Medios electrónicos

I. Del Comprobante Fiscal Digital:

A. Características técnicas del archivo que contenga el informe mensual de comprobantes

fiscales digitales emitidos

B. Estándar de comprobante fiscal digital

C. Generación de sellos digitales para comprobantes fiscales digitales

II. Del Comprobante Fiscal Digital por Internet:

A. Estándar de comprobante fiscal digital por internet

B. Generación de sellos digitales para comprobantes fiscales digitales por internet

C. Estándar y uso del complemento obligatorio: Timbre Fiscal Digital del SAT

D. Estándar del servicio de cancelación

E. Especificación técnica del código de barras bidimensional

III. De los distintos medios de comprobación digital:

A. Estándares y especificaciones técnicas que deberán cumplir las aplicaciones

informáticas para la generación de claves de criptografía asimétrica a utilizar para Firma

Electrónica Avanzada

B. Uso de la facilidad de nodos opcionales y

C. Uso de la facilidad de ensobretado

Page 5: 46935137 Facturacion Digital

Pasos para la creación de un CFDI

PASO 1: Crear estructura de clases y documentación básica

Estas son las clases que deben crearse con sus atributos y tipo. Se muestran en orden

jerárquico. Fueron extraidas directamente del Anexo 20. Solo se detallan algunos atributos

que se consideran son un poco complicado de entender o que se prestan a confusión; mas

características deberán consultarse directamente en el Anexo 20 del SAT.

TIPOS SIMPLES

Comprobante

String versión //3.0

String serie //Serie para control interno del Contribuyente (1-25 caracteres)

String folio //Folio para control interno del Contribuyente

Date fecha

String sello //Sello Digital del Comprobante (en Base 64)

String formaDePago

String noCertificado //Número de serie del certificado de sello digital (lo

otorga el SAT)

String certificado //Certificado del sello digital (en Base 64)

String condicionesDePago

T_Importe subtotal //Suma de los importes de los Conceptos antes de

descuentos e impuestos

T_Importe descuento

String motivoDescuento

String tipoCambio //Tipo de Cambio según la moneda usada

String moneda //Moneda utilizada para expresar los montos

T_Importe total //Suma del total – descuentos aplicables + descuentos

trasladados – impuestos retenidos

String metodoDePago

String tipoDeComprobante

Emisor emisor

Receptor receptor

Conceptos

Impuestos

Complemento //Nodo opcional donde se incluirá el complemento Timbre

Fiscal Digital de manera obligatoria y los nodos complementarios

determinados por el SAT, de acuerdo a las disposiciones particulares a un

sector o actividad específica.

Addenda // Nodo opcional para recibir las extensiones al presente formato

que sean de utilidad al contribuyente. Para las reglas de uso del mismo,

referirse al formato de origen

Page 6: 46935137 Facturacion Digital

Emisor

T_Rfc rfc

String nombre

DomicilioFiscal domicilioFiscal

ExpedidoEn expedidoEn

DomicilioFiscal

UbicacionFiscal ubicacionFiscal

ExpedidoEn

Ubicación

Receptor

T_Rfc rfc

String nombre

Domicilio domicilio

Domicilio

Ubicación

Conceptos

List<Concepto> conceptos

BigInteger sumaImportesConceptos //Atributo agregado por nosotros para guardar

la suma total de los importes de los conceptos agregados

Concepto

Double cantidad

String unidad

String noIdentificacion

String descripción

T_Importe valorUnitario

T_Importe importe //cantidad * valorUnitario

InformacionAduanera informacionAduanera

CuentaPredial cuentaPredial

ComplementoConcepto complementoConcepto

Parte

InformacionAduanera

T_InformacionAduanera

CuentaPredial

Numero

ComplementoConcepto

Page 7: 46935137 Facturacion Digital

// Nodo opcional donde se incluirán los nodos complementarios de extensión al

concepto, definidos por el SAT, de acuerdo a disposiciones particulares a un sector

o actividad específica.

Parte

Double cantidad

String unidad

String noIdentificacion

String descripcion

T_Importe valorUnitario

T_Importe importe //cantidad * valorUnitario

InformacionAduanera informacionAduanera

Impuestos

T_Importe totalImpuestosRetenidos //Total de impuestos retenidos, obtenidos de los

Conceptos

T_Importe totalImpuestosTrasladados //Total de impuestos trasladados, obtenidos

de los Conceptos

Retenciones

Traslados

Retenciones

List<Retencion> retenciones

T_Importe sumaImportesRetenciones // Atributo agregado por nosotros para

guardar la suma total de los importes de las retenciones agregadas

Retencion

String impuesto //ISR, IVA

T_Importe importe

Traslados

List<Traslado> traslados

T_Importe sumaImportesTraslados // Atributo agregado por nosotros para guardar

la suma total de los importes de los traslados agregados

Traslado

String impuesto //IVA, IEPS

T_Importe tasa

T_Importe importe

Complemento

TimbreFiscalDigital timbreFiscalDigital

Addenda

Page 8: 46935137 Facturacion Digital

TIPOS COMPLEJOS

T_Ubicacion

String calle

String noExterior

String noInterior

String colonia

String localidad

String referencia

String municipio

String estado

String país

String coidoPostal

T_UnicacionFiscal

Mismos atributos que T_Ubicacion

T_InformacionAduanera

String numero

Date fecha

String aduana

T_Rfc

String rfc //12 a 13 caracteres

T_Importe

BigDecimal importe //Aquí usamos un BigDecimal, debido a que, por su exactitud,

consideramos que es lo mejor para manejar cantidades de dinero

Algunas notas aclaratorias y recomendaciones:

Recomiendo comentar todas las clases, poniendo a cada una la descripción que se

encuentra en los diagramas del Anexo 20

Usar BigDecimal para las unidades de dinero debido a que, según el API Java, es

totalmente exacto

En las clases de Conceptos, Retenciones y Traslados, agregar los atributos de

sumaImportes* y sobreescribir el método del add de Java para que al momento de

agregar un Concepto/Retencion/Traslado nos guarde la suma de los importe y no

tener que hacer ciclos después que nos quitaran tiempo al generar el Comprobante

Usar herencia para las siguientes clases: Ubicación, UbicacionFiscal, Domicilio,

DomicilioFiscal,ExpedidoEn, tomando como clase padre a Ubicación ya que es la

clase que no tiene ningún nodo requerido, y de ahí extender los demas

Page 9: 46935137 Facturacion Digital

Fuente y sitios recomendados:

Anexo 20 paginas 55-76

http://www.google.com.mx/url?sa=t&source=web&cd=1&ved=0CBQQFjAA&url=

ftp%3A%2F%2Fftp2.sat.gob.mx%2Fasistencia_servicio_ftp%2Fpublicaciones%2F

anteproyectos%2FAnteproyecto_A20_03092010.doc&rct=j&q=anexo%2020%20v

3%20del%20sat&ei=Gz28TI3mG5CCsQPZlZzuDg&usg=AFQjCNGRtPPl8xCqSX

AdiRD5Yo6BzUQS3w&sig2=k8508zZvokRiBatwzWv-qg&cad=rja –

Anteproyecto del Anexo 20 V3

ftp://ftp2.sat.gob.mx/asistencia_servicio_ftp/publicaciones/legislacion10/a20rmf_23

092010.doc - Anexo 20 de la Primera Resolución de Modificaciones a la

Resolución Miscelánea Fiscal para 2010, publicada el 14 de septiembre de 2010.

Publicado en el DOF del 23 de septiembre de 2010

http://code.google.com/p/cx-faktura/ - Codigo java para generar un CFD versión2

http://www.facturae.es/ES-

ES/DESCARGAS/DESCARGASDESARROLLO/Paginas/APIJava2.aspx - API

JAVA para la generación de CFDs en España

http://www.nic.cl/anuncios/2003-08-07.html - API JAVA para la generación de

CFDs en Chile

PASO 2: Generar Cadena Original del CFDI SIN TimbreFiscalDigital En este punto existen 2 opciones:

1.- Generar el xml del Comprobante de acuerdo al formato del Anexo 20 y a partir del xml

generar la Cadena Original

2.- Generar “a mano” la Cadena Original y posteriormente el xml del Comprobante.

Nosotros elegimos por razones de tiempo, generar “a mano” la cadena original. Esto lo

logramos de la siguiente manera: Cada clase u objeto se encarga de generar su propia

cadena original de acuerdo al estándar publicado por el SAT, de tal manera que la clase

Comprobante, solo tiene que concatenar al generar su propia cadena Original, todas las

“cadenas originales” de los elementos que requiere.

Estos son los requisitos que deben cumplir la generación de la Cadena Original:

Reglas Generales para la generación de la Cadena Original: 1. Ninguno de los atributos que conforman al comprobante fiscal digital deberá

contener el carácter | (“pipe”) debido a que este será utilizado como carácter de

control en la formación de la cadena original.

2. El inicio de la cadena original se encuentra marcado mediante una secuencia de

caracteres || (doble “pipe”).

Page 10: 46935137 Facturacion Digital

3. Se expresará únicamente la información del dato sin expresar el atributo al que hace

referencia. Esto es, si la serie del comprobante es la “A” solo se expresará |A| y

nunca |Serie A|.

4. Cada dato individual se encontrará separado de su dato subsiguiente, en caso de

existir, mediante un carácter | (“pipe” sencillo).

5. Los espacios en blanco que se presenten dentro de la cadena original serán tratados

de la siguiente manera:

a. Se deberán remplazar todos los tabuladores, retornos de carro y saltos de

línea por espacios en blanco.

b. Acto seguido se elimina cualquier carácter en blanco al principio y al final

de cada separador | (“pipe” sencillo).

c. Finalmente, toda secuencia de caracteres en blanco intermedias se sustituyen

por un único carácter en blanco.

6. Los datos opcionales no expresados, no aparecerán en la cadena original y no

tendrán delimitador alguno.

7. El final de la cadena original será expresado mediante una cadena de caracteres ||

(doble “pipe”).

8. Toda la cadena de original se expresará en el formato de codificación UTF-8.

9. El nodo o nodos adicionales <ComplementoConcepto> se integrarán a la cadena

original como se indica en la secuencia de formación en su numeral 10, respetando

la secuencia de formación y número de orden del ComplemetoConcepto.

10. El nodo o nodos adicionales <Complemento> se integraran al final de la cadena

original respetando la secuencia de formación para cada complemento y número de

orden del Complemento.

11. El nodo Timbre Fiscal Digital del SAT será integrado posterior a la validación

realizada por un proveedor autorizado por el SAT que forma parte de la

Certificación Digital del SAT. Dicho nodo no se integrará a la formación de la

cadena original del CFDI, las reglas de conformación de la cadena original del nodo

se describen en el rubro II.C del presente anexo.

Y la Secuencia de Formación para la Cadena Original es esta:

Secuencia de Formación de la Cadena Original

1. Información del nodo Comprobante

a. version

b. fecha

c. tipoDeComprobante

d. formaDePago

e. condicionesDePago

f. subTotal

g. descuento

h. TipoCambio

i. Moneda

j. total

2. Información del nodo Emisor

a. rfc

b. nombre

Page 11: 46935137 Facturacion Digital

3. Información del nodo DomicilioFiscal

a. calle

b. noExterior

c. noInterior

d. colonia

e. localidad

f. referencia

g. municipio

h. estado

i. pais

j. codigoPostal

4. Información del nodo ExpedidoEn

a. calle

b. noExterior

c. noInterior

d. colonia

e. localidad

f. referencia

g. municipio

h. estado

i. pais

j. codigoPostal

5. Información del nodo Receptor

a. rfc

b. nombre

6. Información del nodo Domicilio

a. calle

b. noExterior

c. noInterior

d. colonia

e. localidad

f. referencia

g. municipio

h. estado

i. pais

j. codigoPostal

7. Información de cada nodo Concepto

nota: esta secuencia deberá ser repetida por cada nodo Concepto relacionado

a. cantidad

b. unidad

c. noIdentificacion

d. descripcion

e. valorUnitario

f. importe

g. InformacionAduanera nota: esta secuencia deberá ser repetida por cada nodo

InformacionAduanera de forma indistinta a su grado de dependencia

i. numero

Page 12: 46935137 Facturacion Digital

ii. fecha

iii. aduana

h. Información del nodo CuentaPredial

i. numero

8. Información del nodo ComplementoConcepto de acuerdo con lo expresado en el

Rubro III.B.

9. Información de cada nodo Retencion

nota: esta secuencia a, b, deberá ser repetida por cada nodo Retención relacionado,

el total de impuestos retenidos no se repite.

a. impuesto

b. importe

c. totalImpuestosRetenidos

10. Información de cada nodo Traslado

nota: esta secuencia a, b, deberá ser repetida por cada nodo Traslado relacionado, el

total de impuestos trasladados no se repite.

a. Impuesto

b. tasa

c. importe

d. totalImpuestosTrasladados

11. Información del nodo Complemento de acuerdo con lo expresado en el Rubro III.B.

Ahora, muestro un ejemplo de la manera en que generamos la Cadena Original

public class Comprobante{

private String versión = “3.0”;

.

.

.

private Emisor emisor;

public String getCadenaOriginal(){

String cadena = "||"; //inicio de la cadena original

sdf = new SimpleDateFormat(Constants.DATE_FORMATO_CFDI);

//para formatear la fecha

//Informacion del Nodo Comprobante

cadena += version + "|" + sdf.format(fecha) + "|" +

tipoDeComprobante + "|" + formaDePago + "|" +

(!getCondicionesDePago().equals("") ? condicionesDePago + "|"

: "" ) +

getSubtotal().getImporte().toString() + "|" +

(!getDescuento().getImporte().toString().equals("0.0") ?

getDescuento().getImporte().toString() + "|" : "") +

(!getTipoDeCambio().equals("") ? getTipoDeCambio() + "|" :

"") + (!getMoneda().equals("") ? getMoneda() + "|" : "") +

getTotal().getImporte().toString()+ "|";

//Informacion del Nodo Emisor (Domicilio Fiscal, ExpedidoEn)

cadena += emisor.getCadenaOriginal() + "|";

//Informacion del Nodo Receptor (Domicilio)

Page 13: 46935137 Facturacion Digital

cadena += receptor.getCadenaOriginal() + "|";

//Informacion del Nodo Conceptos

cadena += conceptos.getCadenaOriginal() + "|";

//Informacion del Nodo Impuestos

//Informacion del Nodo Retenciones

cadena += impuestos.getRetenciones().getCadenaOriginal() +

"|";

//Informacion del Nodo Traslados

cadena += impuestos.getCadenaOriginalTraslados();

//Informacion del Nodo Complemento

cadena += "||";

try{

cadena = new String(cadena.getBytes("UTF-8"));

//Codificacion de la Cadena a UTF-8

}

catch(UnsupportedEncodingException uee){

System.out.println("Error al codificar la cadena a UTF-

8");

}

return cadena;

}

}

public class Emisor {

private T_Rfc rfc;

private String nombre;

private DomicilioFiscal domicilioFiscal;

private ExpedidoEn expedidoEn;

public String getCadenaOriginal() {

String cadena = "";

//Informacion del Nodo Emisor

cadena += this.rfc.getCadenaOriginal() + "|" + nombre;

//Informacion del Nodo Domicilio Fiscal

if(domicilioFiscal != null &&

!domicilioFiscal.getCadenaOriginal().equals("")){

cadena += "|" + domicilioFiscal.getCadenaOriginal();

}

//Informacion del Nodo ExpedidoEn

if(expedidoEn != null &&

!expedidoEn.getCadenaOriginal().equals("")){

cadena += "|" + expedidoEn.getCadenaOriginal();

}

return cadena;

}

Page 14: 46935137 Facturacion Digital

}

public class T_Rfc {

private String rfc; public String getCadenaOriginal(){ //Regresa la Cadena Original del

rfc

return this.rfc;

}

}

Algunas notas aclaratorias y recomendaciones:

Los elementos que son REQUERIDOS el Comprobante no necesariamente son

requeridos por la Cadena Original.

Los elementos REQUERIDOS por la Cadena Original algunos son OPCIONALES

en el Comprobante.

Por lo tanto, los elementos OPCIONALES que no se encuentren el Comprobante,

NO APARECERAN en la Cadena Original.

Notese en el ejemplo anterior, en el elemento Comprobante, que la Cadena Original

se regresa ya codificada en el formato UTF-8, el cual es el estándar establecido por

el Anexo 20

Fuente y sitios recomendados:

Anexo 20 paginas 95-97

http://code.google.com/p/cx-faktura/ - Codigo java para generar un CFD versión2.

PASO 3: Generar Sello Digital

A continuación se describe el procedimiento para la generación del Sello Digital tal y como

lo describe el Anexo 20 del SAT. Hay que recordar que la generación del “sello digital” no

es más que aplicar una serie de algoritmos a la Cadena Original, que convertirán a esta en

una cadena encriptada y es este resultado, lo que conocemos como “sello digital”, al igual

que un Comprobante “sellado”, es un Comprobante que contiene un cadena original que ya

ha sido procesada con los algoritmos necesarios y convertida en el atributo “sello” del

Comprobante.

Page 15: 46935137 Facturacion Digital

Procedimiento

En pasos sencillos, el procedimiento es este:

I. Obtener la Cadena Original

II. Aplicar el método de digestión SHA-1 a la Cadena Original (por ahora no hay

nodos Complementarios asi que no nos causaran problemas ya que no se toman en

cuenta)

III. Encriptar el resultado obtenido en el paso anterior usando el algoritmo de

encriptación RSA, usando para ello la Clave Privada correspondiente al Certificado

Digital del Emisor del Mensaje y Sello Digital (certificado y llave del certificado)

IV. El resultado obtenido en el paso anterior, codificarlo a Base 64 (consiste en la

asociación de cada 6 bits de la secuencia a un elemento de un "alfabeto" que consta

de 64 caracteres imprimibles)

Aquí un ejemplo de Sello Digital:

GqDiRrea6+E2wQhqOCVzwME4866yVEME/8PD1S1g6AV48D8VrLhKUDq0Sjqnp9Iwf

MAbX0ggwUCLRKa+Hg5q8aYhya63If2HVqH1sA08poer080P1J6Z+BwTrQkhcb5Jw8jE

NXoErkFE8qdOcIdFFAuZPVT+9mkTb0Xn5Emu5U8=

Tal y como lo describe el SAT, el procedimiento es este:

Para toda cadena original a ser sellada digitalmente, la secuencia de algoritmos a aplicar es

la siguiente:

I. Aplicar el método de digestión SHA-1 a la cadena original a sellar incluyendo los

nodos Complementarios. Este procedimiento genera una salida de 160 bits (20

bytes) para todo mensaje. La posibilidad de encontrar dos mensajes distintos que

produzcan una misma salida es de 1 en 2160, y por lo tanto en esta posibilidad se

basa la inalterabilidad del sello, así como su no reutilización. Es de hecho una

medida de la integridad del mensaje sellado, pues toda alteración del mismo

provocará una digestión totalmente diferente, por lo que no se podrá autentificar el

mensaje. SHA-1 no requiere semilla alguna. El algoritmo cambia su estado de

bloque en bloque de acuerdo a la entrada previa.

II. Con la clave privada correspondiente al certificado digital del emisor del mensaje y

del sello digital, encriptar la digestión del mensaje obtenida en el paso I utilizando

para ello el algoritmo de encripción RSA. Nota: La mayor parte del software

comercial podría generar los pasos I y II invocando una sola función y

especificando una constante simbólica. En el SAT este procedimiento se hace en

pasos separados, lo cual es totalmente equivalente. Es importante resaltar que

prácticamente todo el software criptográfico comercial incluye APIs o expone

métodos en sus productos que permiten implementar la secuencia de algoritmos

aquí descrita. La clave privada solo debe mantenerse en memoria durante la llamada

a la función de encripción; inmediatamente después de su uso debe ser eliminada de

Page 16: 46935137 Facturacion Digital

su registro de memoria mediante la sobre escritura de secuencias binarias alternadas

de "unos" y "ceros".

III. El resultado será una cadena binaria que no necesariamente consta de caracteres

imprimibles, por lo que deberá traducirse a una cadena que sí conste solamente de

tales caracteres. Para ello se utilizará el modo de expresión de secuencias de bytes

denominado "Base 64", que consiste en la asociación de cada 6 bits de la secuencia

a un elemento de un "alfabeto" que consta de 64 caracteres imprimibles. Puesto que

con 6 bits se pueden expresar los números del 0 al 63, si a cada uno de estos valores

se le asocia un elemento del alfabeto se garantiza que todo byte de la secuencia

original puede ser mapeado a un elemento del alfabeto Base 64, y los dos bits

restantes formarán parte del siguiente elemento a mapear. Este mecanismo de

expresión de cadenas binarias produce un incremento de 25% en el tamaño de las

cadenas imprimibles respecto de la original. La codificación en base 64, así como su

decodificación, se hará tomando los bloques a procesar en el sentido de su lectura,

es decir, de izquierda a derecha. El alfabeto a utilizar se expresa en el siguiente

catálogo

A continuación la manera en la que generamos el Sello Digital

public class GeneradorSelloDigital {

public String getSelloDigital(String cadenaOriginal) throws

GeneralSecurityException{

Security.addProvider(new BouncyCastleProvider()); //Esta es la

manera en la que se añade el Wrapper de BouncyCastle para hacer la

encriptacion. Lo que hace esta línea es que se usen las clases del

paquete Security de BouncyCastle en lugar de las de Java originales

System.out.println("Cadena Original "+cadenaOriginal);

FileInputStream archivoClavePrivada=null;

try{

archivoClavePrivada=new

FileInputStream("Path_del_archivo_emisor.key");

}catch(FileNotFoundException fnfe){

fnfe.printStackTrace();

}

String password="claveDelArchivo";

byte[] clavePrivada = getBytes(archivoClavePrivada);

PKCS8Key pkcs8 = new PKCS8Key(clavePrivada,

password.toCharArray());

PrivateKey pk = pkcs8.getPrivateKey();

Signature firma = Signature.getInstance("SHA1withRSA");

//Aplicacion de la Digestion con SHA-1 y encriptado a con RSA en un solo

paso

firma.initSign(pk);

String selloDigital = null;

try {

firma.update(cadenaOriginal.getBytes("UTF-8"));

//Codificacion del resultado a UTF-8

BASE64Encoder b64 = new BASE64Encoder();

selloDigital = b64.encode(firma.sign()); //Conversion del

resultado anterior a Base64

Page 17: 46935137 Facturacion Digital

} catch (UnsupportedEncodingException e) {

e.printStackTrace();

}

System.out.println("Sello Digital "+selloDigital);

return selloDigital;

}

/**

* Metodo que convierte un input stream con la llave privada a un

array de bytes

* @param is InputSteam con la clave privada

* @return Arreglo de bytes con la clave privada

*/

private byte[] getBytes(InputStream is) {

int totalBytes = 714;

byte[] buffer = null;

try {

buffer = new byte[totalBytes];

is.read(buffer, 0, totalBytes);

is.close();

} catch (IOException e) {

e.printStackTrace();

}

return buffer;

}

}

Algunas notas aclaratorias y recomendaciones:

Al parecer, las únicas librerías aceptadas por el SAT para la generación de la firma

digital son: Open SSL y BouncyCastle, el cual cuenta con un Wrapper para Java,

que es lo que nosotros usamos

Una vez generado el Sello Digital, deberemos asignarlo en los siguientes lugares:

I. En el Comprobante, en el atributo “sello”

II. En el Nodo de Complemento Timbre Fiscal, en el atributo “selloCFD”

Fuente y sitios recomendados:

Anexo 20 paginas 97-98

NOTA: Todos los links ftp del SAT deben abrirse con Internet Explorer

ftp://ftp2.sat.gob.mx/asistencia_servicio_ftp/publicaciones/solcedi/Certif_PACyEmi

sor.zip - Certificado PAC y Emisor

http://www.javamexico.org/blogs/nopalin/facturacion_electronica - Encriptación y

codificación a Base 64, pero usando MD5 (usado en los CFD v2)

http://uetiko-developer.blogspot.com/2010/02/como-obtener-el-sello-digital-con-

java.html -Obtención del Sello Digital en una sola Clase totalmente comentada,

pero usando MD5

http://es.debugmodeon.com/articulo/generar-hash-sha-1-de-una-cadena-en-java -

Generación del Hash SHA-1 con Java

Page 18: 46935137 Facturacion Digital

http://renetrejo.blogspot.com/2007/11/facturacin-electrnica.html - Generacion Sello

Digital usando MD5 con Java

http://www.sat.gob.mx/sitio_internet/e_sat/comprobantes_fiscales/15_6522.html -

OpenSSL y BouncyCastle, son las unicas opciones que muestra el SAT para generar

el Sello

http://www.validacfd.com/phpbb3/viewtopic.php?f=5&t=34 OpenSSL y Java no

firman igual

http://www.bouncycastle.org Sitio oficial Bouncy Castle

http://www.openssl.org Sitio Oficial Open SSL

PASO 4: Generar y validar XML del Comprobante

En este paso, nosotros hicimos uso JDOM, que es una biblioteca de código abierto para

manipulaciones de datos XML optimizados para Java.

Esta es la manera en la que logramos generar el XML:

public class CrearXML {

protected Locale local = new java.util.Locale

(Constants.LOCALE_LANGUAGE, Constants.LOCALE_COUNTRY,

Constants.LOCALE_VARIANT);

private SimpleDateFormat sdf = new SimpleDateFormat

(Constants.DATE_FORMATO_CFDI, local);

private Document xml=new Document();

private Element root;

/**

* Este metodo genera el Elemento Comprobante del XML

* @param comprobante

*/

public void generaRaiz(Comprobante comprobante) {

//crea un elemento raiz y le asigna los namespaces y los xsd

root = new

Element(Constants.COMPROBANTE_COMPROBANTE,Constants.COMPROBANTE_PREFIX_NA

MESPACE,Constants.COMPROBANTE_NAMESPACE_URI);

//root = new

Element(Constants.COMPROBANTE_COMPROBANTE,Constants.COMPROBANTE_NAMESPACE

_URI);

Namespace

namespace=Namespace.getNamespace(Constants.COMPROBANTE_PREFIX,

Constants.COMPROBANTE_URI_PREFIX);

root.setAttribute(Constants.COMPROBANTE_SCHEMA,Constants.COMPROBANTE_SCHE

MA_XSD,namespace);

root.addNamespaceDeclaration(namespace);

//se empieza a construir el comprobante

root.setAttribute(Constants.COMPROBANTE_VERSION,

Constants.VERSION_COMPROBANTE_TRES);

Page 19: 46935137 Facturacion Digital

if(comprobante.getSerie()!=null&&!comprobante.getSerie().trim().equals(""

)){

root.setAttribute(Constants.COMPROBANTE_SERIE,

comprobante.getSerie());

}

if(comprobante.getFolio()!=null&&!comprobante.getFolio().trim().equals(""

)){

root.setAttribute(Constants.COMPROBANTE_FOLIO,

comprobante.getFolio());

}

root.setAttribute(Constants.COMPROBANTE_FECHA,

sdf.format(comprobante.getFecha()));

root.setAttribute(Constants.COMPROBANTE_SELLO,

comprobante.getSello());

.

.

.

//se generan el Nodo Emisor

generaEmisor(comprobante.getEmisor());

generaReceptor(comprobante.getReceptor());

generaConceptos(comprobante.getConceptos());

generaImpuestos(comprobante.getImpuestos());

getXml().setRootElement(root);

}

public void generaEmisor(Emisor emisor) {

//se le agrega el namespace al emisor

Element emisorElement = new

Element(Constants.COMPROBANTE_EMISOR,Constants.COMPROBANTE_PREFIX_NAMESPA

CE,Constants.COMPROBANTE_NAMESPACE_URI);

emisorElement.setAttribute(Constants.COMPROBANTE_RFC,

emisor.getRfc().getRfc());

emisorElement.setAttribute(Constants.COMPROBANTE_NOMBRE,

emisor.getNombre());

//se crea el nodo domiciliofiscal

Element domicilioFiscal = new

Element(Constants.COMPROBANTE_DOMICILIO_FISCAL,Constants.COMPROBANTE_PREF

IX_NAMESPACE,Constants.COMPROBANTE_NAMESPACE_URI);

domicilioFiscal.setAttribute(Constants.COMPROBANTE_DOMICILIO_GENERICO_CAL

LE, emisor.getDomicilioFiscal().getCalle());

if(emisor.getDomicilioFiscal().getNoExterior()!=null&&!emisor.getDomicili

oFiscal().getNoExterior().trim().equals("")){

domicilioFiscal.setAttribute(Constants.COMPROBANTE_DOMICILIO_GENERICO_NO_

EXTERIOR, emisor.getDomicilioFiscal().getNoExterior());

}

if(emisor.getDomicilioFiscal().getNoInterior()!=null&&!emisor.getDomicili

oFiscal().getNoInterior().trim().equals("")){

domicilioFiscal.setAttribute(Constants.COMPROBANTE_DOMICILIO_GENERICO_NO_

INTERIOR, emisor.getDomicilioFiscal().getNoInterior());

Page 20: 46935137 Facturacion Digital

}

.

.

.

domicilioFiscal.setAttribute(Constants.COMPROBANTE_DOMICILIO_GENERICO_MUN

ICIPIO, emisor.getDomicilioFiscal().getMunicipio());

domicilioFiscal.setAttribute(Constants.COMPROBANTE_DOMICILIO_GENERICO_EST

ADO, emisor.getDomicilioFiscal().getEstado());

.

.

.

//se agrega el domicilio fiscal al nodo emisor

emisorElement.addContent(domicilioFiscal);

//se agrega el nodo emisor al elemento comprobante

root.addContent(emisorElement);

}

public void generaReceptor(Receptor receptor) {

//se crea el nodo receptor

Element rec = new

Element(Constants.COMPROBANTE_RECEPTOR,Constants.COMPROBANTE_PREFIX_NAMES

PACE,Constants.COMPROBANTE_NAMESPACE_URI);

rec.setAttribute(Constants.COMPROBANTE_RFC,

receptor.getRfc().getRfc());

if(receptor.getNombre()!=null&&!receptor.getNombre().trim().equals("")){

rec.setAttribute(Constants.COMPROBANTE_NOMBRE,

receptor.getNombre());

}

//se crea el nodo domicilio

Element domicilio = new

Element(Constants.COMPROBANTE_DOMICILIO,Constants.COMPROBANTE_PREFIX_NAME

SPACE,Constants.COMPROBANTE_NAMESPACE_URI);

if(receptor.getDomicilio().getCalle()!=null&&!receptor.getDomicilio().get

Calle().trim().equals("")){

domicilio.setAttribute(Constants.COMPROBANTE_DOMICILIO_GENERICO_CALLE,

receptor.getDomicilio().getCalle());

}

if(receptor.getDomicilio().getNoExterior()!=null&&!receptor.getDomicilio(

).getNoExterior().trim().equals("")){

domicilio.setAttribute(Constants.COMPROBANTE_DOMICILIO_GENERICO_NO_EXTERI

OR, receptor.getDomicilio().getNoExterior());

}

.

.

.

//se agrega el domicilio al receptor

rec.addContent(domicilio);

//se agrega el nodo receptor al comprobante

root.addContent(rec);

Page 21: 46935137 Facturacion Digital

}

public void generaConceptos(Conceptos concp) {

Element conceptos = new

Element(Constants.COMPROBANTE_CONCEPTOS,Constants.COMPROBANTE_PREFIX_NAME

SPACE,Constants.COMPROBANTE_NAMESPACE_URI);

for (Concepto con : concp) {

Element concepto = new

Element(Constants.COMPROBANTE_CONCEPTO,Constants.COMPROBANTE_PREFIX_NAMES

PACE,Constants.COMPROBANTE_NAMESPACE_URI);

concepto.setAttribute(Constants.COMPROBANTE_CONCEPTO_CANTIDAD,

con.getCantidad().toString());

if(con.getUnidad()!=null&&!con.getUnidad().trim().equals("")){

concepto.setAttribute(Constants.COMPROBANTE_CONCEPTO_UNIDAD,

con.getUnidad());

}

if(con.getNoIdentificacion()!=null&&!con.getNoIdentificacion().trim().equ

als("")){

concepto.setAttribute(Constants.COMPROBANTE_CONCEPTO_NO_IDENTIFICACION,

con.getNoIdentificacion());

}

concepto.setAttribute(Constants.COMPROBANTE_CONCEPTO_DESCRIPCION,

con.getDescripcion());

concepto.setAttribute(Constants.COMPROBANTE_CONCEPTO_VALOR_UNITARIO,

con.getValorUnitario().getImporte().toString());

concepto.setAttribute(Constants.COMPROBANTE_CONCEPTO_IMPORTE,

con.getImporte().getImporte().toString());

//checar los nodos opcionales de conceptos

InformacionAduanera,CuentaPredial,ComplementoConcepto,Parte

conceptos.addContent(concepto);

}

root.addContent(conceptos);

}

public void generaImpuestos(Impuestos imp){

//checar los elementos de impuestos

Element impuestos=new Element(Constants.COMPROBANTE_IMPUESTOS,

Constants.COMPROBANTE_PREFIX_NAMESPACE,Constants.COMPROBANTE_NAMESPACE_UR

I);

root.addContent(impuestos);

}

public boolean creaAndValidaXML(Comprobante comprobante){

boolean response=false;

generaRaiz(comprobante);

//Instancia La clase que da la salida XML al archivo

XMLOutputter outputter = new XMLOutputter();

//Formato XML Arreglado Con Identacion

Format formato = Format.getPrettyFormat();

outputter.setFormat(formato);

//Crea el archivo aunque no de manera logica

Page 22: 46935137 Facturacion Digital

File archivoXml = new File("/home/eder/comprobante.xml");

try {

//se instancia la clase que va a escrbir el archivo en disco

Writer write = new FileWriter(archivoXml);

//se escribe el archivo en disco

outputter.output(getXml(),write);

} catch (IOException e) {

System.err.println(e);

}

//se instancia la clase que validara el XSD

SAXBuilder builder = new

SAXBuilder("org.apache.xerces.parsers.SAXParser", true);

builder.setFeature("http://apache.org/xml/features/validation/schema",

true);

builder.setFeature("http://apache.org/xml/features/validation/schema-

full-checking", true);

builder.setProperty("http://apache.org/xml/properties/schema/external-

schemaLocation", Constants.COMPROBANTE_SCHEMA_XSD);

builder.setValidation(true);

//se imprime el documento si se logro cumplir con el XSD

try {

Document document = builder.build(archivoXml);

outputter.output(document, System.out);

response=true;

} catch (JDOMException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

return response;

}

/**

* @return the xml

*/

public Document getXml() {

return xml;

}

}

A continuación muestro las Constantes con sus valores que usamos

//Comprobante Fiscal Digital-START

public static final String COMPROBANTE_COMPROBANTE = "Comprobante";

public static final String COMPROBANTE_VERSION = "version";

public static final String COMPROBANTE_NUM_VERSION = "3.0";

public static final String COMPROBANTE_FOLIO = "folio";

public static final String COMPROBANTE_SERIE = "serie";

public static final String COMPROBANTE_FECHA = "fecha";

public static final String COMPROBANTE_SELLO = "sello";

public static final String COMPROBANTE_NO_CERTIFICADO =

"noCertificado";

public static final String COMPROBANTE_CERTIFICADO = "certificado";

Page 23: 46935137 Facturacion Digital

public static final String COMPROBANTE_CONDICIONES_PAGO =

"condicionesDePago";

public static final String COMPROBANTE_SUBTOTAL = "subTotal";

public static final String COMPROBANTE_DESCUENTO = "descuento";

public static final String COMPROBANTE_MOTIVO_DESCUENTO =

"motivoDescuento";

public static final String COMPROBANTE_TIPO_CAMBIO = "TipoCambio";

public static final String COMPROBANTE_MONEDA = "Moneda";

public static final String COMPROBANTE_TOTAL = "total";

public static final String COMPROBANTE_NO_APROBACION =

"noAprobacion";

public static final String COMPROBANTE_ANO_APROBACION =

"anoAprobacion";

public static final String COMPROBANTE_FORMA_PAGO = "formaDePago";

public static final String COMPROBANTE_METODO_DE_PAGO =

"metodoDePago";

public static final String COMPROBANTE_TIPO_COMPROBANTE =

"tipoDeComprobante";

public static final Integer NUMERO_DECIMALES_IMPORTE = 6;

public static final String VERSION_COMPROBANTE_TRES = "3.0";

public static final String COMPROBANTE_RFC = "rfc";

public static final String COMPROBANTE_NOMBRE = "nombre";

//Emisor

public static final String COMPROBANTE_EMISOR = "Emisor";

//Receptor

public static final String COMPROBANTE_RECEPTOR = "Receptor";

//Domicilios

public static final String COMPROBANTE_DOMICILIO_FISCAL =

"DomicilioFiscal";

public static final String COMPROBANTE_DOMICILIO = "Domicilio";

//DomicilioGenerico

public static final String COMPROBANTE_DOMICILIO_GENERICO_CALLE =

"calle";

public static final String COMPROBANTE_DOMICILIO_GENERICO_NO_EXTERIOR

= "noExterior";

public static final String COMPROBANTE_DOMICILIO_GENERICO_NO_INTERIOR

= "noInterior";

public static final String COMPROBANTE_DOMICILIO_GENERICO_COLONIA =

"colonia";

public static final String COMPROBANTE_DOMICILIO_GENERICO_PAIS =

"pais";

public static final String

COMPROBANTE_DOMICILIO_GENERICO_CODIGO_POSTAL = "codigoPostal";

public static final String COMPROBANTE_DOMICILIO_GENERICO_ESTADO =

"estado";

public static final String COMPROBANTE_DOMICILIO_GENERICO_REFERENCIA

= "referencia";

public static final String COMPROBANTE_DOMICILIO_GENERICO_LOCALIDAD =

"localidad";

public static final String COMPROBANTE_DOMICILIO_GENERICO_MUNICIPIO =

"municipio";

//DomicilioGenerico

//Conceptos

Page 24: 46935137 Facturacion Digital

public static final String COMPROBANTE_CONCEPTOS = "Conceptos";

public static final String COMPROBANTE_CONCEPTO = "Concepto";

public static final String COMPROBANTE_CONCEPTO_CANTIDAD =

"cantidad";

public static final String COMPROBANTE_CONCEPTO_UNIDAD = "unidad";

public static final String COMPROBANTE_CONCEPTO_NO_IDENTIFICACION =

"noIdentificacion";

public static final String COMPROBANTE_CONCEPTO_DESCRIPCION =

"descripcion";

public static final String COMPROBANTE_CONCEPTO_VALOR_UNITARIO =

"valorUnitario";

public static final String COMPROBANTE_CONCEPTO_IMPORTE = "importe";

public static final String COMPROBANTE_NAMESPACE_URI =

"http://www.sat.gob.mx/cfd/3";

//Impuestos

public static final String COMPROBANTE_IMPUESTOS = "Impuestos";

public static final String COMPROBANTE_IMPUESTOS_TOTAL_IMPUESTOS =

"totalImpuestosTrasladados";

//NameSpaces

public static final String COMPROBANTE_PREFIX = "xsi";

public static final String COMPROBANTE_PREFIX_NAMESPACE = "cfdi";

public static final String COMPROBANTE_URI_PREFIX =

"http://www.w3.org/2001/XMLSchema-instance";

public static final String COMPROBANTE_SCHEMA = "schemaLocation";

public static final String COMPROBANTE_SCHEMA_XSD =

"http://www.sat.gob.mx/cfd/3

http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv3.xsd";

//TimbreFiscal-START http://www.sat.gob.mx/cfd/3

public static final String COMPROBANTE_TIMBRE_FISCAL =

"TimbreFiscalDigital";

public static final String VERSION_TIMBRE_FISCAL = "2.0";

public static final String COMPROBANTE_TIMBRE_FISCAL_UUID = "UUID";

public static final String COMPROBANTE_TIMBRE_FISCAL_FECHA_TIMBRADO =

"FechaTimbrado";

public static final String COMPROBANTE_TIMBRE_FISCAL_SELLO_CFD =

"selloCFD";

public static final String

COMPROBANTE_TIMBRE_FISCAL_NO_CERTIFICADO_SAT = "noCertificadoSAT";

public static final String COMPROBANTE_TIMBRE_FISCAL_SELLO_SAT =

"selloSAT";

//TimbreFiscal-END

//Encriptacion-START

public static final String ALGORITMO_DIGESTION_AND_CIFRADO =

"SHA1withRSA";

Algunas notas aclaratorias y recomendaciones:

El archivo no esta completo. Se omitieron ciertas partes que se considera son

repetitivas, al igual que explicar línea a línea el código seria muy “pesado”; por eso

mostramos el código usado con sus respectivos comentarios, con la esperanza que

sea entendible para quien lo lea.

Recomendamos el uso de Constantes para los Namespaces y para las demás

constantes.

Page 25: 46935137 Facturacion Digital

Nótese el uso de la clase java SimpleDateFormat, la cual es usada para dar formato

a las fechas, siendo para ello el formato establecido por el SAT: ISO 1801, la cual

queda de esta manera: new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");

Notese el método creaAndValidaXML, que es el método en el cual se genera el

archivo XML y se graba en el disco duro y al mismo tiempo se valida contra el

XSD proveido por el SAT

Nótese todas las validaciones hechas. Si el atributo es requerido se añade por default

a la generación del XML, si no lo es, se valida si esta rellenado ese atributo; si lo

está, se añade al XML y si no, se ignora.

En este paso se ha creado solamente el XML del Comprobante SIN

TimbreFiscalDigital debido a que el SAT provee 2 archivos XSD. Uno para el CFD

(Sin Timbre Fiscal Digital) y otro solo para el Timbre Fiscal Digital.

Fuente y sitios recomendados:

ftp://ftp2.sat.gob.mx/asistencia_servicio_ftp/publicaciones/solcedi/cfdv3.xsd - XSD

para el Comprobante SIN Timbre Fiscal Digital

ftp://ftp2.sat.gob.mx/asistencia_servicio_ftp/publicaciones/solcedi/TimbreFiscalDig

ital.xsd - XSD para el Timbre Fiscal Digital

PASO 5: Generar Cadena Original del Timbre Fiscal Digital

Este es el orden de los elementos que se integraran a la Cadena Original del Timbre Fiscal

Digital, tomado del Anexo 20. Recordar que la cadena debe estar codificada con UTF-8:

“La secuencia de formación será siempre en el orden que se expresa a continuación,

tomando en cuenta las reglas generales expresadas en el párrafo anterior.

a. Atributos del elemento raíz TimbreFiscalDigital

1. version

2. UUID

3. FechaTimbrado

4. selloCFD

5. noCertificadoSAT”

Ejemplo de cadena original de un timbre:

||1.0|ad662d33-6934-459c-a128-bdf0393e0f44|2001-12-

17T09:30:47Z|iYyIk1MtEPzTxY3h57kYJnEXNae9lvLMgAq3jGMePsDtEOF6XLWbrV2

GL/2TX00vP2+YsPN+5UmyRdzMLZGEfESiNQF9fotNbtA487dWnCf5pUu0ikVpgHvpY

7YoA4lB1D/JWc+zntkgW+Ig49WnlKyXi0LOlBOVuxckDb7EAx4=|12345678901234

567890||

Page 26: 46935137 Facturacion Digital

“Nota: El atributo selloCFD será el sello previo del Comprobante Fiscal Digital, el sello del

timbre será guardado dentro del atributo selloSAT. Esta cadena original será sellada

utilizando el algoritmo de digestión SHA-1.”

Ahora, bien, hasta donde hemos logrado comprender, el Timbre Fiscal Digital se añadirá al

Comprobante, como un elemento del elemento Complemento (No ComplementoConcepto).

Los únicos atributos que deberán estar rellenados en el TimbreFiscalDigital son: “versión”,

y “selloCFD”. Los demás elementos serán rellenados por el SAT cuando haga la validación

de nuestro CFDI (se entiende que el CFDI se enviara al SAT por internet).

“El resultado de la validación de un CFDI, asignación de un folio fiscal e incorporación del

sello digital del SAT se entenderá como el Timbrado Fiscal Digital. El folio fiscal digital

será referido como el UUID. Para integrar el complemento TimbreFiscalDigital a un

comprobante fiscal digital por Internet, la estructura resultante deberá integrarse como un

nodo hijo del nodo Comprobante/Complemento/TimbreFiscalDigital. Adicional a su

inclusión, se deberá definir el namespace correspondiente dentro del nodo Comprobante,

así como referenciar la ubicación pública del esquema XSD correspondiente”.

Fuente y sitios recomendados:

Anexo 20 página 103

Anexo 20, pagina 104 – Explicación de los namespaces del Timbre Fiscal Digital

PASO 6: Generar y validar XML del Timbre Fiscal Digital

Una vez que el CFDI ha sido validado por el SAT y EL Timbre Fiscal Digital ha sido

rellenado con los campos de “uuid”, “selloSAT”, “fechaTimbrado” y “noCertificadoSAT”,

toca el momento de generar el XML del Timbre Fiscal Digital, el cual se generara y

validara de la misma forma que el del Comprobante.

Fuente y sitios recomendados:

ftp://ftp2.sat.gob.mx/asistencia_servicio_ftp/publicaciones/solcedi/TimbreFiscalDig

ital.xsd -XSD para el Timbre Fiscal Digital

PASO 7: Juntar (concatenar) el XML obtenido del Comprobante + XML del

TimbreFiscalDigital

Como ultimo paso, se juntara en un solo archivo el XML del Comprobante y el XML del

Timbre Fiscal Digital y se tendrá un solo archivo que es en si nuestra “Factura” o

“Comprobante Fiscal Digital por Internet”.

Page 27: 46935137 Facturacion Digital

Fuente y sitios recomendados:

ftp://ftp2.sat.gob.mx/asistencia_servicio_ftp/publicaciones/solcedi/ejemplo1%20cfd

v3.xml – Ejemplo oficial del SAT de un CFDI

http://www.sat.gob.mx/sitio_internet/asistencia_contribuyente/principiantes/compro

bantes_fiscales/66_19430.html - Utilerías del SAT para los CFDI

OTROS Sobre el Uso de la Addenda:

http://www.sat.gob.mx/sitio_internet/e_sat/comprobantes_fiscales/15_6601.html