34 votes

How to validate a Mexican RFC and its verification digit

Question: How can I verify that the format of a Mexican RFC is valid?

What is the RFC? The Federal Taxpayers Registry (RFC) is a unique code required by every individual or legal entity in Mexico to carry out any lawful economic activity. It is the tax code for individuals and companies issued by the Mexican government. SAT .

The RFC is generated from the letters of the first name and surname (individuals), or from the acronym or the first letters of the name and the date of creation (companies). The rules of generation and validation are described in the Algorithm to generate the RFC with homoclave for individuals and companies.odt

5 votes

5 votes

0 votes

Well I moved to Mexico a couple of years ago and I was quite lost to calculate my rfc, but in this page I found the formula and they explain with an example of how to calculate it. I recommend that you read it, because the system that I used is very simple and there is no need to complicate with formulas, it worked for me and my wife, I leave you the link: https://rfconline.com.mx/

52voto

Mariano Points 21056

Regular expression

The following regular expression verifies:

  • The first 3 (legal entity) or 4 (individual) characters in capital letters.
  • Valid date (although for simplicity, months with less than 31 days are not being validated).
  • The check digit is either a digit or a letter A.
  • Allowing hyphens and/or spaces between parts.
  • Capturing each part in a group.

    /^([A-ZÑ&]{3,4}) ?(?:- ?)?(\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\d|3[01])) ?(?:- ?)?([A-Z\d]{2})([A\d])$/

Full validation

I publish the code in JavaScript to be able to run it here, but it is very easy to translate it to any other language.

//Función para validar un RFC
// Devuelve el RFC sin espacios ni guiones si es correcto
// Devuelve false si es inválido
// (debe estar en mayúsculas, guiones y espacios intermedios opcionales)
function rfcValido(rfc, aceptarGenerico = true) {
    const re       = /^([A-ZÑ&]{3,4}) ?(?:- ?)?(\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\d|3[01])) ?(?:- ?)?([A-Z\d]{2})([A\d])$/;
    var   validado = rfc.match(re);

    if (!validado)  //Coincide con el formato general del regex?
        return false;

    //Separar el dígito verificador del resto del RFC
    const digitoVerificador = validado.pop(),
          rfcSinDigito      = validado.slice(1).join(''),
          len               = rfcSinDigito.length,

    //Obtener el digito esperado
          diccionario       = "0123456789ABCDEFGHIJKLMN&OPQRSTUVWXYZ Ñ",
          indice            = len + 1;
    var   suma,
          digitoEsperado;

    if (len == 12) suma = 0
    else suma = 481; //Ajuste para persona moral

    for(var i=0; i<len; i++)
        suma += diccionario.indexOf(rfcSinDigito.charAt(i)) * (indice - i);
    digitoEsperado = 11 - suma % 11;
    if (digitoEsperado == 11) digitoEsperado = 0;
    else if (digitoEsperado == 10) digitoEsperado = "A";

    //El dígito verificador coincide con el esperado?
    // o es un RFC Genérico (ventas a público general)?
    if ((digitoVerificador != digitoEsperado)
     && (!aceptarGenerico || rfcSinDigito + digitoVerificador != "XAXX010101000"))
        return false;
    else if (!aceptarGenerico && rfcSinDigito + digitoVerificador == "XEXX010101000")
        return false;
    return rfcSinDigito + digitoVerificador;
}

//Handler para el evento cuando cambia el input
// -Lleva la RFC a mayúsculas para validarlo
// -Elimina los espacios que pueda tener antes o después
function validarInput(input) {
    var rfc         = input.value.trim().toUpperCase(),
        resultado   = document.getElementById("resultado"),
        valido;

    var rfcCorrecto = rfcValido(rfc);   // ⬅️ Acá se comprueba

    if (rfcCorrecto) {
        valido = "Válido";
      resultado.classList.add("ok");
    } else {
        valido = "No válido"
        resultado.classList.remove("ok");
    }

    resultado.innerText = "RFC: " + rfc 
                        + "\nResultado: " + rfcCorrecto
                        + "\nFormato: " + valido;
}

#resultado {
    background-color: red;
    color: white;
    font-weight: bold;
}
#resultado.ok {
    background-color: green;
}

<label>RFC:</label>
<input type="text" id="rfc_input" style="width:100%;"
       oninput="validarInput(this)" 
       placeholder="Ingrese su RFC">
<pre id="resultado"></pre>

Description

Taking as a reference the way in which the RFC is constructed:

4 letras de nombre y apellidos - fecha nac - homoclave

  1. The first 3-4 characters are taken from the name ([A-ZÑ&]{3,4}) Group 1 .
    • Initial of paternal surname (or first initial of company).
    • First internal vowel of the paternal surname (or second initial of the company).
      * In this case, we could have validated that it is only a vowel or an "X", but if the first surname has 1 or 2 letters, the first letter of the maternal surname is taken (it can be a consonant).
      * For companies, if they do not have 3 words, the following letters of the first name are taken.
    • Initial of mother's last name (or third initial of the company).
    • Initial of the name (nothing for companies, they have 3 characters in total).
  2. Optional spaces or dashes ?(?:- ?)? .
    Accepts: " " , "-" , " -" , " - " , "- " or without hyphens or spaces.
    * The pattern looks funny but it is: an optional space, followed by an optional (uncaptured) group, this matches a hyphen optionally followed by a space. If you do not want to allow spaces or hyphens, you can remove this pattern.
  3. The date of birth (or creation of the company).
    (\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\d|3[01])) Group 2 .
    • \d{2} year.
    • (?:0[1-9]|1[0-2]) month.
    • (?:0[1-9]|[12]\d|3[01]) day.
      * I am accepting up to 31 for any month. I believe that an error in entering the date data would be further validated with the check digit. However, if one wanted to be stricter, and even though could be validated in the regular expression I would recommend to do it with the functions of the programming language used.
  4. Optional spaces or dashes ?(?:- ?)? .
  5. Homoclave of 2 alphanumeric characters ([A-Z\d]{2}) Group 3 .
  6. Verifying digit (digit or letter A) ([A\d]) Group 4 .

After validating with the regex, we check that the expected check digit for the first 11 or 12 characters matches the entered check digit (the last character). We use an adaptation of the method for control codes called Module 11 o ISBN 10 .

We already have separate screenshots of the text of the 4 parts of the RFC, in which rfcSinDigito will be the first 11 or 12 characters and digitoVerificador will be the last character.

//Separar el dígito verificador del resto del RFC
const digitoVerificador = validado.pop(),
      rfcSinDigito      = validado.slice(1).join(''),

But if there are 11 characters (RFC of legal person - company), it is adjusted to use the same algorithm for both. You can precede it with a space, or directly enter the calculated value.

if (len == 12) suma = 0
else suma = 481; //Ajuste para persona moral

To calculate the expected digit, first add the index of each character from 13 to 2, multiplied by the value of each of the 12 characters, which have a value from 0 to 38 in this order (dictionary):

0123456789ABCDEFGHIJKLMN&OPQRSTUVWXYZ Ñ

for(var i=0; i<len; i++)
    suma = suma + diccionario.indexOf(rfcSinDigito.charAt(i)) * (indice - i);

And on the sum, we take the 11's complement of the remainder of dividing by 11 (or modulo 11, hence the name of the method).

digitoEsperado = 11 - suma % 11;

If it is 11, it becomes 0 . If it gives 10, it becomes A .

if (digitoEsperado == 11) digitoEsperado = 0;
else if (digitoEsperado == 10) digitoEsperado = "A";

Now we can compare if they match to return the result.

if (digitoVerificador != digitoEsperado)
    return false;

But we added 2 exceptions, for the special cases of generic RFCs ( Questions and Answers on Tax Verification, items 5 and 6

0 votes

I have a doubt, if a person is born, let's say in 1915, how does it differ from a person born in 2015, maybe the homoclave that you mention, is somehow adjusted taking into account the above. Greetings

0 votes

P.S: maybe in PA 9 the 9 represents the 9 in 1 9 15 and for a 2015 would be PA 0 I would like to say something about the previous comments.

0 votes

@AngelAngel 1915 and 2015 are both treated equally, as "15". This is not something that perhaps is otherwise. It is specified in the RFC reference... The last character of the homoclave is not the year, but the verification digit... At the weekend I will add more details (I wanted to answer you something before).

11voto

RFC Validation Algorithm

An RFC is valid if and only if it meets the following 7 conditions:

  1. The RFC must be exactly 12 or 13 characters long (12 for corporations and 13 for individuals). It is possible that our user interface allows you to enter hyphens, spaces or other separator characters. Here I speak only of the characters that compose the RFC, separators would be treated at another level.
  2. The characters of the name can only contain the capital letters A-Z, the symbol & and the Ñ. For 12-character RFCs the name is the first 3 characters and for 13 characters the name is the first 4 characters.
  3. The name is not an inconvenience. There is a table with 41 inconvenient names in the document, for example MOCO, a valid RFC cannot have that name. All the inconvenient names are for individuals (they are all four letters) but when checking it is not necessary to check that the RFC is 13 characters long. We can check against the first four directly, if we give as incorrect an RFC of a legal person for this reason the result would be valid because this can only happen if the first digit of the date is not a digit, which would be an incorrect RFC.
  4. The date is valid. The date is the 6 characters following the name. In YYMMDD format (last two digits of the year, month 01 to 12 and day 01 to 31). Neither 331403 (3 of the 14th month of a year ending in 33) would be valid. Nor would it be valid 010229 (29th of February of any year ending in 01).
  5. The first homonymy differentiating character is valid.This is the first one following the date. It must be a capital letter from A to V inclusive, or a digit from 1 to 9 inclusive, Ñ and 0 are not valid. This is because in the PROCEDURE FOR OBTAINING THE HOMONY DIFFERENTIATING KEY section of the document in the question there is a step in which a 3-digit number is divided by 34 and a table is consulted. 999/34 = 29 . In that table the 29 is the letter V
  6. The second differentiating character of homonymy is valid. This is the one that follows the previous one. Due to the procedure followed this can be any character from the corresponding table, i.e. from A to Z and from 1 to 9. The Ñ and 0 are not valid. The document describes how the 2 homonym distinguishing characters are calculated, but this is of no interest to us because we only have the RFC and not the name that gave rise to those 2 homonym distinguishing characters.
  7. The check digit must be correct. The check digit is the last digit. It can only be a digit from 0 to 9 or the letter A. And it is calculated based on the other characters of the RFC. This digit acts as an error detector code that allows to detect most of the mistakes made by users when entering an RFC.

Note that by valid we mean an RFC that meets all the rules of the document, i.e., there is a combination of name and date of birth or creation that generates that RFC. Whereas for an invalid RFC there is no name and date that ends up generating that RFC. Just because it is valid does not mean that it exists.

Check digit calculation.

If the RFC has 12 characters we add a blank space at the beginning.

We use all the characters of the RFC except the last one. That is, we always use 12 characters.
Each character corresponds to a value according to the following table:

introducir la descripción de la imagen aquí

The value of the first character is multiplied by 13, the second by 12, the third by 11 and so on until the twelfth character is multiplied by 2.
All these values add up. And with the sum the document describes some unnecessarily complicated operations that are equivalent to :

  • Subtract the sum from 11000. You calculate the modulus 11 of the subtraction.
  • If the result of the modulus is 10 the check digit is A. Otherwise it is the same number you have obtained.

Example for RFC GODE561231GR8

Carácter Valor Multiplicador  Resultado
    G     16  *     13      =    208       
    O     25  *     12      =    300 
    D     13  *     11      =    143
    E     14  *     10      =    140
    5      5  *      9      =     45
    6      6  *      8      =     48
    1      1  *      7      =      7
    2      2  *      6      =     12
    3      3  *      5      =     15
    1      1  *      4      =      4
    G     16  *      3      =     48
    R     28  *      2      =     56
-------------------------------------
                         SUMA : 1026
( 11000 - 1026 ) % 11 = 8 -> El dígito verificador es 8
El RFC es Válido.

Regular Expression

If I were to use a regular expression as a pre-validation step I would use :

[A-ZÑ&]{3,4}\d{6}[A-V1-9][A-Z1-9][0-9A]

This expression accepts incorrect dates such as 999999. Neither day 99 nor month 99 exists.
I don't see any sense in complicating the regex, to reject days starting with 9 for example, since dates not checked by the regex will remain anyway (unless you use a very complicated regex). It is better to leave the lexical analysis for the regex (to see if the characters are valid) and the semantic analysis for other levels (to see if the date is correct). But this is a matter of opinion.

Using Python and a library.

Often the best way to implement something is not to do it and use a ready-made implementation if it is available and reliable. Except for educational purposes or certain very special requirements.

There are several libraries that check an RFC. For example stdnum by Arthur de Jong and others. Available at https://github.com/arthurdejong/python-stdnum under license GNU Lesser General Public License version 2.1 or later.

#!/usr/bin/env python
from stdnum.mx.rfc import (validate,InvalidComponent,InvalidFormat,
InvalidLength,InvalidChecksum)

# Devuelve true si el RFC pasado es valido
# rfc es un string
def esValido(rfc):
  try:
    validate( rfc, validate_check_digits=True)
    return True
  except (InvalidComponent,InvalidFormat,InvalidLength,InvalidChecksum):
    return False

There is little to comment, everything is already done by the library.

Using functional programming. In Scala

The function that performs the check is the only public one and it is also called esValido . Like the Python returns true if the past RFC is valid.
The code includes comments explaining how it works.

object RFCcheck extends  App {
  private val caracteres = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

  // Estos son los carácteres permitidos en las 3 primeras posiciones (personas
  // morales, longitud total RFC es 12) o las 4 primeras posiciones (personas
  // físicas, longitud total RFC es 3)
  private val caracteresPrimeraParte = caracteres + "Ñ&"

  // Cifras permitidas en los 6 carácteres de la fecha
  private val cifras = "0123456789"

  // Carácteres permitidos en el dígito validador
  private val caracteresValidador = cifras + "A"

  // Valores permitidos para los carácteres primero y segundo de la clave
  // diferenciadora de la homonimia
  // Estos valores estan en la tabla del anexo 2
  // Nótese que el primer carácter se obtiene dividiendo un numero de 3 cifras
  // entre 34
  // 999/34 = 29 . Por tanto el máximo carácter en ese caso es 'V'
  private val caracteresHomonimia1 = "123456789ABCDEFGHIJKLMNOPQRSTUV"
  private val caracteresHomonimia2 = caracteresHomonimia1 + "WXYZ"

  // Comprobar que la fecha es valida
  // Por ejemplo, no permitir el 97 de octubre o el mes 17
  // Nótese que se permite el 29 de febrero de los años acabados en 00
  //porque el año 2100 no tendrá ese día pero el 2000 sí lo tuvo
  private val maxDiaMes = -1::31::28::31::30::31::30::31::31::30::31::30::31::
    Nil
  private def fechaValida( s:String ):Boolean = {
    val anyo = s.substring( 0, 2).toInt
    val mes  = s.substring( 2, 4).toInt
    val dia  = s.substring( 4, 6).toInt
    if ( mes<1 || mes>12 ) return false
    if ( dia<1 ) return false
    if ( anyo%4==0 && mes==2 ) return dia<=29
    dia<=maxDiaMes(mes)
  }

  // Carácteres en el orden de la tabla del anexo 3. Su posición es igual al
  // valor que se les asigna en la tabla del Anexo 3
  private val tablaAnexo3 = "0123456789ABCDEFGHIJKLMN&OPQRSTUVWXYZ Ñ"

  // Cálculo del dígito verificador
  private def calculaDigitoVerificador( rfc:String ):Char = {
    // Usar el rfc sin el último carácter que es el verificador
    // Para las personas morales se añade un espacio al principio
    val rfcSinDigitoV = if (rfc.length==13 ) rfc.substring(0,12)
    else " " +rfc.substring(0,11)
    // Para cada carácter multiplicamos su valor por (13 - posicion)
    // Y calculamos la suma de todas esas multiplicaciones
    val suma = (0 until 12 zip rfcSinDigitoV) .
      foldLeft (0) ( (acu,p) => acu + tablaAnexo3.indexOf(p._2) * (13-p._1) )
    // Y calculamos el dígito verificador (11000-suma) módulo 11.
    // caracteresValidador tiene los carácteres en el orden que
    // necesitamos del 0 al 10 (el décimo es la A)
    caracteresValidador( (11000-suma) % 11)
  }

  // Palabras no permitidas según el anexo 4
  private val palabrasInconvenientes = "BUEI"::"BUEY"::"CACA"::"CACO"::"CAGA"::
    "CAGO"::"CAKA"::"CAKO"::"COGE"::"COJA"::"COJE"::"COJI"::"COJO"::"CULO"::
    "FETO"::"GUEY"::"JOTO"::"KACA"::"KACO"::"KAGA"::"KAGO"::"KOGE"::"COJO"::
    "KAKA"::"KULO"::"MAME"::"MAMO"::"MEAR"::"MEAS"::"MEON"::"MION"::"MOCO"::
    "MULA"::"PEDA"::"PEDO"::"PENE"::"PUTA"::"PUTO"::"QULO"::"RATA"::"RUIN"::
    Nil

  // Calcula si es válido un rfc
  // El RFC debe tener exáctamente 12 carácteres para personas morales
  // Y 13 carácteres para personas físicas
  // No se admiten separadores como espacios o guiones
  def esValido( rfc:String ):Boolean = {
    val nombre = rfc.substring(0, rfc.length - 9) // Primeros 3 o 4 carácteres
    val fecha  = rfc.substring(rfc.length - 9, rfc.length - 3) // 6 carácteres
    val homonimia1 = rfc(rfc.length-3) // 1º char de clave dif de homonimia
    val homonimia2 = rfc(rfc.length-2) // 2º char de clave dif de homonimia
    val digitoVerificador = rfc(rfc.length-1) // Último carácter
    // Un RFC es válido si se cumple todo lo siguiente:
    (rfc.length == 12 || rfc.length == 13) && // 12 o 13 de longitud
      // Solo carácteres permitidos en nombre
      nombre.foldLeft(true)(_ && caracteresPrimeraParte.contains(_)) &&
      // Solo carácteres permitidos en fecha
      fecha. foldLeft(true)(_ && cifras.contains(_)) &&
      // Solo carácteres permitidos en clave diferenciadora de homonimia
      caracteresHomonimia1.contains(homonimia1) &&
      caracteresHomonimia2.contains(homonimia2) &&
      // La fecha es valida
      fechaValida(fecha) &&
      // Nombre no es una palabra inconveniente
      !palabrasInconvenientes.contains(nombre) &&
      // El digito verificador es correcto
      digitoVerificador == calculaDigitoVerificador(rfc)
  }
}

Remarks

In the document Algorithm to generate the RFC with homoclave for individuals and companies.odt

0 votes

@Mariano Those RFCs are not valid according to the question document. That those webs validate them means that those webs are using a different RFC specification document than the one in the question. This is evident by testing the example document, GODE561231GR8, which is given as invalid on the first web. Either that, or the question document is wrong.

3voto

Orlando Alfonso Points 21

Entering the SAT website https://portalsat.plataforma.sat.gob.mx/ConsultaRFC/ I was able to get the regular expression and the function that they use, I hope it helps:

// patron del RFC, persona moral
_rfc_pattern_pm = "^(([A-ZÑ&]{3})([0-9]{2})([0][13578]|[1][02])(([0][1-9]|[12][\\d])|[3][01])([A-Z0-9]{3}))|" +
                  "(([A-ZÑ&]{3})([0-9]{2})([0][13456789]|[1][012])(([0][1-9]|[12][\\d])|[3][0])([A-Z0-9]{3}))|" +
                  "(([A-ZÑ&]{3})([02468][048]|[13579][26])[0][2]([0][1-9]|[12][\\d])([A-Z0-9]{3}))|" +
                  "(([A-ZÑ&]{3})([0-9]{2})[0][2]([0][1-9]|[1][0-9]|[2][0-8])([A-Z0-9]{3}))$";
 // patron del RFC, persona fisica
 _rfc_pattern_pf = "^(([A-ZÑ&]{4})([0-9]{2})([0][13578]|[1][02])(([0][1-9]|[12][\\d])|[3][01])([A-Z0-9]{3}))|" +
                       "(([A-ZÑ&]{4})([0-9]{2})([0][13456789]|[1][012])(([0][1-9]|[12][\\d])|[3][0])([A-Z0-9]{3}))|" +
                       "(([A-ZÑ&]{4})([02468][048]|[13579][26])[0][2]([0][1-9]|[12][\\d])([A-Z0-9]{3}))|" +
                       "(([A-ZÑ&]{4})([0-9]{2})[0][2]([0][1-9]|[1][0-9]|[2][0-8])([A-Z0-9]{3}))$";

function ValidaRFC(){
    var rfc = document.getElementById("ConsultaForm:rfc").value;
    if (rfc.match(_rfc_pattern_pm) || rfc.match(_rfc_pattern_pf)){
            alert("La estructura de la clave de RFC es valida");
            return true;
        }else {
            alert("La estructura de la clave de RFC es incorrecta.");
            return false;
        }
}

0 votes

Stack snippet should only be used for executable HTML/CSS/JavaScript code. Point and aside from the above, it's interesting to know that the code is so handy, but your answer would be more useful if you explained how it works.

1voto

Free API

API open source always free with a response time of 600 ms and in 2 steps to verify the rfc, to know if it is in the black list of the SAT and in LRFC: Documentation .

Regular expression

The following regular expression (in the code) verifies:

  • Individually to the legal entity and to the individual.
  • If it accepts XAXX01010101000 and XEXX0101010101000
  • If it accepts AAAA010101010A8, AAAA0101010101AZ3 and MOCO0101010101AA9, but the SAT in its system searches in its database and returns "RFC not registered in the taxpayer registry". That is to say, they are not in LRFC.

Following the logic of SAT SAT 2 for the answer Orlando Alfonso. Using Mariano's example code.

//Función para validar un RFC
// Devuelve el RFC sin espacios ni guiones si es correcto
// Devuelve false si es inválido
// (debe estar en mayúsculas, guiones y espacios intermedios opcionales)
function rfcValido(rfc, aceptarGenerico = true) {
     _rfc_pattern_pm = "^(([A-ZÑ&]{3})([0-9]{2})([0][13578]|[1][02])(([0][1-9]|[12][\\d])|[3][01])([A-Z0-9]{3}))|" +
              "(([A-ZÑ&]{3})([0-9]{2})([0][13456789]|[1][012])(([0][1-9]|[12][\\d])|[3][0])([A-Z0-9]{3}))|" +
              "(([A-ZÑ&]{3})([02468][048]|[13579][26])[0][2]([0][1-9]|[12][\\d])([A-Z0-9]{3}))|" +
              "(([A-ZÑ&]{3})([0-9]{2})[0][2]([0][1-9]|[1][0-9]|[2][0-8])([A-Z0-9]{3}))$";
 _rfc_pattern_pf = "^(([A-ZÑ&]{4})([0-9]{2})([0][13578]|[1][02])(([0][1-9]|[12][\\d])|[3][01])([A-Z0-9]{3}))|" +
                   "(([A-ZÑ&]{4})([0-9]{2})([0][13456789]|[1][012])(([0][1-9]|[12][\\d])|[3][0])([A-Z0-9]{3}))|" +
                   "(([A-ZÑ&]{4})([02468][048]|[13579][26])[0][2]([0][1-9]|[12][\\d])([A-Z0-9]{3}))|" +
                   "(([A-ZÑ&]{4})([0-9]{2})[0][2]([0][1-9]|[1][0-9]|[2][0-8])([A-Z0-9]{3}))$";
   return rfc.match(_rfc_pattern_pm) || rfc.match(_rfc_pattern_pf);
}

//Handler para el evento cuando cambia el input
// -Lleva la RFC a mayúsculas para validarlo
// -Elimina los espacios que pueda tener antes o después
function validarInput(input) {
    var rfc         = input.value.trim().toUpperCase(),
        resultado   = document.getElementById("resultado"),
        valido;

    var rfcCorrecto = rfcValido(rfc);   // ⬅️ Acá se comprueba

    if (rfcCorrecto) {
        valido = "Válido";
      resultado.classList.add("ok");
    } else {
        valido = "No válido"
        resultado.classList.remove("ok");
    }

    resultado.innerText = "RFC: " + rfc
                        + "\nFormato: " + valido;
}

#resultado {
    background-color: red;
    color: white;
    font-weight: bold;
}
#resultado.ok {
    background-color: green;
}

<label>RFC:</label>
<input type="text" id="rfc_input" style="width:100%;"
       oninput="validarInput(this)" 
       placeholder="Ingrese su RFC">
<pre id="resultado"></pre>

It works in other languages. Here is an example in go.

func ensureRFC(rfc string) bool {
    naturalPerson, _ := regexp.MatchString("^(([A-ZÑ&]{4})([0-9]{2})([0][13578]|[1][02])(([0][1-9]|[12][\\d])|[3][01])([A-Z0-9]{3}))|(([A-ZÑ&]{4})([0-9]{2})([0][13456789]|[1][012])(([0][1-9]|[12][\\d])|[3][0])([A-Z0-9]{3}))|(([A-ZÑ&]{4})([02468][048]|[13579][26])[0][2]([0][1-9]|[12][\\d])([A-Z0-9]{3}))|(([A-ZÑ&]{4})([0-9]{2})[0][2]([0][1-9]|[1][0-9]|[2][0-8])([A-Z0-9]{3}))$", 
    rfc)
    legalPerson, _ := regexp.MatchString("^(([A-ZÑ&]{3})([0-9]{2})([0][13578]|[1][02])(([0][1-9]|[12][\\d])|[3][01])([A-Z0-9]{3}))|(([A-ZÑ&]{3})([0-9]{2})([0][13456789]|[1][012])(([0][1-9]|[12][\\d])|[3][0])([A-Z0-9]{3}))|(([A-ZÑ&]{3})([02468][048]|[13579][26])[0][2]([0][1-9]|[12][\\d])([A-Z0-9]{3}))|(([A-ZÑ&]{3})([0-9]{2})[0][2]([0][1-9]|[1][0-9]|[2][0-8])([A-Z0-9]{3}))$", 
    rfc)
    return !naturalPerson && !legalPerson
}

0voto

I currently use this regular expression, it validates the following:

  • 10 Digits (without homoclave)
  • 12 Digits (moral)
  • 13 Digits

    /^[a-zA-Z]{3,4}(\d{6})((\D|\d){2,3})?$/

    function validaRFC(){ let pattern = /^[a-zA-Z]{3,4}(\d{6})((\D|\d){2,3})?$/; let rfc = document.getElementById("rfc").value; document.getElementById("estatus").innerHTML = pattern.test(rfc); }

    <input id="rfc" type="text" onkeyup="validaRFC()"/> <label id="estatus"></label>

HolaDevs.com

HolaDevs is an online community of programmers and software lovers.
You can check other people responses or create a new question if you don't find a solution

Powered by:

X