177 lines
5.4 KiB
VB.net
177 lines
5.4 KiB
VB.net
Imports System.Net.Http
|
|
Imports System.Text.Json
|
|
Imports System.Text.Json.Serialization
|
|
Imports System.Text.RegularExpressions
|
|
Imports System.Threading.Tasks
|
|
|
|
' ============================================================
|
|
' CLASES DE MODELO PARA EL JSON DEVUELTO POR VIES (REST)
|
|
' ============================================================
|
|
|
|
Public Class ViesApproximate
|
|
<JsonPropertyName("matchName")>
|
|
Public Property MatchName As Integer
|
|
|
|
<JsonPropertyName("matchStreet")>
|
|
Public Property MatchStreet As Integer
|
|
|
|
<JsonPropertyName("matchPostalCode")>
|
|
Public Property MatchPostalCode As Integer
|
|
|
|
<JsonPropertyName("matchCity")>
|
|
Public Property MatchCity As Integer
|
|
|
|
<JsonPropertyName("matchCompanyType")>
|
|
Public Property MatchCompanyType As Integer
|
|
End Class
|
|
|
|
Public Class ViesRestResponse
|
|
<JsonPropertyName("isValid")>
|
|
Public Property IsValid As Boolean
|
|
|
|
<JsonPropertyName("requestDate")>
|
|
Public Property RequestDate As Date
|
|
|
|
<JsonPropertyName("userError")>
|
|
Public Property UserError As String
|
|
|
|
<JsonPropertyName("name")>
|
|
Public Property Name As String
|
|
|
|
<JsonPropertyName("address")>
|
|
Public Property Address As String
|
|
|
|
<JsonPropertyName("requestIdentifier")>
|
|
Public Property RequestIdentifier As String
|
|
|
|
<JsonPropertyName("originalVatNumber")>
|
|
Public Property OriginalVatNumber As String
|
|
|
|
<JsonPropertyName("vatNumber")>
|
|
Public Property VatNumber As String
|
|
|
|
<JsonPropertyName("viesApproximate")>
|
|
Public Property ViesApproximate As ViesApproximate
|
|
|
|
' Campo adicional para errores locales
|
|
Public Property LocalError As String
|
|
End Class
|
|
|
|
|
|
' ============================================================
|
|
' VALIDADOR COMPLETO VAT + VIES REST
|
|
' ============================================================
|
|
|
|
Public Class ValidacionDocumentosIdentidadVIES
|
|
|
|
' -----------------------------
|
|
' 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}$"}
|
|
}
|
|
|
|
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 ViesRestResponse)
|
|
|
|
Dim result As New ViesRestResponse()
|
|
|
|
Try
|
|
' Normalización
|
|
countryCode = countryCode.Trim().ToUpper()
|
|
vatNumber = vatNumber.Trim().ToUpper()
|
|
|
|
' Validación de formato previa
|
|
If Not IsValidVatFormat(countryCode, vatNumber) Then
|
|
result.LocalError = $"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).ConfigureAwait(False)
|
|
|
|
result = JsonSerializer.Deserialize(Of ViesRestResponse)(json)
|
|
|
|
Catch ex As HttpRequestException
|
|
result.LocalError = "Error HTTP: " & ex.Message
|
|
|
|
Catch ex As TaskCanceledException
|
|
result.LocalError = "Timeout al consultar VIES"
|
|
|
|
Catch ex As Exception
|
|
result.LocalError = "Error inesperado: " & ex.Message
|
|
End Try
|
|
|
|
Return result
|
|
End Function
|
|
|
|
|
|
' -----------------------------
|
|
' 4) Validación VIES vía REST (SINCRONA SEGURA PARA WPF)
|
|
' -----------------------------
|
|
Public Shared Function ValidateVat(countryCode As String,
|
|
vatNumber As String) As ViesRestResponse
|
|
|
|
Return Task.Run(
|
|
Async Function()
|
|
Return Await ValidateVatAsync(countryCode, vatNumber).ConfigureAwait(False)
|
|
End Function
|
|
).Result
|
|
|
|
End Function
|
|
|
|
End Class
|