From 385b9079d29eea6d855dedb1ea8f2a60f8df2aa1 Mon Sep 17 00:00:00 2001 From: manuel Date: Wed, 22 Jul 2026 09:03:26 +0200 Subject: [PATCH] 2026-07-22 1.1.19 Nueva Clase ValidacionDocumentosIdentidad para documentos extranjeros --- ValidacionDocumentosIdentidadVIES.vb | 127 +++++++++++++++++++++++++++ tsUtilidades.vbproj | 3 +- 2 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 ValidacionDocumentosIdentidadVIES.vb diff --git a/ValidacionDocumentosIdentidadVIES.vb b/ValidacionDocumentosIdentidadVIES.vb new file mode 100644 index 0000000..0e4810d --- /dev/null +++ b/ValidacionDocumentosIdentidadVIES.vb @@ -0,0 +1,127 @@ +Imports System.Net.Http +Imports System.Text.Json +Imports System.Text.RegularExpressions +Imports System.Threading.Tasks + +Public Class VatValidationResult + Public Property IsValid As Boolean + Public Property Name As String + Public Property Address As String + Public Property RawJson As String + Public Property ErrorMessage As String +End Class + +Public Class ValidacionDocumentosIdentidad + + ' ----------------------------- + ' 1) Validación de formato VAT + ' ----------------------------- + Private Shared ReadOnly Patterns As New Dictionary(Of String, String) From { + {"AT", "^[A-Z]U[0-9]{8}$"}, + {"BE", "^[0-9]{10}$"}, + {"BG", "^[0-9]{9,10}$"}, + {"CY", "^[0-9]{8}[A-Z]$"}, + {"CZ", "^[0-9]{8,10}$"}, + {"DE", "^[0-9]{9}$"}, + {"DK", "^[0-9]{8}$"}, + {"EE", "^[0-9]{9}$"}, + {"EL", "^[0-9]{9}$"}, + {"ES", "^[A-Z0-9][0-9]{7}[A-Z0-9]$"}, + {"FI", "^[0-9]{8}$"}, + {"FR", "^[A-Z0-9]{2}[0-9]{9}$"}, + {"HR", "^[0-9]{11}$"}, + {"HU", "^[0-9]{8}$"}, + {"IE", "^[0-9]{7}[A-W][A-I]?$"}, + {"IT", "^[0-9]{11}$"}, + {"LT", "^[0-9]{9}|[0-9]{12}$"}, + {"LU", "^[0-9]{8}$"}, + {"LV", "^[0-9]{11}$"}, + {"MT", "^[0-9]{8}$"}, + {"NL", "^[0-9]{9}B[0-9]{2}$"}, + {"PL", "^[0-9]{10}$"}, + {"PT", "^[0-9]{9}$"}, + {"RO", "^[0-9]{2,10}$"}, + {"SE", "^[0-9]{12}$"}, + {"SI", "^[0-9]{8}$"}, + {"SK", "^[0-9]{10}$"}, + {"XI", "^[0-9]{9}$"} ' Irlanda del Norte + } + + Public Shared Function IsValidVatFormat(countryCode As String, + vatNumber As String) As Boolean + + countryCode = countryCode.ToUpper().Trim() + vatNumber = vatNumber.ToUpper().Trim() + + If Not Patterns.ContainsKey(countryCode) Then + Return False + End If + + Return Regex.IsMatch(vatNumber, Patterns(countryCode)) + End Function + + + ' ----------------------------- + ' 2) Cliente HTTP compartido + ' ----------------------------- + Private Shared ReadOnly _http As New HttpClient() With { + .Timeout = TimeSpan.FromSeconds(10) + } + + + ' ----------------------------- + ' 3) Validación VIES vía REST (ASÍNCRONA) + ' ----------------------------- + Public Shared Async Function ValidateVatAsync(countryCode As String, + vatNumber As String) As Task(Of VatValidationResult) + + Dim result As New VatValidationResult() + + Try + ' Validación de formato previa + If Not IsValidVatFormat(countryCode, vatNumber) Then + result.IsValid = False + result.ErrorMessage = $"Formato VAT inválido para {countryCode}" + Return result + End If + + Dim url = $"https://ec.europa.eu/taxation_customs/vies/rest-api/ms/{countryCode}/vat/{vatNumber}" + + Dim json As String = Await _http.GetStringAsync(url) + result.RawJson = json + + Dim doc = JsonDocument.Parse(json) + Dim root = doc.RootElement + + result.IsValid = root.GetProperty("isValid").GetBoolean() + + If result.IsValid Then + result.Name = root.GetProperty("traderName").GetString() + result.Address = root.GetProperty("traderAddress").GetString() + End If + + Catch ex As HttpRequestException + result.ErrorMessage = "Error HTTP: " & ex.Message + + Catch ex As TaskCanceledException + result.ErrorMessage = "Timeout al consultar VIES" + + Catch ex As Exception + result.ErrorMessage = "Error inesperado: " & ex.Message + End Try + + Return result + End Function + + + ' ----------------------------- + ' 4) Validación VIES vía REST (SINCRONA) + ' ----------------------------- + Public Shared Function ValidateVat(countryCode As String, + vatNumber As String) As VatValidationResult + + Return ValidateVatAsync(countryCode, vatNumber).GetAwaiter().GetResult() + + End Function + +End Class diff --git a/tsUtilidades.vbproj b/tsUtilidades.vbproj index 89333c4..54d52bc 100644 --- a/tsUtilidades.vbproj +++ b/tsUtilidades.vbproj @@ -16,11 +16,12 @@ net8.0 tsUtilidades net8.0, libreria - 1.1.18 + 1.1.19 Manuel Tecnosis S.A Utilidades Varias + - 2026-07-22 1.1.19 Nueva Clase ValidacionDocumentosIdentidad para documentos extranjeros - 2026-05-29 1.1.18 Corrección rutina LeeMysql y LeeMysqlBytArray para que como maximo se admitan 2048 caracteres string - 2026-05-29 1.1.17 Corrección rutina LeeMysql para que como maximo se admitan 2048 caracteres string - 2026-05-19 1.1.16 Corrección multiplataforma tsNotificacionesClient