Hola todos,
Alguien tiene alguna función que compruebe/valide el CIF español?
(El NIF de personas jurídicas, empresas...)
Muchas gracias,
///////////////////////////////
// ValidacionNif.prg
//
//
// Validacion de NIF, CIF y NIE nacional
// Cuando se hizo, Junio 2023, comprobaba todos los tipos de CIF y letras en NIF/ NIE existentes
//
// Todos los méritos para Juan Pastor, el creador de las funciones.
// Apenas hice yo (Paquito) el testeo y unas leves modificaciones
/////////////////////////////////////////////////////////////////////////////////////////////
#Define CRLF Chr(13)+ Chr(10)
#define regex_CIF '^(?>[NPQRSW]{1}\d{7}[A-J]{1})$|^(?>[ABEH]{1}\d{7}\d{1})$|^(?>[CDFGJUV]{1}\d{7}[A-J0-9]{1})$|^(?>[ABCDEFGHJNPQRSUVW]{1}00\d{5}[A-J]{1})$'
#define regex_NIE '^([XYZ])(\d{7,8})([A-Z])$'
#define regex_DNI '^(\d{8})([A-Z])$'
// 08/06/23
// Esta es la funcion PRINCIPAL que comprueba y es la que se exporta para ser usada desde fuera
// Esta funcion lo comprueba todo: NIF, CIF y NIE
// Se requiere que cCode sea Nacional, para lo cual la nacion ha de ser comprobada
// antes de entrar o lo que sea para garantizar que el parametro se corresponde con un
// NIF, CIF o NIE nacional.
//
function NIFCheck_JuanPastor( cCode )
Local lRet := .F.
cCode := ( hb_StrReplace( cCode, " .-/\,_" ) ) // 08/06/23
Do Case
Case hb_RegExLike( regex_DNI, cCode ) // DNI - NIF
lRet := DNICheck( cCode )
Case hb_RegExLike( regex_NIE, cCode ) // NIE
lRet := DNICheck( cCode )
Case hb_RegExLike( regex_CIF, cCode ) // CIF
lRet := CIFCheck( cCode )
End Case
return lRet // 19/06/23
/* FUNCION: CIFCheck( cCode )
Comprueba si una CIF es correcto
Parámetros:
cCode - CIF
Devuelve:
Logical
*/
STATIC Function CIFCheck(cCode)
Local lRet := .F.
Local cDigit
// Comprueba si formato CIF es correcto
If !hb_RegExLike( regex_CIF, cCode )
return lRet
endif
// Empieze por: PQRSW -> Letra // HJUV -> Digito // Resto -> Indiferente // Si empieza por 00 -> Letra
cDigit := CIFDigit( cCode )
if ( Left( cCode, 1 ) $ "PQRSWABEH" ) .or. SubStr( cCode, 2, 2 ) == '00' // Obligatoriamente es Letra o Dígito
lRet := Right( cCode, 1 ) == cDigit
else // // Puede ser Letra o Dígito indistintamente
lRet := cDigit != NIL .AND.;
( Right( cCode, 1) == cDigit .or. Right( cCode, 1) == Chr(Val(IIF(cDigit == '0','10',cDigit) ) + 64) )
endif
return lRet
/* FUNCION: CIFDigit( cCode )
Calcula los dígitos de control de un CIF
Parámetros:
cCode - Código CIF
Devuelve:
Character o NIL si no cumple formato */
STATIC Function CIFDigit( cCode )
Local nCheckSum := 0
Local nImpar := 0
Local n := 0
Local cRet := 0
Local cNewCode
// cNewCode := Upper( hb_StrReplace( cCode, " .-/\,_" ) )
cNewCode := ( hb_StrReplace( cCode, " .-/\,_" ) ) // Al 08/06/23
cNewCode := SubStr( cCode, 2, Len( cCode ) - 2 ) // Parte numérica
// Comprueba si formato CIF es correcto
If !hb_RegExLike( regex_CIF, cCode )
return NIL
endif
for n := 1 TO Len ( cNewCode )
if n % 2 == 0
nCheckSum += Val( SubStr( cNewCode, n, 1 ) )
else
nImpar := Val( SubStr( cNewCode, n, 1 ) ) * 2
nCheckSum += Int( nImpar / 10 ) + ( nImpar % 10 )
endif
next
if ( Left( cCode, 1 ) $ "NPQRSW" ) .or. SubStr( cCode, 2, 2 ) == '00'
cRet := Chr( 10 - ( nCheckSum % 10 ) + 64 ) // Devuelve Letra
else
cRet := Str( ( 10 - ( nCheckSum % 10 ) ) % 10, 1) // Devuelve Dígito
endif
return cRet
/* FUNCION: DNICheck( cCode )
Comprueba un DNI / NIF / NIE e Correcto
Devuelve:
Logical
*/
STATIC function DNICheck( cDNI )
return DNILetter( cDNI ) == Right( cDNI, 1 )
/* FUNCION: DNILetter( cCode )
Calcula el caracter de control de un DNI / NIF Fisico / NIE
Devuelve:
Character o NIL si no cumple formato
*/
STATIC function DNILetter( cDNI )
Local cClv := "TRWAGMYFPDXBNJZSQVHLCKE"
//cDNI := Upper( hb_StrReplace( cDNI , " .-/\,_" ) )
cDNI := ( hb_StrReplace( cDNI , " .-/\,_" ) ) // Al 08/06/23
If hb_RegExLike( regex_NIE, cDNI ) // Si es NIE
cDNI := Str( Asc( Left( cDNI, 1 ) ) - 88, 1 ) + SubStr( cDNI, 2 )
endif
If !hb_RegExLike( regex_DNI, cDNI )
return NIL
endif
cDNI := Left( cDNI, Len( cDNI ) - 1 )
return SubStr( cClv, mod( Val( cDNI ), 23 ) + 1, 1 )
STATIC function CheckType( cCode )
Local cRet := ''
// cCode := Upper( hb_StrReplace( cCode, " .-/\,_" ) )
cCode := ( hb_StrReplace( cCode, " .-/\,_" ) ) // Al 08/06/23
Do Case
Case hb_RegExLike( regex_DNI, cCode ) // DNI - NIF
cRet := "DNI/NIF Fisico"
Case hb_RegExLike( regex_NIE, cCode ) // NIE
cRet := "NIE"
Case hb_RegExLike( regex_CIF, cCode ) // CIF
cRet := "NIF/CIF Juridico"
End Case
return cRet
paquitohm wrote:Ahí va !
Validacion de NIF, CIF y NIE nacional
Cuando se hizo, Junio 2023, comprobaba todos los tipos de CIFS y letras en NIF/ NIE existentes
Todos los méritos para Juan Pastor, el creador de las funciones.
apenas hice yo (Paquito) el testeo y unas leves modificaciones
FiveWiDi wrote:paquitohm wrote:Ahí va !
Validacion de NIF, CIF y NIE nacional
Cuando se hizo, Junio 2023, comprobaba todos los tipos de CIFS y letras en NIF/ NIE existentes
Todos los méritos para Juan Pastor, el creador de las funciones.
apenas hice yo (Paquito) el testeo y unas leves modificaciones
Las variables tipo 'regex_DNI' ... Que valores tienen? De dónde salen?
Falta algún fichero .CH ?
Muchas Paquito.
paquitohm wrote:He modificado el fuente y he puesto las constantes faltantes al principio
function NIFCheck_JuanPastor( cCode, lEmpty )
Local lRet := .F.
If lEmpty == Nil // 12/11/2024
lEmpty := .F.
EndIf
cCode := ( hb_StrReplace( cCode, " .-/\,_" ) ) // 08/06/23
Do Case
Case hb_RegExLike( regex_DNI, cCode ) // DNI - NIF
lRet := DNICheck( cCode )
Case hb_RegExLike( regex_NIE, cCode ) // NIE
lRet := DNICheck( cCode )
Case hb_RegExLike( regex_CIF, cCode ) // CIF
lRet := CIFCheck( cCode )
End Case
If( lEmpty .and. Empty(cCode), lRet := .T., Nil ) // 12/11/2024
return lRet // 19/06/23
FiveWiDi wrote:Hola Paquito,
Como que yo preciso poder dejar el NIF/CIF en blanco, he modificado la función así para que sea compatible con el uso actual:
- Code: Select all Expand view RUN
function NIFCheck_JuanPastor( cCode, lEmpty )
Local lRet := .F.
If lEmpty == Nil // 12/11/2024
lEmpty := .F.
EndIf
cCode := ( hb_StrReplace( cCode, " .-/\,_" ) ) // 08/06/23
Do Case
Case hb_RegExLike( regex_DNI, cCode ) // DNI - NIF
lRet := DNICheck( cCode )
Case hb_RegExLike( regex_NIE, cCode ) // NIE
lRet := DNICheck( cCode )
Case hb_RegExLike( regex_CIF, cCode ) // CIF
lRet := CIFCheck( cCode )
End Case
If( lEmpty .and. Empty(cCode), lRet := .T., Nil ) // 12/11/2024
return lRet // 19/06/23
Con las primeras pruebas me va perfecto, lástima que el CIF de Amazon ( LU.....) no se lo coma.
Ya he leído que deben ser códigos españoles,
Muchas gracias de nuevo.
//////////////////////////
// Vies.prg
//
// Clase para comprobar un codigo VIES (Operador Intracomunitario)
//
// Autor: Paquito
/////////////////////////////////////////////////////////////////////////////
//-------------------------------------------------------------------------//
FUNCTION PruebaTCheckVies()
Local oCheck
Local a
Local c, nItem, lOk
Local cCountry, cVatNumber
Local cFile
*
a:= {;
"PT249774194",;
"ESA28017895",;
"PT212629514",;
"PT122965795",;
"PT509064329",;
"PT233221638",;
"PT132291037",;
"PT513376810",;
"PT201580314",;
"ESA28017895",;
"PT514652110" ;
}
*
oCheck:= TCheckVies():New()
IF !oCheck:lActivate()
RETURN NIL
ENDIF
*
c:= ""
FOR nItem:= 1 TO Len(a)
cCountry := Left( a[nItem], 2)
cVatNumber:= SubStr(a[nItem], 3)
*
lOk:= oCheck:lCheck(cCountry, cVatNumber)
c+= "CHECANDO "+ cCountry+ "/"+ cVatNumber+;
" ("+ If(lOk, "Si correcto", "No correcto")+ ")"+;
CRLF
NEXT
oCheck:End()
*
cFile:= "Tmp\CHECK_VIES_"+ DateStrZeroSeconds()+ ".txt"
hb_MemoWrit(cFile, c)
run ("Notepad "+ cFile)
*
RETURN NIL
*
//-------------------------------------------------------------------------//
CLASS TCheckVies
METHOD New()
METHOD lActivate()
METHOD lCheck()
METHOD End()
DATA oDoc
DATA oHttp
DATA cUrl
ENDCLASS
//-------------------------------------------------------------------------//
METHOD New()
::cUrl:= "https://ec.europa.eu/taxation_customs/vies/rest-api/ms/%COUNTRY%/vat/%VATNUMBER%"
RETURN Self
//-------------------------------------------------------------------------//
METHOD lActivate()
*
Local lOk:= .t.
Local oTry
*
xTRY INI TO oTry
::oDoc := CreateObject( "MSXML2.DOMDocument" )
::oHttp:= CreateObject( "MSXML2.XMLHTTP" )
xTRY END
*
IF oTry:lError
lOk:= .f.
oTry:SaveError()
ENDIF
*
RETURN lOk
*
*
//-------------------------------------------------------------------------//
METHOD lCheck(cCountry, cVatNumber, cCountryYVatNumber)
local odoc := ::oDoc
local ohttp := ::oHttp
local cResponseText
Local cUrl := ::cUrl
Local hHash
Local lOk
IF cCountryYVatNumber != NIL
cCountry := Left( cCountryYVatNumber, 2)
cVatNumber:= Substr(cCountryYVatNumber, 3)
ENDIF
///////////////////////////////////// cUrl:= "https://ec.europa.eu/taxation_customs/vies/rest-api/ms/%COUNTRY%/vat/%VATNUMBER%"
cUrl:= StrTran(cUrl, "%COUNTRY%" , cCountry )
cUrl:= StrTran(cUrl, "%VATNUMBER%", cVatNumber)
ohttp:Open( "GET" , cUrl, .F. )
oHttp:SetRequestHeader( "Content-Type" , "application/x-www-form-urlencoded" )
oHttp:setRequestHeader('User-Agent', 'node-soap')
oHttp:setRequestHeader('Accept' , 'text/html,application/xhtml+xml,application/xml,text/xml;q=0.9,*/*;q=0.8')
oHttp:setRequestHeader('Accept-Encoding', 'none')
oHttp:setRequestHeader('Accept-Charset', 'utf-8')
oDoc:async := .f.
oDoc:LoadXml('<?xml version=""1.0"" encoding=""utf-8""?>')
ohttp:Send(oDoc:xml)
cResponseText:= alltrim(ohttp:responseText)
#Define lES_JSON cLeft(cResponseText, "{")
#Define cDATA_ "isValid"
#Define lJSON_ESTRUCTURA_OK ( lES_JSON .AND. At("isValid", cResponseText) > 0 )
lOk:= !Empty(cResponseText) .AND. lJSON_ESTRUCTURA_OK
IF lOk
hb_jsonDecode(cResponseText, @hHash)
lOk:= Valtype(hHash) == "H" .AND. hb_hPos(hHash, cDATA_) > 0
IF lOk
lOk:= hHash[cDATA_] // True / False
ELSE
FLOGMSG_("Error !! No es hash o no es de la estructura o data isValid no encontrado !!", cResponseText, cDATA_, Valtype(hHash))
ENDIF
ELSE
FLOGMSG_("Error !! Respuesta vacia o invalida !!", cResponseText)
ENDIF
RETURN lOk
//-------------------------------------------------------------------------//
METHOD End()
::oDoc := NIL
::oHttp:= NIL
RETURN NIL
Return to Off Topic / Otros temas
Users browsing this forum: No registered users and 6 guests