Perl module to test for correct cpf numbers
use Business::BR::CPF; print "ok " if test_cpf('390.533.447-05'); # prints 'ok ' print "bad " unless test_cpf('231.002.999-00'); # prints 'bad '
The \s-1CPF\s0 number is an identification number of Brazilian citizens emitted by the Brazilian Ministry of Revenue, which is called \*(L"Ministe\*'rio da Fazenda\*(R".
\s-1CPF\s0 stands for \*(L"Cadastro de Pessoa Fi\*'sica\*(R" (literally, physical person registration) as opposed to the \s-1CNPJ\s0 number for companies.
The \s-1CPF\s0 is comprised of a base of 9 digits and 2 check digits. It is usually written like '231.002.999-00' so as to be more human-readable.
This module provides \*(C`test_cpf\*(C' for checking that a \s-1CPF\s0 number is correct. Here a correct \s-1CPF\s0 number means
it is 11 digits long
it satisfies the two check equations mentioned below
Before checking, any non-digit letter is stripped, making it easy to test formatted entries like '231.002.999-00' and entries with extra blanks like ' 999.221.222-00 '.
test_cpf('999.444.333-55') # incorrect CPF, returns 0 test_cpf(' 263.946.533-30 ') # is ok, returns 1 test_cpf('888') # nope, returns undef Tests whether a \s-1CPF\s0 number is correct. Before testing, any non-digit character is stripped. Then it is expected to be 11 digits long and to satisfy two check equations which validate the last two check digits. See \*(L"\s-1THE\s0 \s-1CHECK\s0 \s-1EQUATIONS\s0\*(R". The policy to get rid of '.' and '-' is very liberal. It indeeds discards anything that is not a digit (0, 1, ..., 9) or letter. That is handy for discarding spaces as well test_cpf(' 263.946.533-30 ') # is ok, returns 1 But extraneous inputs like '#333%444*2.3+2-00' are also accepted. If you are worried about this kind of input, just check against a regex: warn "bad CPF: only digits (11) expected" unless ($cpf =~ /^\d{11}$/);
warn "bad CPF: does not match mask '_\|_\|_._\|_\|_._\|_\|_-_\|_'" unless ($cpf =~ /^\d{3}\.\d{3}\.\d{3}-\d{2}$/); \s-1NOTE\s0. Integer numbers like 9999811299 (or 99_998_112_99) with fewer than 11 digits will be normalized (eg. to \*(L"09999811299\*(R") before testing.
canon_cpf(99); # returns '00000000099' canon_cpf('999.999.999-99'); # returns '99999999999' Brings a candidate for a \s-1CPF\s0 number to a canonical form. In case, the argument is an integer, it is formatted to at least eleven digits. Otherwise, it is stripped of any non-alphanumeric characters and returned as it is.
format_cpf('00000000000'); # returns '000.000.000-00' Formats its input into '000.000.000-00' mask. First, the argument is canon'ed and then dots and hyphen are added to the first 11 digits of the result.
($base, $dv) = parse_cpf($cpf); $hashref = parse_cpf('999.222.111-00'); # { base => '999222111', dv => '00' } Splits a candidate for \s-1CPF\s0 number into base and check digits (dv - di\*'gitos de verificac\*,a\*~o). It canon's the argument before splitting it into 9- and 2-digits parts. In a list context, returns a two-element list with the base and the check digits. In a scalar context, returns a hash ref with keys 'base' and 'dv' and associated values.
$rand_cpf = random_cpf($valid);
$correct_cpf = random_cpf(); $cpf = random_cpf(1); # also a correct CPF $bad_cpf = random_cpf(0); # an incorrect CPF Generates a random \s-1CPF\s0. If $valid is omitted or 1, it is guaranteed to be correct. If $valid is 0, it is guaranteed to be incorrect. This function is intented for mass test. (Use it wisely.) The implementation is simple: just generate a 9-digits random number, hopefully with a uniform distribution and then compute the check digits. If $valid==0, the check digits are computed not to satisfy the check equations.
\*(C`test_cpf\*(C' is exported by default. \*(C`canon_cpf\*(C', \*(C`format_cpf\*(C', \*(C`parse_cpf\*(C' and \*(C`random_cpf\*(C' can be exported on demand.
A correct \s-1CPF\s0 number has two check digits which are computed from the base 9 first digits. Consider the \s-1CPF\s0 number written as 11 digits
c[1] c[2] c[3] c[4] c[5] c[6] c[7] c[8] c[9] dv[1] dv[2]
To check whether a \s-1CPF\s0 is correct or not, it has to satisfy the check equations:
c[1]*10+c[2]*9+c[3]*8+c[4]*7+c[5]*6+ c[6]*5+c[7]*4+c[8]*3+c[9]*2+dv[1] = 0 (mod 11) or = 1 (mod 11) (if dv[1]=0)
and
c[2]*10+c[3]*9+c[4]*8+c[5]*7+c[6]*6+ c[7]*5+c[8]*4+c[9]*3+dv[1]*2+dv[2] = 0 (mod 11) or = 1 (mod 11) (if dv[2]=0)
I heard that there are exceptions of \s-1CPF\s0 numbers which don't obey the check equations and are still authentic. I have never found one of them.
To make sure this module works, one can try the results obtained against those found with \*(L"Comprovante de Inscric\*,a\*~o e de Situac\*,a\*~o Cadastral no \s-1CPF\s0\*(R", a web page which the Brazilian Ministry of Revenue provides for public consultation on regularity status of the taxpayer. This page tells if the \s-1CPF\s0 number is a correct entry (11-digits-long with verified check digits), if it references a real person and if he/she is regular with the government body.
Given a bad \s-1CPF\s0, the after-submit page tells \*(L"\s-1CPF\s0 incorreto\*(R". If the \s-1CPF\s0 is a good one but does not reference a real person, it says \*(L"\s-1CPF\s0 na\*~o existe em nossa base de dados\*(R" (\s-1CPF\s0 does not exist in our database). Otherwise, it shows a details form for the identified taxpayer.
Note that this module only tests correctness. It doesn't enter the merit whether the \s-1CPF\s0 number actually exists at the Brazilian government databases.
As you might have guessed, this is not the first Perl module to approach this kind of functionality. Take a look at
http://search.cpan.org/search?module=Brasil::Checar::CPF http://search.cpan.org/search?query=cpf&mode=all
Please reports bugs via \s-1CPAN\s0 \s-1RT\s0, http://rt.cpan.org/NoAuth/Bugs.html?Dist=Business-BR-Ids By doing so, the author will receive your reports and patches, as well as the problem and solutions will be documented.
A. R. Ferreira, <[email protected]>
Copyright (C) 2005 by A. R. Ferreira
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.6 or, at your option, any later version of Perl 5 you may have available.