Pasos necesarios:
1. Genear XML con datos de factura
2. Obtener Cadena Original usando xml generado.
3. Obtener “sello” de la cadena original (SHA1 y RSA)
4. Enviar XML a PAC (proveedor autorizado de certificación)
Necesitarán dos clases que adjunto:
• clFacturaElectronica.cs, está construida con la herramienta xsd.exe utilizando el xsd proporcionado por el SAT. ([URL="http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv32.xsd"]http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv32.xsd[/URL])
• clsSeguridad.cs, librería publicada en este mismo foro que está basada en “OpenSSL.cs”
Ahora, comencemos.
Es necesario tener la ruta a los archivos .cer y .key proporcionados por el SAT:
Cita:
(**** private String ***)
strPath = Path.GetDirectoryName(Application.ExecutablePath);
strCertFile = strPath + @"\aaa010101aaa__csd_01.cer";
strKeyFile = strPath + @"\aaa010101aaa__csd_01.key";
strKeyClave=@"12345678a";
(*** String deben ser llenados en algún momento previo al proceso ****)
strPath = Path.GetDirectoryName(Application.ExecutablePath);
strCertFile = strPath + @"\aaa010101aaa__csd_01.cer";
strKeyFile = strPath + @"\aaa010101aaa__csd_01.key";
strKeyClave=@"12345678a";
(*** String deben ser llenados en algún momento previo al proceso ****)
Cita:
//Creamos una nueva clase y comenzamos a llenar
Comprobante oComp = new Comprobante();
oComp.Receptor = new ComprobanteReceptor();
oComp.Receptor.Domicilio = new t_Ubicacion();
oComp.Emisor = new ComprobanteEmisor();
oComp.Emisor.DomicilioFiscal = new t_UbicacionFiscal();
oComp.Emisor.RegimenFiscal = new ComprobanteEmisorRegimenFiscal[1];
oComp.Emisor.RegimenFiscal[0] = new ComprobanteEmisorRegimenFiscal();
oComp.Conceptos = new ComprobanteConcepto[1]; // N° Filas Detalle Factura
oComp.Impuestos = new ComprobanteImpuestos();
oComp.Impuestos.Traslados = new ComprobanteImpuestosTraslado[1];
oComp.Impuestos.Traslados[0] = new ComprobanteImpuestosTraslado();
// Datos
oComp.version = “3.2”;
oComp.folio = “111”;
....
.... deben llenar todas las propiedades necesarias.
....
X509Certificate2 x509 = new X509Certificate2(strCertFile);
if (x509 != null)
{
oComp.certificado = Convert.ToBase64String(x509.RawData);
oComp.noCertificado = clsSeguridad.HexToString(x509.SerialNumber);
}
oComp.sello = "**Pendiente**";
XmlDocument oXML = Class2XmlDocument(oComp);
String strCadenaOriginal = ObtieneCadenaOriginal_XSLT(oXML);
String strSello = ObtieneSello_RSA(strCadenaOriginal);
oXML.ChildNodes[1].Attributes["sello"].Value = strSello;
txbResultado.Text = oXML.InnerXml; // texbox con el resultado xml que se debe enviar al PAC
Comprobante oComp = new Comprobante();
oComp.Receptor = new ComprobanteReceptor();
oComp.Receptor.Domicilio = new t_Ubicacion();
oComp.Emisor = new ComprobanteEmisor();
oComp.Emisor.DomicilioFiscal = new t_UbicacionFiscal();
oComp.Emisor.RegimenFiscal = new ComprobanteEmisorRegimenFiscal[1];
oComp.Emisor.RegimenFiscal[0] = new ComprobanteEmisorRegimenFiscal();
oComp.Conceptos = new ComprobanteConcepto[1]; // N° Filas Detalle Factura
oComp.Impuestos = new ComprobanteImpuestos();
oComp.Impuestos.Traslados = new ComprobanteImpuestosTraslado[1];
oComp.Impuestos.Traslados[0] = new ComprobanteImpuestosTraslado();
// Datos
oComp.version = “3.2”;
oComp.folio = “111”;
....
.... deben llenar todas las propiedades necesarias.
....
X509Certificate2 x509 = new X509Certificate2(strCertFile);
if (x509 != null)
{
oComp.certificado = Convert.ToBase64String(x509.RawData);
oComp.noCertificado = clsSeguridad.HexToString(x509.SerialNumber);
}
oComp.sello = "**Pendiente**";
XmlDocument oXML = Class2XmlDocument(oComp);
String strCadenaOriginal = ObtieneCadenaOriginal_XSLT(oXML);
String strSello = ObtieneSello_RSA(strCadenaOriginal);
oXML.ChildNodes[1].Attributes["sello"].Value = strSello;
txbResultado.Text = oXML.InnerXml; // texbox con el resultado xml que se debe enviar al PAC
Funciones:
Cita:
public XmlDocument Class2XmlDocument(object pClass)
{
XmlDocument oXML = new XmlDocument();
XmlSerializerNamespaces oXMLSerializeNS = new XmlSerializerNamespaces();
XmlSerializer oXMLSerialize = new XmlSerializer(pClass.GetType());
MemoryStream oMS = new MemoryStream();
StreamWriter oSW = new StreamWriter(oMS, Encoding.UTF8);
oXMLSerializeNS.Add("cfdi", strSAT_CFDI);
oXMLSerializeNS.Add("xsi", strSAT_XSI);
oXMLSerialize.Serialize(oSW, pClass, oXMLSerializeNS);
oMS.Flush();
oMS.Position = 0;
oXML.Load(oMS);
oMS.Dispose();
oSW.Dispose();
XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add("http://www.sat.gob.mx/cfd/3", "http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv32.xsd");
oXML.Schemas.Add(schemas);
ValidationEventHandler eventHandler = new ValidationEventHandler(Class2XmlDocument_Validatio n);
oXML.Validate(eventHandler);
return oXML;
}
{
XmlDocument oXML = new XmlDocument();
XmlSerializerNamespaces oXMLSerializeNS = new XmlSerializerNamespaces();
XmlSerializer oXMLSerialize = new XmlSerializer(pClass.GetType());
MemoryStream oMS = new MemoryStream();
StreamWriter oSW = new StreamWriter(oMS, Encoding.UTF8);
oXMLSerializeNS.Add("cfdi", strSAT_CFDI);
oXMLSerializeNS.Add("xsi", strSAT_XSI);
oXMLSerialize.Serialize(oSW, pClass, oXMLSerializeNS);
oMS.Flush();
oMS.Position = 0;
oXML.Load(oMS);
oMS.Dispose();
oSW.Dispose();
XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add("http://www.sat.gob.mx/cfd/3", "http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv32.xsd");
oXML.Schemas.Add(schemas);
ValidationEventHandler eventHandler = new ValidationEventHandler(Class2XmlDocument_Validatio n);
oXML.Validate(eventHandler);
return oXML;
}
Cita:
private String ObtieneCadenaOriginal_XSLT(XmlDocument pXML)
{
XslCompiledTransform oXSLT = new XslCompiledTransform();
oXSLT.Load(strXLST);
MemoryStream oMS = new MemoryStream();
oXSLT.Transform(pXML, null, oMS);
oMS.Flush();
oMS.Position = 0;
StreamReader oSR = new StreamReader(oMS,Encoding.UTF8);
String strCadena = oSR.ReadToEnd();
oMS.Dispose();
oSR.Dispose();
return strCadena;
}
{
XslCompiledTransform oXSLT = new XslCompiledTransform();
oXSLT.Load(strXLST);
MemoryStream oMS = new MemoryStream();
oXSLT.Transform(pXML, null, oMS);
oMS.Flush();
oMS.Position = 0;
StreamReader oSR = new StreamReader(oMS,Encoding.UTF8);
String strCadena = oSR.ReadToEnd();
oMS.Dispose();
oSR.Dispose();
return strCadena;
}
Cita:
clFacturacionElectronica.cs: private String ObtieneSello_RSA(String pCadenaOriginal)
{
SecureString lSecStr = new SecureString();
lSecStr.Clear();
foreach (char c in strKeyClave.ToCharArray())
lSecStr.AppendChar(c);
Byte[] pLlavePrivadaenBytes = System.IO.File.ReadAllBytes(strKeyFile);
RSACryptoServiceProvider lrsa = clsSeguridad.DecodeEncryptedPrivateKeyInfo(pLlaveP rivadaenBytes, lSecStr);
SHA1CryptoServiceProvider oSHA1 = new SHA1CryptoServiceProvider();
Byte[] bytesFirmados_SHA = lrsa.SignData(Encoding.UTF8.GetBytes(pCadenaOrigin al.Trim()), oSHA1);
return Convert.ToBase64String(bytesFirmados_SHA);
}
{
SecureString lSecStr = new SecureString();
lSecStr.Clear();
foreach (char c in strKeyClave.ToCharArray())
lSecStr.AppendChar(c);
Byte[] pLlavePrivadaenBytes = System.IO.File.ReadAllBytes(strKeyFile);
RSACryptoServiceProvider lrsa = clsSeguridad.DecodeEncryptedPrivateKeyInfo(pLlaveP rivadaenBytes, lSecStr);
SHA1CryptoServiceProvider oSHA1 = new SHA1CryptoServiceProvider();
Byte[] bytesFirmados_SHA = lrsa.SignData(Encoding.UTF8.GetBytes(pCadenaOrigin al.Trim()), oSHA1);
return Convert.ToBase64String(bytesFirmados_SHA);
}
clsSeguridad.cs
http://rapidshare.com/files/1020870058/clSeguridad.zip
http://rapidshare.com/files/956031239/clFacturacionElectronica.zip