Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Envío de registros y sus respuestas (https://www.clubdelphi.com/foros/forumdisplay.php?f=66)
-   -   Ejemplo para crear la Huella (https://www.clubdelphi.com/foros/showthread.php?t=97085)

gohermo 04-12-2024 09:40:48

Ejemplo para crear la Huella
 
Buenos días,
Estoy intentando hacer un programa en Visual Studio Basic para calcular la huella siguiendo el ejemplo en java que la AEAT expone en la documentación, y el resultado es diferente. Alguien podría compartir el código en Visual Studio Basic?

Expongo el código que estoy utilizando:

Código:

Imports System
Imports System.Security.Cryptography
Imports System.Text
Imports System.Web

Module Program
    Sub Main(args As String())
        Console.WriteLine(CalculaHuellaAlta("89890001K", "12345678/G33", "01-01-2024", "F1", "12.35", "123.45", "", "2024-01-01T19:20:30+01:00"))

    End Sub


    ' Genera el hash en formato Base16 (hexadecimal) en mayúsculas
    Public Function GetHashVerificada(msg As String) As String
        Try
            Dim digest As HashAlgorithm = SHA256.Create()
            Dim hash As Byte() = digest.ComputeHash(Encoding.UTF8.GetBytes(msg))

            ' Convertir el hash a formato hexadecimal en mayúsculas
            Dim sb As New StringBuilder()
            For Each b As Byte In hash
                sb.Append(b.ToString("X2")) ' X2 asegura mayúsculas
            Next
            Return sb.ToString()
        Catch ex As Exception
            Throw New ArgumentException("Error al generar la huella SHA", ex)
        End Try
    End Function

    ' Genera la referencia concatenada
    Public Function GetReferenciaRegistroAlta(nifEmisor As String, numFacturaSerie As String,
                                                    fechaExpedicion As String, tipoFactura As String,
                                                    cuotaTotal As String, importeTotal As String,
                                                    huellaAnterior As String, fechaHoraUsoRegistro As String) As String
        Dim sb As New StringBuilder()
        sb.Append(GetValorCampo("IDEmisorFactura", nifEmisor, True)) _
          .Append(GetValorCampo("NumSerieFactura", numFacturaSerie, True)) _
          .Append(GetValorCampo("FechaExpedicionFactura", fechaExpedicion, True)) _
          .Append(GetValorCampo("TipoFactura", tipoFactura, True)) _
          .Append(GetValorCampo("CuotaTotal", cuotaTotal, True)) _
          .Append(GetValorCampo("ImporteTotal", importeTotal, True)) _
          .Append(GetValorCampo("Huella", huellaAnterior, True)) _
          .Append(GetValorCampo("FechaHoraUsoRegistro", fechaHoraUsoRegistro, False))

        Return sb.ToString()
    End Function

    ' Concatena un campo con su valor y separador
    Public Function GetValorCampo(nombre As String, valor As String, separador As Boolean) As String
        If separador Then
            Return nombre & "=" & If(String.IsNullOrEmpty(valor), "", valor.Trim()) & ";"
        Else
            Return nombre & "=" & If(String.IsNullOrEmpty(valor), "", valor.Trim())
        End If
    End Function
    ' Calcula la huella completa
    Public Function CalculaHuellaAlta(nifEmisor As String, numFacturaSerie As String, fechaExpedicion As Date,
                                            tipoFactura As String, cuotaTotal As String, importeTotal As String,
                                            huellaAnterior As String, fechaHoraUsoRegistro As String) As String
        ' Genera la referencia concatenada
        Dim ref As String = GetReferenciaRegistroAlta(nifEmisor, numFacturaSerie, fechaExpedicion.ToString("yyyy-MM-dd"),
                                                      tipoFactura, cuotaTotal, importeTotal, huellaAnterior, fechaHoraUsoRegistro)

        ' Genera el hash en Base16
        Return GetHashVerificada(ref)
    End Function
End Module

Resultado obtenido: 07DCAADE3EA3216A80409A37359A5A53D48038F7BD2C61D51178CD7112C3E9FA
Resultado que debería de ser según la documentación de la AEAT: 3C464DAF61ACB827C65FDA19F352A4E3BDC2C640E9E9FC4CC058073F38F12F60

Gracias de antemano por la ayuda.

Saludos,

MaeseKvothe 04-12-2024 10:23:36

Buenas. Yo lo tengo en C#, estoy algo oxidado en VB pero creo que veo algún error.

Estás añadiendo un separador ";" entre campos al pasar el true como parámetro. El separador en todo caso sería "&".
El string te tiene que quedar con el "&" como inicio del nombre de cada campo excepto del primero(IDEmisorFactura). Cambiando eso ya te debería salir bien. Si te sigue saliendo mal pon también cómo te queda el string antes de convertirlo y será más fácil localizar otros posibles fallos.

Ese código del SHA256 huele a ChatGPT :D

gohermo 04-12-2024 10:52:58

Error en huella
 
Gracias por la respuesta MaeseKvothe,

He reemplazado el separador ";" por el "&", y displayo en consola la cadena:

IDEmisorFactura=89890001K&NumSerieFactura=12345678/G33&FechaExpedicionFactura=01-01-2024&TipoFactura=F1&CuotaTotal=12.35&ImporteTotal=123.45&Huella=&FechaHoraUsoRegistro=2024-01-01T19:20:30+01:00
A63B2F9600DDAAD8464120FBA23486E9F0BB39619060C1C75AA08135314560D3

Y según el manual de la AEAT es el siguiente:

Código:

calcularHuella("IDEmisorFactura=89890001K&NumSerieFactura=12345678/G33&FechaExpedicionFactura=01-01-2024&TipoFactura=F1&CuotaTotal=12.35&ImporteTotal=123.45&Huella=&FechaHoraHusoGenRegistro=2024-01-01T19:20:30+01:00”);
Debería devolver el siguiente dato de salida como valor de la huella o «hash»:
3C464DAF61ACB827C65FDA19F352A4E3BDC2C640E9E9FC4CC058073F38F12F60

Te agradezco la ayuda.

Saludos

gohermo 04-12-2024 11:06:30

Error en huella
 
Gracias por la respuesta MaeseKvothe,

He reemplazado el separador ";" por el "&", y displayo en consola la cadena:

IDEmisorFactura=89890001K&NumSerieFactura=12345678/G33&FechaExpedicionFactura=01-01-2024&TipoFactura=F1&CuotaTotal=12.35&ImporteTotal=123.45&Huella=&FechaHoraUsoRegistro=2024-01-01T19:20:30+01:00
A63B2F9600DDAAD8464120FBA23486E9F0BB39619060C1C75AA08135314560D3

Y según el manual de la AEAT es el siguiente:
Código:

calcularHuella("IDEmisorFactura=89890001K&NumSerieFactura=12345678/G33&FechaExpedicionFactura=01-01-2024&TipoFactura=F1&CuotaTotal=12.35&ImporteTotal=123.45&Huella=&FechaHoraHusoGenRegistro=2024-01-01T19:20:30+01:00”);
Debería devolver el siguiente dato de salida como valor de la huella o «hash»:
3C464DAF61ACB827C65FDA19F352A4E3BDC2C640E9E9FC4CC058073F38F12F60

Te agradezco la ayuda.

Saludos

gohermo 04-12-2024 11:15:37

Ya está resuelto, para quien le pueda ayudar, el problema lo tenia en la etiqueta "FechaHoraHusoGenRegistro" que estaba mal escrita.

IDEmisorFactura=89890001K&NumSerieFactura=12345678/G33&FechaExpedicionFactura=01-01-2024&TipoFactura=F1&CuotaTotal=12.35&ImporteTotal=123.45&Huella=&FechaHoraHusoGenRegistro=2024-01-01T19:20:30+01:00
3C464DAF61ACB827C65FDA19F352A4E3BDC2C640E9E9FC4CC058073F38F12F60

Gracias por la colaboración.

Saludos,

Neftali [Germán.Estévez] 05-12-2024 11:47:51

Cita:

Empezado por gohermo (Mensaje 560387)
Expongo el código que estoy utilizando:
...


Por favor, a los que sois usuarios nuevos, revisad la Guía de estilo de los foros.

Una de las cosas que explica es que en los mensajes donde se añade código es útil utilizar los TAGs destinados a ese menester.
Hay una etiqueta para DELPHI y otra genérica para otros lenguajes.
Gracias.


razorxxx 18-12-2024 12:49:55

En Delphi, la función para calcular la huella SHA-256 es sencilla:

Código Delphi [-]
function GetSHA256HashOfString(const Texto: String): String;
begin
       Result := THashSHA2.GetHashString(Texto, THashSHA2.TSHA2Version.SHA256);
end;

Y aquí la llamada, creando primero la cadena con los campos que pide Verifactu (en este ejemplo, los campos están en TEdit en pantalla):

Código Delphi [-]
procedure CalcularHuella;
var
   Cadena: String;
begin
     // Formar la cadena de entrada desde la que se calculará el hash
     Cadena := 'IDEmisorFactura=' + Trim(NIF.Text) + '&';
     Cadena := Cadena + 'NumSerieFactura=' + Trim(NumSerieFac.Text) + '&';
     Cadena := Cadena + 'FechaExpedicionFactura=' + Trim(FechaExpe.Text) + '&';
     Cadena := Cadena + 'TipoFactura=' + Trim(TipoFac.Text) + '&';
     Cadena := Cadena + 'CuotaTotal=' + Trim(Cuota.Text) + '&';
     Cadena := Cadena + 'ImporteTotal=' + Trim(Importe.Text) + '&';
     Cadena := Cadena + 'Huella=' + Trim(HuellaAnterior.Text) + '&';
     Cadena := Cadena + 'FechaHoraHusoGenRegistro=' + Trim(FechaGenReg.Text);
     Consola.Lines.Add('Cadena de entrada: ' + Cadena);
     // Calcular el hash SHA-256 de la cadena formada anteriormente y devolverlo en mayúsculas como exige Veri*Factu
     Consola.Lines.Add('Cadena de salida: ' + AnsiUpperCase(GetSHA256HashOfString(Cadena)));
end;

Lo probé con el ejemplo que aparece en la documentación de la AEAT y devuelve exactamente el mismo hash. Imprescindible poner en el uses la unit System.Hash

netsistemas 24-01-2025 21:13:59

Formateo Fecha.
 
Ojo con la función publicada. El formateo de la fecha yo creo que está mal:
debe ser dd-MM-yyyy

Código:

        ' Genera la referencia concatenada
        Dim ref As String = GetReferenciaRegistroAlta(nifEmisor, numFacturaSerie, fechaExpedicion.ToString("dd-MM-yyyy"),
                                                          tipoFactura, cuotaTotal, importeTotal, huellaAnterior, fechaHoraUsoRegistro)


Jarogo08 28-01-2025 10:27:34

Yo lo hago así en VB .NET:



Código:

Public Function HuellaVerifactu_Alta(ByVal IDEmisorFactura As String, ByVal NumSerieFactura As String, ByVal FechaExpedicionFactura As Date, ByVal TipoFactura As String, _
                                      ByVal CuotaTotal As Decimal, ByVal ImporteTotal As Decimal, ByVal Huella As String, ByVal FechaHoraHusoGenRegistro As String) As String

        Dim HuellaVerifactu As String = ""

        Dim Cadena As String = ""
        Cadena += "IDEmisorFactura=" & IDEmisorFactura & "&"
        Cadena += "NumSerieFactura=" & NumSerieFactura & "&"
        Cadena += "FechaExpedicionFactura=" & Format(FechaExpedicionFactura, "dd-MM-yyyy") & "&"
        Cadena += "TipoFactura=" & TipoFactura & "&"
        Cadena += "CuotaTotal=" & CuotaTotal.ToString.Replace(",", ".") & "&"
        Cadena += "ImporteTotal=" & ImporteTotal.ToString.Replace(",", ".") & "&"
        Cadena += "Huella=" & Huella & "&"
        Cadena += "FechaHoraHusoGenRegistro=" & FechaHoraHusoGenRegistro

        HuellaVerifactu = ObtenerHashVerifactu(Cadena)

        Return HuellaVerifactu
    End Function

    Public Function ObtenerHashVerifactu(ByVal cadena As String) As String
        Using sha256 As SHA256 = sha256.Create()
            Dim array As Byte() = sha256.ComputeHash(Encoding.UTF8.GetBytes(cadena))
            Return BitConverter.ToString(array).Replace("-", "").ToUpper
        End Using
    End Function


Como dicen arriba, hay que tener cuidado con los formatos de los campos (sobretodo FechaHoraHusoGenRegistro) porque si no tiene el formato esperado dará error.


Espero que le pueda servir a alguien


La franja horaria es GMT +2. Ahora son las 21:02:23.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi