Imagen

DESCARGA SOFTWARE PARA FACTURA ELECTRONICA DE AQUI.
Facturacion, Validacion, Addendas, Librerias de programacion, etc.


ECODEX TIENE ESTOS NUEVOS DATOS DE CONTACTO :
Comercializacion y Ventas - Evelia Vicke evicke@ecodex.com.mx 33-16-03-03-48
Soporte - Humberto Guerrero soporte@ecodex.com.mx 33-34-90-46-03

Cancelacion de CFDI con el PAC Facturador Electronico

Foro dedicado para discutir la parte tecnica de como es el timbrado
[[ FORO CERRADO DEBIDO A QUE YA LA INFORMACION YA NO ES VIGENTE ]]
acanche
Mensajes: 8
Registrado: Vie Jul 12, 2013 10:28 am

Cancelacion de CFDI con el PAC Facturador Electronico

Mensajepor acanche » Mié Sep 04, 2013 11:22 am

Hola buenas tardes:


Estoy realizando el Timbrado de mis XML con el PAC Facturador Electronico, Uso C# para el desarrollo.
Pero al momento de Cancelar un XML me manda el Siguiente Mensaje de Error:

<solicitud esValido="False" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="">
<errores>
<Error codigo="044" mensaje="La llaveCertificado no está correctamente formada ó no corresponde con el Certificado establecido" />
</errores>
</solicitud>



Y ya he revisado y si se esta enviando la informacion en forma correcta.
Estoy utilizando los certificados de Prueba del PAC
Alguien ha tenido este mismo problema en alguna ocasion con este proveedor?

Espero sus comentarios
Saludos
Abelardo
AC

CexarE
Mensajes: 13
Registrado: Vie Jun 29, 2012 10:55 am

Re: Cancelacion de CFDI con el PAC Facturador Electronico

Mensajepor CexarE » Jue Oct 10, 2013 11:22 am

A mi me paso lo mismo, pero envie un correo al proveedor y me enviaron la solucion. Te la paso, solo que Yo estoy desarrollando en PHP, espero te sirva:

Es requerido que se tenga la llave privada en la siguiente estructura, (Este es el formato XML de como debiera obtenerse el contenido de la llavePrivada):

Código: Seleccionar todo


<RSAKeyValue>
  <Modulus>...</Modulus>
  <Exponent>...</Exponent>
  <P>...</P>
  <Q>...</Q>
  <DP>...</DP>
  <DQ>...</DQ>
  <InverseQ>...</InverseQ>
  <D>...</D>
</RSAKeyValue>

y esto lo tendrías que pasar a base 64.

Paso 1: Generar archivos PEM a partir de los key y cer (si ya generabas CFD, esto ya lo sabes hacer), (Se hace sólo una vez al instalar el sello del cliente en nuestro sistema):

Código: Seleccionar todo


<?php
   system('openssl x509 -in 00001000000201532020.cer -inform DER -out 00001000000201532020.cer.pem -outform PEM');
   system('openssl pkcs8 -in mars7001114w6_1207111111s.key -inform DER -passin pass:xxxxxx -out mars7001114w6_1207111111s.key.pem -outform PEM'); ?>

Esto genera los archivos 00001000000201532020.cer.pem y mars7001114w6_1207111111s.key.pem que ya todos conocemos y que son los que se están usando actualmente para el "sellado" del XML.

(Ahora, esto es lo nuevo):
Paso 2: Obtener los datos internos de la llave privada, Con el siguiente código en php:

Código: Seleccionar todo


<?php
   $Comando = "openssl rsa -inform PEM -outform PEM -in mars7001114w6_1207111111s.key.pem -out 1.txt -text";
?>


El comando anterior genera un archivo de texto plano (1.txt) con la siguiente información:

Código: Seleccionar todo


Private-Key: (1024 bit) modulus: 00:9c:d3:00:13:f9:f7:7f:58:40:16:20:63:13:e2: a7:91:75:42:ca:17:1a:0a:e7:1f:81:5c:6f:c2:49: f2:ed:60:3c:7c:57:8b:c6:c7:37:58:d1:bd:40:40: e6:a8:9c:c0:7c:4d:6a:23:f7:ae:ab:d3:e6:ce:6a: 05:b0:c7:98:14:6d:ef:9b:e5:c2:d8:17:1f:13:f0: d9:5d:ad:42:a3:d4:4e:b6:4d publicExponent: 65537 (0x10001) privateExponent: 7a:d0:99:26:27:d0:47:8e:59:41:fa:c3:1c:c3:97: 23:36:41:33:1e:ee:65:6c:67:03:ce:5e:85:bc:2b: d3:1f:be:57:42:4b:ee:21:6a:35:2b:00:2c:a5:3f: 28:0e:9b:8a:e2:d7:e7:ff:7f:cc:04:3b:b2:33:ca: e7:03:36:45:a9:fe:95:01 prime1: 00:ce:75:67:31:cf:96:0b:c5:0b:9f:45:67:f1:4b:
21:d7:88:e1:b0:76:6f:6c:5c:e5:66:8c:00:21:ed: 01:da:2b:76:18:a6:7d:12:12:98:56:a0:22:c9:7d: 73:8f:f6:74:51 prime2: 00:c2:75:06:18:aa:6b:26:7c:1a:fa:d0:03:36:4c: 31:ca:3a:0f:3c:0a:e6:f3:54:20:d6:2a:77:1a:e5: 71:5b:11:ce:2d:28:bf:19:ed:58:96:fc:62:24:e2: da:31:b0:4f:3d exponent1: 7b:64:7d:bd:ae:84:ce:1a:01:9d:3a:7d:2a:20:ae: 64:44:16:27:16:51:f7:e0:f9:96:35:7c:6a:ca:8a: 15:26:be:99:73:00:2c:aa:62:73:fb:97:6e:f7:54: 97:29:44:51 exponent2: 0e:31:dc:b7:12:39:a0:25:8f:12:9f:fc:9c:0a:14: ce:a6:d6:90:09:33:36:ed:4c:5c:e5:7f:f7:09:ed: d8:85:44:77:6d:94:4e:4e:e5:d6:bc:62:d5:63:ca: dd:87:b1:41 coefficient: 55:43:8b:f1:e1:c0:9e:59:65:06:ce:0f:6d:ec:53: 74:fa:88:ad:83:c3:00:0a:f4:f2:8c:6a:09:84:61: 27:3c:7f:63 -----BEGIN RSA PRIVATE KEY----- MIICWwIBAAKBgQCc01kT+fd/WEAWIGMT4qeRdULKFxoK5x+BXG/CSfLtYDx8V4vG xzdY0b1AQPQnmRoHSJB30X3yFbJQZmRlQ6TWRSrn/PtZ/QXSyR/5q+SZGGMkps80 UNolceaonMB8TWoj966r0+bOagWwx5gUbe+b5cLYFx8T8NldrUKj1E62TQIDAQAB AoGAetCZJifQR45ZQfrDHMOX7zYhxBorbvZpmelGLKW09Wk0dTwqXtWM5qX6y+MS UiB4XdPaL7uEIp4TMxu87AD5iQpQpHsQiPTi6OU+IzZBMx7uZWxnA85ehbwr0x++ UiB4XdPaL7uEIp4TMxu87AD5iQpQpHsQiPTi6OU+IzZBMx7uZWxnA85ehbwr0x++9+D5ljV8asqKTOMr7q7Qh4/Q6mG7smc/FSa+mXMALKpic/uXbvdUlylEUQJADjHc txI5oCWPEp/8nAoUzqbWkAkzNu1MXOV/9wnt2IVEd22UTk7l1rxi1WPKUouKMWG4 EXxx6xOhVm/43Yex KA6biuLX5/9/zAQ7sjPK5wM2Ran lBs4PbexTdPqIrYPDJAr08oxqCYRhg6Os JNIUov9QKBl1czFpR9yiBguZBmmKtxvFnZrXJzx/Yw== -----END RSA PRIVATE KEY-----

Esto lo guardo en la variable $LLaveCertif.

Paso 3: Extraer los datos de cada "modulo". Guardando en variables, la informacion de cada "modulo" del archivo obtenido. Por ejemplo:

Código: Seleccionar todo


$Modulus = "00:9c:d3:59:13:f9:f7:7f:58:40:16:20:63:13:e2:a7:91:75:42:ca:17:1a:0a:e7:1f:81:5c:6f:c2:49:f2: 3:a4:d6:45:2a:e7:fc:fb:59:fd:05:d2:c9:1f:f9:ab:e4:99:18:63:24:a6:cf:34:50:da:25:71:e6:a8:9c:c0:
7c:4d:6a:23:f7:ae:ab:d3:e6:ce:6a:05:b0:14:6d:ef:9b:e5:c2:d8:17:1f:13:f0:d9:5d:ad:42:a3:d4:4e:b6:4d";
$PrivateExponent = "7a:d0:99:26:27:d0:47:8e:59:41:fa:c3:1c:c3:97:ef:36:21:c4:1a:2b:6e:f6:69:99:e9:46:2c:a5:b4:f5:69:34:75:3c:2a:5e:d5:8c:e6:a5:fa:cb:e3:12:52:20:78:5d:d3:da:2f:bb:84:22:9e:13:33:1b:bc:ec:00::42:4b:ee:27:6a:35:2b:00:2c:a5:3f:28:0e:9b:8a:e2:d7:e7:ff:7f:cc:04:3b:b2:33:ca:e7:03:36:45:a9:fe:95:01";

etc...

Yo lo hago con esta funcion:

Código: Seleccionar todo


$Modulus = obtenerCadena($LLaveCertif, 'modulus:', 'publicExponent:');
....

function obtenerCadena($contenido,$inicio,$fin){
   $r = explode($inicio, $contenido);
   if (isset($r[1])){
      $r = explode($fin, $r[1]);
      $saltos = array("\r\n", "\n\r", "\n", "\r");
      $r[0] = str_replace ($saltos, "", $r[0]);
      $r[0] = str_replace(" ", "", $r[0]);
      return $r[0];
   }
   return '';
}


Despues aplico otra funcion para eliminar los dos puntos ":" y convertir de hexadecimal a string y convertir a base64:

Código: Seleccionar todo


$Modulus = SSLDataExtractedToXMLData($Modulus, true);
...

function SSLDataExtractedToXMLData($SSLData, $JumpFirst)
{
   $ArrVals = explode(":", $SSLData);
   $a = "";
   if ($JumpFirst)
   {
      $inicio = 1;
   } else {
      $inicio = 0;
   }
   for($i = $inicio; $i < count($ArrVals); $i = $i + 1)
   {
      $a = $a.hexToStr($ArrVals[$i]);
   }
   return base64_encode($a);
}

function hexToStr($hex)
{
    $string='';
    for ($i=0; $i < strlen($hex)-1; $i+=2)
    {
        $string .= chr(hexdec($hex[$i].$hex[$i+1]));
    }
    return $string;
}


Paso 4: Agrego las variables a la estructura requerida para la cancelacion

Código: Seleccionar todo


$KeyInXML = base64_encode("<RSAKeyValue><Modulus>".[u]$Modulus[/u]."</Modulus><Exponent>".[u]$PublicExponent[/u]."</Exponent><P>".[u]$Prime1[/u]."</P><Q>".[u]$Prime2[/u]."</Q><DP>".[u]$Exponent1[/u]."</DP><DQ>".[u]$Exponent2[/u]."</DQ><InverseQ>".[u]$Coefficient[/u]."</InverseQ><D>".[u]$PrivateExponent[/u]."</D></RSAKeyValue>");

echo "<br>KeyInXML base64: " . $KeyInXML . "<br><br>";


(Y al final guardo el resultado de este proceso en un campo de mi base de datos, y asi lo utilizo cada que necesito hacer una cancelacion, "pegandoselo" al requerimiento del web-service para cancelacion)...

Cuando voy a cancelar a "$xml" le asigno el Dato que guarde anteriormente con el XML base64 de la llave privada.

Código: Seleccionar todo


   //<Funcion cancelarComprobante
   $params = array(
      "xmlCancelacion" => $xml,
      "usuario" => $user,
      "password" => $pw         
   );
   $resultado = $client->call("cancelarComprobante", $params, $mynamespace);


Y con eso ya me funciono correctamente la Cancelacion del CFDI con dicho web-service.

Espero te sirva.
Saludos...

mauricio
Mensajes: 372
Registrado: Mié Ago 11, 2010 1:55 am
Ubicación: México, D.F.
Contactar:

Re: Cancelacion de CFDI con el PAC Facturador Electronico

Mensajepor mauricio » Mar Oct 15, 2013 10:03 pm

Guau!... eso es pensar sencillo!!...
Todo lo que no es dado es perdido

acanche
Mensajes: 8
Registrado: Vie Jul 12, 2013 10:28 am

Re: Cancelacion de CFDI con el PAC Facturador Electronico

Mensajepor acanche » Mié Oct 16, 2013 1:17 pm

Hola buenas tardes:

Gracias, ya se ha logrado realizar la cancelacion utilizando la Clase opensslkey.cs

Coloco Funcion para alguno que lo requiera...

En ella le paso los parametros:

private static XmlElement CrearNodoCancelacion()
{
///////////////FUNCION PARA LA CANCELACION DE FACTURAS CON FACTURADOR ELECTRONICO//////////////////////////////////////////7
String filename = "C:\\Cert\\llavePrivada.pem";

StreamReader sr = File.OpenText(filename);
String pemstr = sr.ReadToEnd().Trim();
sr.Close();
if (pemstr.StartsWith("-----BEGIN"))
JavaScience.opensslkey.DecodePEMKey(pemstr);
else
JavaScience.opensslkey.DecodeDERKey(filename);
//CODIFICO PARA PODER LUEGO PASARLO A LA FUNCION Y APLICARLO A BASE 64

RSACryptoServiceProvider rsa = JavaScience.opensslkey.DecodePEMKey(pemstr);
if (rsa != null)
{
String xmlprivatekey = rsa.ToXmlString(true);
llave = Convert.ToBase64String(Encoding.UTF8.GetBytes(xmlprivatekey.ToString()));
}
///////////////TERMINA FUNCION PARA LA CANCELACION DE FACTURAS CON FACTURADOR ELECTRONICO//////////////////////////////////////////7

XmlElement Cancelacion;
Cancelacion = xmlCancelacion.CreateElement("Cancelacion");
Cancelacion.SetAttribute("rfcEmisor", RFCEmisorCancelacion);
Cancelacion.SetAttribute("certificado", ObtenerCertificado());
Cancelacion.SetAttribute("llaveCertificado", llave);
IndentarNodo(Cancelacion);
return Cancelacion;
}
AC

jasistemas
Mensajes: 158
Registrado: Mié Ene 11, 2012 2:08 pm
Contactar:

Re: Cancelacion de CFDI con el PAC Facturador Electronico

Mensajepor jasistemas » Jue Oct 17, 2013 12:21 pm

Buena aportación acanche

Yo uso también openSSLKey.cs, solo que accedo directo al archivo .key, no necesito migrar a .pem, a mi se me hace muy comodo... y son las mismas rutinas.

Saludos

acanche
Mensajes: 8
Registrado: Vie Jul 12, 2013 10:28 am

Re: Cancelacion de CFDI con el PAC Facturador Electronico

Mensajepor acanche » Mié Nov 13, 2013 3:55 pm

Hola jasistemas

De que manera haces el envio con el .key unicamente desde la funciona?
ya que yo estuve intentando pero me mandaba la informacion incorrecta a como la pide Facturador electronico.

Saludos
Abelardo
AC

jasistemas
Mensajes: 158
Registrado: Mié Ene 11, 2012 2:08 pm
Contactar:

Re: Cancelacion de CFDI con el PAC Facturador Electronico

Mensajepor jasistemas » Mié Nov 20, 2013 8:47 am

Bueno, si depuras el código del C# veras que tiene varias rutinas para los diferentes argumentos y tipos de archivos (constructores), en mi caso únicamente tuve que asignar los parámetros indicando la ruta del .key y password, luego fui siguiendo el código hasta encontrar la sección del código donde se procesaba para comprenderlo mejor e ir documentando mi código, pero prácticamente opensslkey.cs ya traía todo

acanche
Mensajes: 8
Registrado: Vie Jul 12, 2013 10:28 am

Re: Cancelacion de CFDI con el PAC Facturador Electronico

Mensajepor acanche » Mié Nov 20, 2013 4:17 pm

Perfecto.. Lo voy a estar revisando

Gracias y Saludos
AC
AC

Trex
Mensajes: 2
Registrado: Mar Dic 10, 2013 7:04 pm

Re: Cancelacion de CFDI con el PAC Facturador Electronico

Mensajepor Trex » Mar Dic 10, 2013 7:24 pm

Hola a todos.
Estoy siguiendo el procedimiento de CexarE para obtener el xml de la llave privada en base64

Pero tengo un problema con el nodo exponent1

el valor correcto de ese nodo es:
<DP>Sw5EJhxDGYGqfglmZ8UQaXfukyYep+uRJoLZojuvcG+NEwhFL5RiuTcKtKKTAZXGJAbnjvHOGMUI4DEPgDIYYQ==</DP>

pero con el procedimiento me da el siguiente valor:
<DP>DkQmHEMZgap+CWZnxRBpd+6TJh6n65EmgtmiO69wb40TCEUvlGK5Nwq0opMBlcYkBueO8c4YxQjgMQ+AMhhh</DP>

Por lo tanto al convertir el XML completo en base64 me da un resultado diferente al correcto, todos los demas nodos me salen correctos excepto "exponent1"

lo obtengo de la sigiente manera:
$Exponent1 = obtenerCadena($LLaveCertif, 'exponent1:', 'exponent2:');

$Exponent1 = SSLDataExtractedToXMLData($Exponent1, true);

Alguna sugerencia?? :?:

Gracias por su tiempo, saludos a todos :)

Trex
Mensajes: 2
Registrado: Mar Dic 10, 2013 7:04 pm

Re: Cancelacion de CFDI con el PAC Facturador Electronico

Mensajepor Trex » Mar Dic 10, 2013 7:58 pm

Gracias a todos, para resolverlo se debe poner el ultimo parámetro en false para que se brinque el primer elemento del arreglo

INCORRECTO:
$Exponent1 = SSLDataExtractedToXMLData($Exponent1, true);

CORRECTO:
$Exponent1 = SSLDataExtractedToXMLData($Exponent1, false);

:mrgreen:

saludos


Volver a “Envio para Timbrado”

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 5 invitados