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