Open Carodial opened 11 years ago
Si, hemos visto este problema antes, déjame revisar el código y ver si hay una solución pronto.
Buenas tardes, sobre este tema alguien ya lo pudo solucionar.
Agradecería mucho su ayuda.
El problema es el que la librería de XSD está transformando los dígitos a decimales y al ponerlos en la cadena original los pone como números sin los decimales adicionales y eso impide que valide correctamente.
Alguien ha encontrado solución para esto?
Buenas tardes, me tope con el mismo problema y normalmente retornaba a los usuarios finales que hablaran con sus PACs y volvieran a generar su factura cuando tenian datos como cantidad="02" o importe=".25" o importe="1.200000".
Sin embargo en este momento me vi obligado a dar solución definitiva ya que el SAT para los ex-REPECOs y que ahora pertenecen al Régimen de Incorporación Fiscal obliga a que expidan los CFDI por su portal. Y el propio SAT expide las facturas con los detalles de los ejemplos expuestos, y el que mas me dio problema fue la fecha ya que ellos la expresan asi "2014-05-14T12:25:03Z", con la Z al final, lo cual las librerias de bigdata al usar el Binder para DateTime omite dicha información, por lo cuál resulta en un sello inválido.
La solución que implemente fue:
1- Agregar el método sobrecargado a la clase correspondiente (en mi caso CFDv32.java) verificar y getOriginalBytes, recibiendo un InputStream, creo que el autor de la libreria o alguien mas lo comento en otro post. 2- Los nuevos métodos sobrecargados deberian verse así:
public void verificar(InputStream in) throws Exception{ String certStr = document.getCertificado(); Base64 b64 = new Base64(); byte[] cbs = b64.decode(certStr); X509Certificate cert = KeyLoader .loadX509Certificate(new ByteArrayInputStream(cbs)); String sigStr = document.getSello(); byte[] signature = b64.decode(sigStr); byte[] bytes = getOriginalBytes(in); Signature sig = Signature.getInstance("SHA1withRSA"); sig.initVerify(cert); sig.update(bytes); boolean bool = sig.verify(signature); if (!bool) { throw new Exception("Sello de Emisor inválido");//("Invalid signature"); } }
byte[] getOriginalBytes(InputStream in) throws Exception{ ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { Source source = new StreamSource(in); Source xsl = new StreamSource(getClass().getResourceAsStream(XSLT)); Result out = new StreamResult(baos); TransformerFactory factory = tf; if (factory == null) { factory = TransformerFactory.newInstance(); factory.setURIResolver(new URIResolverImpl()); } Transformer transformer = factory .newTransformer(new StreamSource(getClass().getResourceAsStream(XSLT))); transformer.transform(source, out); } finally { in.close(); }
return baos.toByteArray();
}
Con lo cuál solo basta hacer la invocación necesaria enviando algun FileInputStream p. ej. obviamente teniendo instanciado previamente el objeto CFDv32 correctamente.
No lo aplico al SVN/GitHub ya que yo cuento con una version de la libreria que es desde las primeras versiones y he ido modificando y adecuando a mis necesidades. Espero ayudar a varios con este tema que en realidad llega a ser desesperante.
Excelente apoyo gracias El 26/05/2014 18:04, "poseidon24" notifications@github.com escribió:
Buenas tardes, me tope con el mismo problema y normalmente retornaba a los usuarios finales que hablaran con sus PACs y volvieran a generar su factura cuando tenian datos como cantidad="02" o importe=".25" o importe="1.200000".
Sin embargo en este momento me vi obligado a dar solución definitiva ya que el SAT para los ex-REPECOs y que ahora pertenecen al Régimen de Incorporación Fiscal obliga a que expidan los CFDI por su portal. Y el propio SAT expide las facturas con los detalles de los ejemplos expuestos, y el que mas me dio problema fue la fecha ya que ellos la expresan asi "2014-05-14T12:25:03Z", con la Z al final, lo cual las librerias de bigdata al usar el Binder para DateTime omite dicha información, por lo cuál resulta en un sello inválido.
La solución que implemente fue:
1- Agregar el método sobrecargado a la clase correspondiente (en mi caso CFDv32.java) verificar y getOriginalBytes, recibiendo un InputStream, creo que el autor de la libreria o alguien mas lo comento en otro post. 2- Los nuevos métodos sobrecargados deberian verse así:
public void verificar(InputStream in) throws Exception{ String certStr = document.getCertificado(); Base64 b64 = new Base64(); byte[] cbs = b64.decode(certStr); X509Certificate cert = KeyLoader .loadX509Certificate(new ByteArrayInputStream(cbs)); String sigStr = document.getSello(); byte[] signature = b64.decode(sigStr); byte[] bytes = getOriginalBytes(in); Signature sig = Signature.getInstance("SHA1withRSA"); sig.initVerify(cert); sig.update(bytes); boolean bool = sig.verify(signature); if (!bool) { throw new Exception("Sello de Emisor inválido");//("Invalid signature"); } }
byte[] getOriginalBytes(InputStream in) throws Exception{ ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { Source source = new StreamSource(in); Source xsl = new StreamSource(getClass().getResourceAsStream(XSLT)); Result out = new StreamResult(baos); TransformerFactory factory = tf; if (factory == null) { factory = TransformerFactory.newInstance(); factory.setURIResolver(new URIResolverImpl()); } Transformer transformer = factory .newTransformer(new StreamSource(getClass().getResourceAsStream(XSLT))); transformer.transform(source, out); } finally { in.close(); }
return baos.toByteArray();
}
Con lo cuál solo basta hacer la invocación necesaria enviando algun FileInputStream p. ej. obviamente teniendo instanciado previamente el objeto CFDv32 correctamente.
No lo aplico al SVN/GitHub ya que yo cuento con una version de la libreria que es desde las primeras versiones y he ido modificando y adecuando a mis necesidades. Espero ayudar a varios con este tema que en realidad llega a ser desesperante.
— Reply to this email directly or view it on GitHubhttps://github.com/bigdata-mx/factura-electronica/issues/77#issuecomment-44224856 .
Muchas gracias por el aporte, ahorita estoy en proyecto pero en cuanto pueda lo probaré. El may 26, 2014 7:04 p.m., "poseidon24" notifications@github.com escribió:
Buenas tardes, me tope con el mismo problema y normalmente retornaba a los usuarios finales que hablaran con sus PACs y volvieran a generar su factura cuando tenian datos como cantidad="02" o importe=".25" o importe="1.200000".
Sin embargo en este momento me vi obligado a dar solución definitiva ya que el SAT para los ex-REPECOs y que ahora pertenecen al Régimen de Incorporación Fiscal obliga a que expidan los CFDI por su portal. Y el propio SAT expide las facturas con los detalles de los ejemplos expuestos, y el que mas me dio problema fue la fecha ya que ellos la expresan asi "2014-05-14T12:25:03Z", con la Z al final, lo cual las librerias de bigdata al usar el Binder para DateTime omite dicha información, por lo cuál resulta en un sello inválido.
La solución que implemente fue:
1- Agregar el método sobrecargado a la clase correspondiente (en mi caso CFDv32.java) verificar y getOriginalBytes, recibiendo un InputStream, creo que el autor de la libreria o alguien mas lo comento en otro post. 2- Los nuevos métodos sobrecargados deberian verse así:
public void verificar(InputStream in) throws Exception{ String certStr = document.getCertificado(); Base64 b64 = new Base64(); byte[] cbs = b64.decode(certStr); X509Certificate cert = KeyLoader .loadX509Certificate(new ByteArrayInputStream(cbs)); String sigStr = document.getSello(); byte[] signature = b64.decode(sigStr); byte[] bytes = getOriginalBytes(in); Signature sig = Signature.getInstance("SHA1withRSA"); sig.initVerify(cert); sig.update(bytes); boolean bool = sig.verify(signature); if (!bool) { throw new Exception("Sello de Emisor inválido");//("Invalid signature"); } }
byte[] getOriginalBytes(InputStream in) throws Exception{ ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { Source source = new StreamSource(in); Source xsl = new StreamSource(getClass().getResourceAsStream(XSLT)); Result out = new StreamResult(baos); TransformerFactory factory = tf; if (factory == null) { factory = TransformerFactory.newInstance(); factory.setURIResolver(new URIResolverImpl()); } Transformer transformer = factory .newTransformer(new StreamSource(getClass().getResourceAsStream(XSLT))); transformer.transform(source, out); } finally { in.close(); }
return baos.toByteArray();
}
Con lo cuál solo basta hacer la invocación necesaria enviando algun FileInputStream p. ej. obviamente teniendo instanciado previamente el objeto CFDv32 correctamente.
No lo aplico al SVN/GitHub ya que yo cuento con una version de la libreria que es desde las primeras versiones y he ido modificando y adecuando a mis necesidades. Espero ayudar a varios con este tema que en realidad llega a ser desesperante.
— Reply to this email directly or view it on GitHubhttps://github.com/bigdata-mx/factura-electronica/issues/77#issuecomment-44224856 .
Hola el problema que tengo es el siguiente: Al validar un XML cuyas cantidades o importes no tenga el formato con dos decimales, marca Sello Invalido, la misma factura la paso en el SAT y me dice que el sello es válido.
importe="9543.870000" valorUnitario="9543.870000" cantidad="1.000000"> ó cantidad=".39"
Hay alguna forma de que el sello se tome tal y como vienen los valores en el XML, sin que haga ajustes.