This commit is contained in:
2025-05-20 17:14:02 -07:00
parent d4a08c9d28
commit a3add6893c

View File

@@ -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
''' <summary>
''' Aplica el XSLT para generar la Cadena Original según SAT.
''' </summary>
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("<?xml version=""1.0"" encoding=""UTF-8""?>")
Str.Append("<BCE:Balanza xsi:schemaLocation=""www.sat.gob.mx/esquemas/ContabilidadE/1_3/BalanzaComprobacion/BalanzaComprobacion_1_3.xsd"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" Version=""1.3"" ")
Str.Append("<bnc:Balanza ")
Str.Append("xmlns:bnc =""http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/BalanzaComprobacion"" ")
Str.Append("xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" ")
Str.Append("xsi:schemaLocation=""http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/BalanzaComprobacion http://www.sat.gob.mx/esquemas/ContabilidadE/1_3/BalanzaComprobacion/BalanzaComprobacion_1_3.xsd"" ")
Str.Append("Version=""1.3"" ")
Str.AppendFormat("RFC=""{0}"" ", UsuarioActual.Empresa.RFC)
Str.AppendFormat("Mes=""{0}"" ", DdlPeriodo.SelectedValue)
Str.AppendFormat("Anio=""{0}"" ", DdlEjercicio.SelectedValue)
Str.AppendFormat("TipoEnvio=""{0}"" ", "C")
Str.AppendFormat("FechaModBal=""{0}"" ", FechaF.ToString("yyyy-MM-dd"))
Str.AppendFormat("Sello=""{0}"" ", "123")
Str.AppendFormat("noCertificado=""{0}"" ", "123")
Str.AppendFormat("Certificado=""{0}"" ", "1234567890")
Str.Append("xmlns:BCE=""www.sat.gob.mx/esquemas/ContabilidadE/1_3/BalanzaComprobacion"">")
Str.AppendFormat("FechaModBal=""{0}"" >", FechaF.ToString("yyyy-MM-dd"))
'DETALLES
For Each Dr As DataRow In DtCuentas.Rows
Str.Append("<BCE:Ctas ")
Str.Append("<bnc:Ctas ")
If UsuarioActual.Empresa.TipoContabilidad = 1 Then
Str.AppendFormat("NumCta=""{0}"" ", Dr("Codigo").ToString)
Str.AppendFormat("NumCta=""{0}"" ", Dr("Codigo").ToString.Replace("-", ""))
Str.AppendFormat("SaldoIni=""{0}"" ", Dr("SaldoInicial").ToString)
Str.AppendFormat("Debe=""{0}"" ", Dr("Cargos").ToString)
Str.AppendFormat("Haber=""{0}"" ", Dr("Abonos").ToString)
@@ -236,12 +315,10 @@ Partial Class Contabilidad_ContabilidadElectronica
Str.Append("/>")
Next
DtCuentas.Dispose()
'FIN
Str.Append("</BCE:Balanza>")
Str.Append("</bnc:Balanza>")
'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