diff --git a/Contabilidad/ContabilidadElectronica.aspx.vb b/Contabilidad/ContabilidadElectronica.aspx.vb
index 6774efaa5..126988874 100644
--- a/Contabilidad/ContabilidadElectronica.aspx.vb
+++ b/Contabilidad/ContabilidadElectronica.aspx.vb
@@ -1,9 +1,20 @@
Option Explicit On
Option Strict On
-Imports System.Data
-Imports System.IO
Imports Extensiones
+Imports System
+Imports System.IO
+Imports System.Security.Cryptography
+Imports System.Security.Cryptography.X509Certificates
+Imports System.Text
+Imports System.Xml
+Imports System.Xml.Xsl
+Imports System.Data
+Imports CrystalDecisions.Web
+Imports DocumentFormat.OpenXml.Wordprocessing
+Imports Org.BouncyCastle.Asn1
+Imports Org.BouncyCastle.Tls.Crypto.Impl
+
Partial Class Contabilidad_ContabilidadElectronica
Inherits ClsPaginas
@@ -95,7 +106,7 @@ Partial Class Contabilidad_ContabilidadElectronica
End If
objconta.Dispose()
Else
- Dim ObjConpaq As New ClsContPAQi(UsuarioActual.Empresa)
+ Dim ObjConpaq As New ClsContPAQi(UsuarioActual.Empresa)
If ObjConpaq.GetCuentasElectronica(MinFecha, FechaF) Then
DtCuentas = ObjConpaq.DtResultados
End If
@@ -112,9 +123,6 @@ Partial Class Contabilidad_ContabilidadElectronica
Str.AppendFormat("RFC=""{0}"" ", UsuarioActual.Empresa.RFC)
Str.AppendFormat("Mes=""{0}"" ", DdlPeriodo.SelectedValue)
Str.AppendFormat("Anio=""{0}"" ", DdlEjercicio.SelectedValue)
- Str.AppendFormat("Sello=""{0}"" ", "123")
- Str.AppendFormat("noCertificado=""{0}"" ", "123")
- Str.AppendFormat("Certificado=""{0}"" ", "1234567890")
Str.Append("xmlns:catalogocuentas=""www.sat.gob.mx/esquemas/ContabilidadE/1_3/CatalogoCuentas"">")
'DETALLES
@@ -147,21 +155,15 @@ Partial Class Contabilidad_ContabilidadElectronica
ArchivoCuentas = $"{UsuarioActual.Empresa.Ruta}/ContabilidadElectronica/{ UsuarioActual.Empresa.RFC}{DdlEjercicio.SelectedValue}{DdlPeriodo.SelectedValue.PadLeft(2, "0"c)}CT.xml"
'SOBREESCRIBE
- If System.IO.File.Exists(ArchivoCuentas) Then
- System.IO.File.Delete(ArchivoCuentas)
- End If
-
- Dim fs As FileStream = File.Create(ArchivoCuentas)
- Dim info As Byte() = New UTF8Encoding(True).GetBytes(Str.ToString)
- fs.Write(info, 0, info.Length)
- fs.Close()
+ If System.IO.File.Exists(ArchivoCuentas) Then System.IO.File.Delete(ArchivoCuentas)
'DESCARGA XML
Dim DescargaZIP As Ionic.Zip.ZipFile = New Ionic.Zip.ZipFile()
- If IO.File.Exists(ArchivoCuentas) Then
- DescargaZIP.AddFile(ArchivoCuentas, "")
- End If
+ 'generar el sello
+ SellarXML(Str.ToString, ArchivoCuentas, 1)
+
+ If IO.File.Exists(ArchivoCuentas) Then DescargaZIP.AddFile(ArchivoCuentas, "")
DescargaZIP.Save(Response.OutputStream)
Response.AddHeader("content-Disposition", String.Format("attachment; filename={0}{1}{2}CT.zip", UsuarioActual.Empresa.RFC, DdlEjercicio.SelectedValue, DdlPeriodo.SelectedValue.PadLeft(2, "0"c)))
@@ -172,6 +174,84 @@ Partial Class Contabilidad_ContabilidadElectronica
End Sub
+ Private Function SellarXML(xmltexto As String, ArchivoCuentas As String, Opcion As Integer) As String
+ Dim ArchivoLLave As String = $"{UsuarioActual.Empresa.Ruta}Certificados\{UsuarioActual.Empresa.ArchivoKey}"
+ Dim Archivopfx As String = $"{UsuarioActual.Empresa.Ruta}Certificados\{UsuarioActual.Empresa.FielPFX }"
+ Dim Clavepfx As String = UsuarioActual.Empresa.FielPassword
+
+ Dim xsltPath As String
+ Select Case Opcion
+ Case 1
+ xsltPath = $"{AppDomain.CurrentDomain.BaseDirectory}Temp\CatalogoCuentas_1_3.xslt"
+ Case 2
+ xsltPath = $"{AppDomain.CurrentDomain.BaseDirectory}Temp\BalanzaComprobacion_1_3.xslt"
+ End Select
+
+ If Not File.Exists(ArchivoLLave) Then
+ Alert("El archivo de llave privada no existe", TipoMensaje.MsgError)
+ End If
+
+ ' 1. Cargar y transformar el XML para obtener la Cadena Original
+ Dim originalCadena As String = GenerarCadenaOriginal(xmltexto, xsltPath)
+
+ ' 2. Cargar tu certificado PFX (incluye la clave privada)
+ Dim cert As New X509Certificate2(Archivopfx, Clavepfx, X509KeyStorageFlags.MachineKeySet)
+
+ ' 3. Firmar la cadena con SHA256
+ Dim selloBytes As Byte()
+ Using rsa As RSA = cert.GetRSAPrivateKey()
+ selloBytes = rsa.SignData(
+ Encoding.UTF8.GetBytes(originalCadena),
+ HashAlgorithmName.SHA256,
+ RSASignaturePadding.Pkcs1)
+ End Using
+ Dim selloBase64 As String = Convert.ToBase64String(selloBytes)
+
+ ' 4. Obtener el certificado (público) en Base64 y el número de certificado
+ Dim certBase64 As String = Convert.ToBase64String(cert.RawData)
+ Dim noCertificado As String = cert.GetSerialNumberString()
+
+ ' 5. Insertar atributos en el XML
+ Dim xmlDoc As New XmlDocument()
+ xmlDoc.PreserveWhitespace = True ' conserva espacios y saltos
+ xmlDoc.LoadXml(xmltexto)
+
+ Dim root As XmlElement = xmlDoc.DocumentElement
+ root.SetAttribute("Sello", selloBase64)
+ root.SetAttribute("noCertificado", noCertificado)
+ root.SetAttribute("certificado", certBase64)
+
+ ' 6. Guardar archivo sellado
+ Dim StrFinal As String = xmlDoc.OuterXml
+ Dim fs As FileStream = File.Create(ArchivoCuentas)
+ Dim info As Byte() = New UTF8Encoding(True).GetBytes(StrFinal)
+ fs.Write(info, 0, info.Length)
+ fs.Close()
+ 'xmlDoc.Save(ArchivoCuentas)
+ Return StrFinal
+ End Function
+
+ '''
+ ''' Aplica el XSLT para generar la Cadena Original según SAT.
+ '''
+ Function GenerarCadenaOriginal(xmlContenido As String, xsltFile As String) As String
+ ' Carga la transformación XSLT
+ Dim xslt As New XslCompiledTransform()
+ xslt.Load(xsltFile)
+
+ ' Prepara un StringReader sobre el contenido del XML
+ Using sr As New StringReader(xmlContenido),
+ xr As XmlReader = XmlReader.Create(sr),
+ sw As New StringWriter()
+
+ ' Ejecuta la transformación
+ xslt.Transform(xr, Nothing, sw)
+
+ ' Devuelve la cadena original (trim para quitar saltos extra)
+ Return sw.ToString().Trim()
+ End Using
+ End Function
+
Private Sub GeneraBalanza()
Dim FechaI As Date = String.Format("01/{0}/{1}", DdlPeriodo.SelectedValue.PadLeft(2, "0"c), DdlEjercicio.SelectedValue).ToDate
Dim FechaF As Date = FechaI.LastDayOfMonth
@@ -186,10 +266,10 @@ Partial Class Contabilidad_ContabilidadElectronica
If DtCuentas IsNot Nothing Then
Dim Deudor As Decimal = DtCuentas.SUM("SaldoAD")
Dim Acreedor As Decimal = DtCuentas.SUM("SaldoAA")
- If Deudor <> Acreedor Then
- Alert("los Saldos Actuales no cuadran.", TipoMensaje.MsgError)
- Exit Sub
- End If
+ 'If Deudor <> Acreedor Then
+ ' Alert("los Saldos Actuales no cuadran.", TipoMensaje.MsgError)
+ ' Exit Sub
+ 'End If
End If
Else
Dim ObjConpaq As New ClsContPAQi(UsuarioActual.Empresa)
@@ -204,24 +284,23 @@ Partial Class Contabilidad_ContabilidadElectronica
'CABECERA
Str.Append("")
- Str.Append("")
-
+ Str.AppendFormat("FechaModBal=""{0}"" >", FechaF.ToString("yyyy-MM-dd"))
'DETALLES
For Each Dr As DataRow In DtCuentas.Rows
- Str.Append("")
Next
-
DtCuentas.Dispose()
'FIN
- Str.Append("")
-
+ Str.Append("")
'GUARDA ARHIVO
ArchivoBalanza = Server.MapPath(String.Format("~/Empresas/{0}/ContabilidadElectronica/{1}{2}{3}BN.xml", UsuarioActual.CveEmpresa, UsuarioActual.Empresa.RFC, DdlEjercicio.SelectedValue, DdlPeriodo.SelectedValue.PadLeft(2, "0"c)))
@@ -251,14 +328,10 @@ Partial Class Contabilidad_ContabilidadElectronica
'SOBREESCRIBE
If System.IO.File.Exists(ArchivoBalanza) Then System.IO.File.Delete(ArchivoBalanza)
-
- Dim fs As FileStream = File.Create(ArchivoBalanza)
- Dim info As Byte() = New UTF8Encoding(True).GetBytes(Str.ToString)
- fs.Write(info, 0, info.Length)
- fs.Close()
-
'DESCARGA XML
Dim DescargaZIP As Ionic.Zip.ZipFile = New Ionic.Zip.ZipFile()
+ 'generar el sello
+ SellarXML(Str.ToString, ArchivoBalanza, 2)
If IO.File.Exists(ArchivoBalanza) Then
DescargaZIP.AddFile(ArchivoBalanza, "")
@@ -275,6 +348,4 @@ Partial Class Contabilidad_ContabilidadElectronica
#End Region
-
-
End Class