logo
Free, unlimited AI code reviews that run on commit
git-lrc git-lrc GitHub Install Now We'd appreciate a star git-lrc - Free, unlimited AI code reviews that run on commit | Product Hunt git-lrc - Free, unlimited AI code reviews that run on commit | Product Hunt

Business::BR::CNPJ - Perl module to test for correct CNPJ numbers

Author

       A. R. Ferreira, <ferreira@cpan.org>

Bugs

       I heard that there are exceptions of CNPJ numbers which don't obey the  check  equations  and  are  still
       authentic. I have never found one of them.

Description

       The CNPJ number is an identification number of Brazilian companies emitted by the Brazilian Ministry of
       Revenue, which is called "Ministério da Fazenda".

       CNPJ stands for "Cadastro Nacional de Pessoa Jurídica" (literally, national juridical person
       registration) as opposed to the CPF number for natural persons. Sometime ago, it was called CGC
       ("Cadastro Geral de Contribuinte" or general taxpayer registration).

       The CNPJ is comprised of a base of 8 digits, a 4-digits radical and 2 check digits. It is usually written
       like '11.111.111/0001-55' so as to be more human-readable.

       This module provides "test_cnpj" for checking that a CNPJ number is correct. Here a correctCNPJnumber
       means

       •   it is 14 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
       '11.111.111/0001-55' and entries with extra blanks like '   43.337.004 / 0001-72  '.

       test_cnpj
             test_cnpj('48.999.764/0001-60') # incorrect CPF, returns 0
             test_cnpj(' 43.337.004/0001-72 ') # is ok, returns 1
             test_cnpj('888') # nope, returns undef

           Tests whether a CNPJ number is correct. Before testing, any non-digit character is stripped. Then  it
           is expected to be 14 digits long and to satisfy two check equations which validate the last two check
           digits.  See "THE CHECK EQUATIONS".

           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_cnpj(' 66.818.021/0001-27 ') # is ok, returns 1

           But extraneous inputs like 'a53##045%4-20**0001!50' are also accepted. If you are worried about  this
           kind of input, just check against a regex:

             warn "bad CNPJ: only digits (14) expected"
               unless ($cnpj =~ /^\d{14}$/);

             warn "bad CNPJ: does not match mask '__.___.___/____-__'"
               unless ($cnpj =~ /^\d{2}\.\d{3}\.\d{3}/\d{4}-\d{2}$/);

           NOTE.  Integer  numbers  like  3337004000158 (or 3_337_004_0001_58) with fewer than 14 digits will be
           normalized (eg. to 03_337_004_0001_58) before testing.

       canon_cnpjcanon_cnpj(1); # returns '00000000000001'
             canon_cnpj('99.999.222/0001-12'); # returns '99999222000112'

           Canon's a candidate for a CNPJ number. In case, the argument is an integer, it  is  formatted  to  at
           least  fourteen  digits. Otherwise, it is stripped of any non-alphanumeric characters and returned as
           it is.

       format_cnpj
             format_cnpj('00 000 000 0000 00'); # returns '00.000.000/0000-00'

           Formats its input into '00.000.000/0000-00' mask.  First, the argument is  canon'ed  and  then  dots,
           slash and hyphen are added to the first 14 digits of the result.

       parse_cnpj
             ($base, $filial, $dv) = parse_cnpj($cpf);
             $hashref = parse_cnpj('11.222.333/4444-00'); # { base => '11222333', filial => '4444' dv => '00' }

           Splits a candidate for CNPJ number into base, radical and check digits (dv - dígitos de verificação).
           It  canon's  the  argument  before  splitting  it  into 8-, 4- and 2-digits parts. In a list context,
           returns a three-element list with the base, the radical and the check digits. In  a  scalar  context,
           returns a hash ref with keys 'base', 'filial' and 'dv' and associated values.

       random_cnpj
             $rand_cnpj = random_cnpj($valid);

             $good_cnpj = random_cnpj();
             $cnpj = random_cnpj(1); # also a good one
             $bad_cnpj = random_cnpj(0); # bad CNPJ

           Generates  a  random CNPJ. 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: generate a 8-digits random number for the base, and the  variation  is  chosen
           95%  of  the  time  to  be  '0001'  and the other 5% a skewed random distribution with the expression
           "int(sqr rand(1E8))" is used. A uniform distribution is expected  from  "rand".  With  the  base  and
           variation, the check digits are computed.  If $valid==0, the check digits are computed notto satisfy
           the check equations.

   EXPORT
       "test_cnpj"  is  exported  by default. "canon_cnpj", "format_cnpj", "parse_cnpj" and "random_cnpj" can be
       exported on demand.

Name

       Business::BR::CNPJ - Perl module to test for correct CNPJ numbers

Pod Errors

       Hey! Theabovedocumenthadsomecodingerrors,whichareexplainedbelow:

       Around line 112:
           Non-ASCII character seen before =encoding in '"Ministério'. Assuming CP1252

perl v5.36.0                                       2022-10-13                            Business::BR::CNPJ(3pm)

See Also

       To  make  sure  this module works, one can try the results obtained against those found with  "Emissão de
       Comprovante de Inscrição e de Situação Cadastral de Pessoa Jurídica", a  web  page  which  the  Brazilian
       Ministry  of  Revenue  provides  for public consultation on regularity status of the taxpayer.  This page
       tells if the CNPJ number is a correct entry (14-digits-long with verified check digits), if it references
       a real company and if it is regular with the government body.

       Given a bad CNPJ, the after-submit page tells "O número do CNPJ não é válido" (the  CNPJ  number  is  not
       valid).   If  the  CNPJ  is a good one but does not reference a real company, it says "CNPJ não existe em
       nossa base de dados" (CNPJ 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 CNPJ 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::CGC

       Please reports bugs via CPAN RT, 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.

Synopsis

         use Business::BR::CNPJ;

         print "ok " if test_cnpj('90.117.749/7654-80'); # prints 'ok '
         print "bad " unless test_cnpj('88.222.111/0001-10'); # prints 'bad '

The Check Equations

       A correct CNPJ number has two check digits which are computed from the 12 first digits. Consider the CNPJ
       number written as 14 digits

         c[1] c[2] c[3] c[4] c[5] c[6] c[7] c[8] c[9] c[10] c[11] c[12] dv[1] dv[2]

       To check whether a CNPJ is correct or not, it has to satisfy the check equations:

         5*c[1]+4*c[2]+3*c[3]+2*c[4]+9*c[5]+
         8*c[6]+7*c[7]+6*c[8]+5*c[9]+4*c[10]+
                             3*c[11]+2*c[12]+dv[1] = 0 (mod 11) or
                                                   = 1 (mod 11) (if dv[1]=0)

       and

         6*c[1]+5*c[2]+4*c[3]+3*c[4]+2*c[5]+
         9*c[6]+8*c[7]+7*c[8]+6*c[9]+5*c[10]+
                     4*c[11]+3*c[12]+2*dv[1]+dv[2] = 0 (mod 11) or
                                                   = 1 (mod 11) (if dv[2]=0)

See Also