CNPJ生成器和验证器 - 巴西企业身份识别工具
CNPJ生成器和验证器用于生成或校验巴西的国家法人登记簿号码(CNPJ),这是巴西企业的法定税务识别码。工具依照巴西联邦税务局(Receita Federal)公布的官方校验位计算公式,生成格式正确、数学上有效的测试用CNPJ号码,也可以验证一个现有号码的校验位是否正确,主要供开发者测试企业注册表单和财务系统。
巴西企业注册号生成器和验证器
CNPJ生成器
生成用于测试目的的有效巴西企业注册号。
CNPJ验证器
检查巴西企业注册号是否有效。
文档
了解巴西 CNPJ 号码
**CNPJ(Cadastro Nacional da Pessoa Jurídica)**是巴西的企业税务识别号,是一个14位数字,用于识别该国的每个法律商业实体。如果您正在构建处理巴西商业数据的软件,您很快就会在注册表单、发票和 API 集成中遇到这些数字。
这个工具的实用之处在于:它生成在数学上有效的 CNPJ 用于测试,而不使用真实的公司标识符。当您正在设置包含 1,000 条记录的测试数据库,或者在凌晨 2 点调试验证程序时,您需要通过算法检查但不会意外匹配实际企业的 CNPJ。这正是该工具生成的内容。
这里创建的数字遵循巴西联邦税务局(Receita Federal)的官方验证算法。它们具有正确的校验位和适当的格式——只是未在政府数据库中注册。可以将它们视为语法正确的测试数据,不会在您的开发环境中造成合规性问题。
什么是 CNPJ 及其重要性
CNPJ 是巴西的企业标识符,类似于美国的 EIN 或英国的公司注册号。每个在巴西合法经营的企业实体都必须拥有一个,由联邦税务局(Receita Federal)颁发。
在以下情况下,你会遇到 CNPJ:
- 处理支付:巴西支付网关要求对商户账户进行 CNPJ 验证
- 税务合规:巴西发出的每张发票都必须包含有效的 CNPJ
- 企业注册:政府机构使用 CNPJ 在系统间跟踪法人实体
- 银行业务:开设公司账户或处理国际转账
- 进出口:海关文件需要验证 CNPJ
- 政府合同:公共招标系统在接受投标前验证 CNPJ
根据我在巴西电子商务平台工作的经验,最常见的集成点之一是结账流程,用户在此输入其 CNPJ 进行企业购买。你的验证逻辑需要在支付处理器之前捕捉格式错误,否则你会看到本可以避免的交易失败。
CNPJ结构和格式
CNPJ由14位数字组成,格式为:XX.XXX.XXX/YYYY-ZZ
分解结构:
- 前8位数字(XX.XXX.XXX):唯一分配给公司的基本注册号码
- 接下来的4位数字(/YYYY):分支或机构标识符—
/0001表示总部,而/0002、/0003代表分支机构 - 最后2位数字(-ZZ):通过加权算法计算的校验数字
示例:12.345.678/0001-95
关于分支标识符的有趣之处:当一家公司开设多个地点时,每个地点都使用相同的前8位数字,但分支号码不同。因此,如果一家零售连锁店有50家门店,它们的CNPJ将以/0001到/0050结尾,但共享相同的基本号码。这使得可以轻松识别多个CNPJ属于同一母公司。
校验数字并非随机—它们使用特定权重序列的模数-11算法计算。这种设计选择,在巴西行政文件中很常见,使得伪造有效数字或通过输入错误意外创建有效数字在数学上变得困难。
CNPJ验证的实际工作原理
验证算法使用加权模数-11计算。以下是其背后的逻辑:
第一个校验位计算
- 取前12位数字,并按权重乘以:
5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2 - 求所有乘积的和
- 将和除以11并取余数
- 如果余数 < 2,校验位为0;否则为
11 - 余数
第二个校验位计算
- 取前13位数字(包括第一个校验位)并按权重乘以:
6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2 - 求所有乘积的和
- 除以11并取余数
- 如果余数 < 2,校验位为0;否则为
11 - 余数
为什么这种方法有效: 加权乘法系统在所有12个基础数字和最终校验位之间创建了唯一的关系。即使更改基础数字中的单个数字,也会产生不同的校验位,从而捕捉常见的转录错误,如交换两个数字(输入12.345而不是12.354)。
实际注意事项:所有数字相同的CNPJ(如11.111.111/1111-11)即使通过数学检查也会自动无效。巴西税务局明确排除了这些模式,以防止简单的情况。
如何使用CNPJ生成器和验证器
生成测试CNPJ
需要一个用于测试数据库的有效CNPJ?操作如下:
- 点击 "生成CNPJ"
- 工具立即创建一个数学上有效的号码
- 点击 "复制" 将其复制到剪贴板
- 将其粘贴到测试表单、数据库种子或单元测试中
每个生成的CNPJ都通过所有算法验证检查,但未在联邦税务局注册。这意味着您可以在开发中自由使用它们,无需担心意外使用真实公司的标识符。
验证CNPJ号码
有需要验证的CNPJ?验证器可以处理:
- 将CNPJ粘贴或输入到输入框中
- 不用担心格式—它可以处理
12345678000195或12.345.678/0001-95 - 点击 "验证"
- 立即获取检查位是否正确的反馈
验证器检查的内容:正确的长度(14位数字)、正确的检查位计算,以及排除无效模式(如全相同数字)。它不检查的内容:CNPJ是否在政府数据库中注册—这需要直接查询联邦税务局。
CNPJ生成器和验证器的实际应用场景
软件开发和测试
数据库填充:在搭建具有真实测试数据的暂存环境时,您需要数十甚至数百个有效的CNPJ。手动创建这些数据既乏味,使用真实公司标识符还会引起隐私问题。生成的CNPJ可以解决这两个问题。
单元测试边界情况:您的验证功能应拒绝00.000.000/0000-00,但接受11.222.333/0001-81。拥有生成器可以快速创建有效和故意无效的测试用例,以验证您的逻辑是否正确处理边界条件。
QA回归测试:在测试注册表单或B2B结账流程时,QA团队需要每次运行都有新的测试数据。我见过的常见问题是:测试环境被反复使用的5-6个相同CNPJ污染,这会掩盖只在特定数字模式下出现的错误。
API集成测试:如果您正在与巴西支付处理商(如PagSeguro或Mercado Pago)集成,他们的沙盒环境通常需要有效的CNPJ格式。即使不是针对生产数据库,数学计算也必须正确。
数据处理和验证
清理导入数据:您收到了一个包含10,000条巴西公司记录的CSV。在处理之前,您需要识别哪些CNPJ是格式错误的。通过验证器运行这些数据可以标记出有拼写错误、截断或不正确校验位的条目,从而节省大量后续调试时间。
客户端表单验证:在表单提交前捕获无效的CNPJ可以改善用户体验。没有人希望填写一个20个字段的注册表,最后因为在CNPJ中颠倒了两个数字而在提交时出错。
数据匿名化分析:在准备与分析团队或外部合作伙伴共享生产数据时,您需要用有效但虚构的CNPJ替换真实的CNPJ。这在保持数据集引用完整性的同时,保护了实际业务身份。
国际商业运营
了解巴西要求:如果您正在拓展巴西市场,您将在合同、发票和运输文档中遇到CNPJ要求。拥有一个可以试验格式的工具,有助于您了解系统需要处理的内容。
第三方集成规范:在审查巴西SaaS提供商的API文档时,您经常会在有效负载示例中看到CNPJ字段。能够生成有效的测试值可以帮助您更快地原型化集成。
替代的 CNPJ 验证方法
编程库
如果您需要在应用程序逻辑中内置 CNPJ 验证,这些库实现了校验位算法:
- JavaScript/Node.js:
cpf-cnpj-validator(每周 130k+ 下载),validator.js(支持巴西文件) - Python:
validate-docbr(验证 CPF、CNPJ 和其他巴西文件),python-cnpj - PHP:
respect/validation(包括 CNPJ 规则),brazilianutils - Java:
caelum-stella(全面的巴西文件验证) - Ruby:
cpf_cnpjgem
这些库通常处理多种巴西文件类型(CPF、CNPJ 等)的格式化、解析和验证。
官方验证 API
对于需要验证实际业务注册的生产系统:
- 巴西国家税务局公共服务:Consulta CNPJ API 允许针对官方数据库进行验证(需要适当的授权和速率限制)
- 第三方数据提供商:如 Serasa Experian 和 Boa Vista SCPC 等服务提供商业 API,可返回公司详细信息、注册状态和信用信息
注意:这些服务检查实际注册,而不仅仅是数学有效性。您需要适当的授权,并且应该预期生产使用的 API 成本。
何时使用每种方法
使用此浏览器工具时: 您需要快速验证,无需安装依赖项,为演示生成测试数据,或了解 CNPJ 验证的工作原理。
使用库时: 您正在构建一个需要作为表单处理一部分进行客户端或服务器端验证的应用程序。
使用官方 API 时: 您需要验证 CNPJ 是否对应于真实、活跃的企业实体,并具有当前的注册状态。
技术实现细节
该工具完全在浏览器中使用JavaScript运行——没有服务器请求,数据不会离开您的机器。以下是算法的工作原理,您可以为自己的项目改编这些代码:
CNPJ生成算法
1function generateCNPJ() {
2 // 随机生成前12位数字
3 const digits = Array.from({ length: 12 }, () => Math.floor(Math.random() * 10));
4
5 // 计算第一个校验位
6 const firstCheckDigit = calculateCheckDigit(digits);
7 digits.push(firstCheckDigit);
8
9 // 计算第二个校验位
10 const secondCheckDigit = calculateCheckDigit(digits);
11 digits.push(secondCheckDigit);
12
13 // 格式化CNPJ
14 return formatCNPJ(digits.join(''));
15}
16
17function calculateCheckDigit(digits) {
18 const weights = digits.length < 13
19 ? [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]
20 : [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
21
22 const sum = digits.reduce((acc, digit, index) => {
23 return acc + digit * weights[index];
24 }, 0);
25
26 const remainder = sum % 11;
27 return remainder < 2 ? 0 : 11 - remainder;
28}
29CNPJ验证算法
1function validateCNPJ(cnpj) {
2 // 删除非数字字符
3 const cleanCNPJ = cnpj.replace(/\D/g, '');
4
5 // 检查长度是否正确
6 if (cleanCNPJ.length !== 14) return false;
7
8 // 检查已知的无效模式(所有数字相同)
9 if (/^(\d)\1+$/.test(cleanCNPJ)) return false;
10
11 // 转换为数字数组
12 const digits = cleanCNPJ.split('').map(Number);
13
14 // 检查第一个校验位
15 const expectedFirstDigit = calculateCheckDigit(digits.slice(0, 12));
16 if (digits[12] !== expectedFirstDigit) return false;
17
18 // 检查第二个校验位
19 const expectedSecondDigit = calculateCheckDigit(digits.slice(0, 13));
20 if (digits[13] !== expectedSecondDigit) return false;
21
22 return true;
23}
24CNPJ格式化函数
1function formatCNPJ(cnpj) {
2 // 删除非数字字符
3 const cleanCNPJ = cnpj.replace(/\D/g, '');
4
5 // 根据长度格式化
6 if (cleanCNPJ.length <= 2) {
7 return cleanCNPJ;
8 } else if (cleanCNPJ.length <= 5) {
9 return `${cleanCNPJ.slice(0, 2)}.${cleanCNPJ.slice(2)}`;
10 } else if (cleanCNPJ.length <= 8) {
11 return `${cleanCNPJ.slice(0, 2)}.${cleanCNPJ.slice(2, 5)}.${cleanCNPJ.slice(5)}`;
12 } else if (cleanCNPJ.length <= 12) {
13 return `${cleanCNPJ.slice(0, 2)}.${cleanCNPJ.slice(2, 5)}.${cleanCNPJ.slice(5, 8)}/${cleanCNPJ.slice(8)}`;
14 } else {
15 return `${cleanCNPJ.slice(0, 2)}.${cleanCNPJ.slice(2, 5)}.${cleanCNPJ.slice(5, 8)}/${cleanCNPJ.slice(8, 12)}-${cleanCNPJ.slice(12, 14)}`;
16 }
17}
18这些核心函数可以在其他编程语言中按照相同的逻辑实现。以下是Python和Java的示例:
Python实现
1import random
2
3def calculate_check_digit(digits):
4 weights = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2] if len(digits) < 13 else [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]
5
6 total = 0
7 for i in range(len(digits)):
8 total += digits[i] * weights[i]
9
10 remainder = total % 11
11 return 0 if remainder < 2 else 11 - remainder
12
13def generate_cnpj():
14 # 随机生成前12位数字
15 digits = [random.randint(0, 9) for _ in range(12)]
16
17 # 计算第一个校验位
18 first_check = calculate_check_digit(digits)
19 digits.append(first_check)
20
21 # 计算第二个校验位
22 second_check = calculate_check_digit(digits)
23 digits.append(second_check)
24
25 # 格式化CNPJ
26 cnpj = ''.join(map(str, digits))
27 return f"{cnpj[:2]}.{cnpj[2:5]}.{cnpj[5:8]}/{cnpj[8:12]}-{cnpj[12:]}"
28
29def validate_cnpj(cnpj):
30 # 删除非数字字符
31 cnpj = ''.join(filter(str.isdigit, cnpj))
32
33 # 检查长度
34 if len(cnpj) != 14:
35 return False
36
37 # 检查是否所有数字都相同
38 if len(set(cnpj)) == 1:
39 return False
40
41 # 转换为整数列表
42 digits = [int(d) for d in cnpj]
43
44 # 验证第一个校验位
45 first_check = calculate_check_digit(digits[:12])
46 if digits[12] != first_check:
47 return False
48
49 # 验证第二个校验位
50 second_check = calculate_check_digit(digits[:13])
51 if digits[13] != second_check:
52 return False
53
54 return True
55Java实现
1import java.util.Random;
2
3public class CNPJUtils {
4
5 public static String generateCNPJ() {
6 Random random = new Random();
7 int[] digits = new int[14];
8
9 // 随机生成前12位数字
10 for (int i = 0; i < 12; i++) {
11 digits[i] = random.nextInt(10);
12 }
13
14 // 计算第一个校验位
15 digits[12] = calculateCheckDigit(digits, 12);
16
17 // 计算第二个校验位
18 digits[13] = calculateCheckDigit(digits, 13);
19
20 // 格式化CNPJ
21 return String.format("%02d.%03d.%03d/%04d-%02d",
22 digits[0] * 10 + digits[1],
23 digits[2] * 100 + digits[3] * 10 + digits[4],
24 digits[5] * 100 + digits[6] * 10 + digits[7],
25 digits[8] * 1000 + digits[9] * 100 + digits[10] * 10 + digits[11],
26 digits[12] * 10 + digits[13]);
27 }
28
29 private static int calculateCheckDigit(int[] digits, int length) {
30 int[] weights = length < 13
31 ? new int[]{5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2}
32 : new int[]{6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2};
33
34 int sum = 0;
35 for (int i = 0; i < length; i++) {
36 sum += digits[i] * weights[i];
37 }
38
39 int remainder = sum % 11;
40 return remainder < 2 ? 0 : 11 - remainder;
41 }
42
43 public static boolean validateCNPJ(String cnpj) {
44 // 删除非数字字符
45 cnpj = cnpj.replaceAll("\\D", "");
46
47 // 检查长度
48 if (cnpj.length() != 14) {
49 return false;
50 }
51
52 // 检查是否所有数字都相同
53 boolean allDigitsSame = true;
54 for (int i = 1; i < cnpj.length(); i++) {
55 if (cnpj.charAt(i) != cnpj.charAt(0)) {
56 allDigitsSame = false;
57 break;
58 }
59 }
60 if (allDigitsSame) {
61 return false;
62 }
63
64 // 转换为整数数组
65 int[] digits = new int[14];
66 for (int i = 0; i < 14; i++) {
67 digits[i] = Character.getNumericValue(cnpj.charAt(i));
68 }
69
70 // 验证第一个校验位
71 int firstCheck = calculateCheckDigit(digits, 12);
72 if (digits[12] != firstCheck) {
73 return false;
74 }
75
76 // 验证第二个校验位
77 int secondCheck = calculateCheckDigit(digits, 13);
78 if (digits[13] != secondCheck) {
79 return false;
80 }
81
82 return true;
83 }
84}
85重要的限制和注意事项
该工具能做什么和不能做什么
它验证的内容: 数学正确性——检查数字是否与算法计算匹配。
它不验证的内容: CNPJ是否在巴西国家税务局注册,是否属于活跃的公司,或是否与您预期的企业名称相关联。
将其视为拼写检查与事实核查的区别。该工具告诉您CNPJ是否根据数学规则"拼写"正确,但无法判断该号码是否对应真实、活跃的企业实体。
法律和道德使用
生成的CNPJ仅用于测试和开发。它们在数学上是有效的,但未在巴西当局注册,这意味着:
- ✅ 可以安全使用于: 填充测试数据库、单元测试验证逻辑、质量保证环境、文档代码示例
- ❌ 绝不可用于: 税务申报、企业注册、签订合同、处理真实交易或误导性企业身份
在官方场合使用虚假CNPJ不仅不道德,在巴西法律下是非法的,可能导致欺诈指控。
需要了解的技术限制
随机生成的影响: 该工具随机生成前12位数字。由国家税务局颁发的真实CNPJ遵循与注册日期、区域办事处和企业类型相关的内部模式。生成的数字不会匹配这些模式,复杂的验证系统可能会标记这一点。
无语义验证: 有效的CNPJ格式并不意味着有效的业务上下文。例如,政府实体有特定的CNPJ范围——这个生成器可能偶然创建一个,但它不会有实际意义。
格式处理: 验证器接受各种输入格式(12345678000195、12.345.678/0001-95),但一些传统系统需要精确的格式。请始终根据您的具体集成要求进行测试。
隐私和安全
所有处理都在浏览器的客户端进行。您生成或验证的CNPJ不会被发送到服务器、记录或存储。该工具不请求、处理或处理任何个人信息。
关于 CNPJ 验证的常见问题
CNPJ 验证和核实有什么区别?
验证检查号码是否在数学上正确——正确的格式、正确的校验位、没有无效模式。这个工具进行验证。
核实检查 CNPJ 是否在联邦税务局数据库中注册为实际公司。核实需要查询政府数据库,这不是此工具的功能。
你可以有一个完全有效但未核实的 CNPJ(如此工具生成的测试号码),或者一个属于真实公司但无效的 CNPJ(因为输入时出现了打字错误)。
我可以在生产测试中使用生成的 CNPJ 吗?
这取决于你所说的"生产测试"是什么。它们适用于暂存环境、负载测试和预发布质量保证。但如果"生产测试"意味着使用真实交易、真实政府 API 或真实财务系统进行测试,那么答案是不行,你需要实际注册的 CNPJ。
更安全的方法是:在隔离的测试环境中使用生成的 CNPJ,然后在测试生产集成时切换到少量你可控制的真实测试公司 CNPJ。
为什么验证器拒绝 11.111.111/1111-11?
尽管具有所有相同数字的 CNPJ 在数学上可以产生有效的校验位,但联邦税务局明确排除了这些模式。这是一个业务规则,而非数学规则。在某些验证系统中,对于连续模式也是如此。
这类似于许多系统拒绝像"password123"这样的密码,即使它们符合长度要求——它们在技术上是有效的,但实际上是不可接受的。
如何在不同地区处理 CNPJ 验证?
巴西公司在国际业务中有时会在输入外国系统时删除格式化字符。你的验证逻辑应在检查前剥离非数字字符:
1const cleanCNPJ = input.replace(/\D/g, ''); // 删除除数字外的所有内容
2接受 12.345.678/0001-95、12345678000195 和 12 345 678 0001 95 作为等效输入。
CNPJ 与 CPF 验证有什么区别?
CPF(个人税务识别号)是巴西的个人税务 ID,而 CNPJ 是针对企业的。它们使用不同的校验位算法和长度(CPF 有 11 位数字,CNPJ 有 14 位)。如果你正在构建一个处理两者的巴西应用,你需要单独的验证函数——尽管许多库支持这两种格式。
常见模式:让用户在同一字段输入 CPF 或 CNPJ,然后在删除格式化字符后根据长度检测类型。
这对在巴西运营的外国公司有效吗?
在巴西运营的外国公司也必须从联邦税务局获取 CNPJ。他们的 CNPJ 遵循与国内公司相同的格式和验证规则。没有特殊的"外国公司"CNPJ 格式。
然而,外国公司可能有额外的文档要求和不同的注册流程——请咨询巴西商业律师以获取具体信息。
我可以查询政府数据库以验证 CNPJ 注册吗?
是的,联邦税务局通过其公共 CNPJ 查询服务提供公共访问以验证基本 CNPJ 信息。你可以手动查找 CNPJ,或在获得适当授权的情况下使用其 API 进行编程访问。
请注意,大量使用需要注册,并且有速率限制以防止滥用。
CNPJ 变更频率如何?
CNPJ 是永久标识符,即使公司更改名称、地址或所有权结构也不会改变。但是,如果公司关闭后又重新注册,可能会收到新的 CNPJ。随着公司开设新地点,分支机构编号(/XXXX 部分)可能会添加,但基本 8 位数字保持不变。
参考资料和其他资源
官方政府来源
- 巴西联邦税务局 - 官方门户网站 - 巴西联邦税务局的官方网站,提供CNPJ注册和验证服务
- 公共CNPJ查询 - 公共CNPJ查询 - 官方政府服务,用于验证CNPJ注册状态
- 规范指令RFB第1863/2018号 - 管理巴西CNPJ注册和使用的法律法规
技术标准和文档
- 模块算术算法 - 校验位计算使用模11算术,这是验证位的标准方法
- ISO/IEC 7064 - 影响巴西文件验证设计的校验位系统国际标准
- 巴西民法典(第10.406/2002号法律) - 定义需要CNPJ注册的商业实体分类的法律框架
开发者资源
- NPM包注册表 - npmjs.com - 包括巴西文件验证器的JavaScript库仓库
- PyPI(Python包索引) - pypi.org - 用于CNPJ验证和巴西文件处理的Python库
- GitHub - 多种编程语言的CNPJ验证开源实现
开始生成和验证 CNPJ
无论您是在构建巴西电子商务平台、测试与 Mercado Pago 的支付集成,还是仅需了解 CNPJ 验证的工作原理,这个工具都能立即为您提供生成和验证功能。
无需安装、无需 API 密钥、无需复杂设置。只需打开浏览器,即可开始使用有效的巴西企业标识符。