JavaScript: Calculadora do Dígito Verificador GTIN/EAN

Todo código de barras de produto (EAN-13 na embalagem do varejo, UPC-A em itens importados, DUN-14 na caixa de embarque) termina em um dígito verificador. Ele é calculado a partir dos demais números e permite que o leitor de código de barras, o ERP ou o emissor de NF-e confirmem que o código foi lido ou digitado corretamente.
Neste tutorial vamos construir, do zero, uma calculadora do dígito verificador GTIN/EAN em JavaScript, com interface em Bootstrap 5. A ferramenta gera o dígito verificador a partir do código incompleto e também valida um GTIN já completo. No final você encontra o código completo em um único arquivo e o resultado esperado para códigos de teste reais.
Nível: iniciante a intermediário. Você precisa conhecer HTML e ter noções de funções e eventos em JavaScript.
O que vamos construir
Uma página única, responsiva e acessível, com dois modos de uso:
- Gerar dígito: o usuário informa 7, 11, 12 ou 13 dígitos e a calculadora devolve o dígito verificador, o GTIN completo e o tipo identificado (GTIN-8, GTIN-12, GTIN-13 ou GTIN-14).
- Validar GTIN: o usuário informa um código completo (8, 12, 13 ou 14 dígitos) e a calculadora informa se o dígito verificador está correto e, se não estiver, qual seria o dígito certo.
Recursos implementados:
- Algoritmo módulo 10 da GS1, com os pesos 3 e 1 aplicados da direita para a esquerda
- Limpeza automática de espaços, pontos e hifens colados junto com o código
- Identificação do tipo de GTIN pelo tamanho
- Mensagens de erro no próprio campo (padrão de validação do Bootstrap), anunciadas por leitores de tela
- Botão para copiar o GTIN gerado
- Lógica isolada em funções puras, fáceis de reaproveitar em outros projetos
Stack: HTML5, Bootstrap 5.3 (via CDN), Bootstrap Icons e JavaScript puro, sem build.
Tempo estimado: 30 a 45 minutos.
Se você só precisa do resultado, a mesma lógica está disponível na calculadora de dígito verificador GTIN do msdicas.
Pré-requisitos
- Um editor de código, como o VS Code
- Um navegador atualizado (Chrome, Edge, Firefox ou Safari)
- Conexão com a internet para carregar o Bootstrap pela CDN
Entendendo o dígito verificador GTIN/EAN
GTIN (Global Trade Item Number) é o número de identificação de itens comerciais mantido pela GS1, organização responsável pelo padrão de códigos de barras. “EAN” é o nome antigo que ainda aparece no dia a dia (EAN-13, EAN-8). Existem quatro tamanhos:
| Formato | Nome usual | Dígitos no total | Dígitos que você informa | Uso típico |
|---|---|---|---|---|
| GTIN-8 | EAN-8 | 8 | 7 | Embalagens pequenas |
| GTIN-12 | UPC-A | 12 | 11 | Produtos dos EUA e do Canadá |
| GTIN-13 | EAN-13 | 13 | 12 | Varejo no Brasil e na maior parte do mundo |
| GTIN-14 | DUN-14 / ITF-14 | 14 | 13 | Caixas e unidades logísticas |
O último dígito de todos eles é o verificador. Para entender a regra com mais profundidade, o impacto na gestão de estoque e os erros mais comuns em cadastros, leia o guia Cálculo do dígito verificador para códigos de barras GTIN.
O algoritmo módulo 10 da GS1
O método oficial da GS1 funciona assim:
- Pegue o código sem o dígito verificador.
- Começando pelo dígito mais à direita, multiplique os dígitos alternadamente por 3, 1, 3, 1…
- Some todos os resultados.
- O dígito verificador é o número que falta para a soma chegar ao próximo múltiplo de 10. Em fórmula:
(10 - (soma % 10)) % 10. O% 10final faz com que uma soma que já é múltipla de 10 resulte em0, e não em10.
Atenção à direção dos pesos. O erro mais comum em implementações é atribuir os pesos a partir da esquerda. Isso funciona por coincidência no EAN-13, que tem 12 dígitos de entrada (quantidade par), mas gera o dígito errado no GTIN-8, no GTIN-12 e no GTIN-14. A versão anterior deste tutorial tinha esse problema. O código abaixo já está corrigido.
Exemplo manual com um EAN-13 real
Vamos calcular o verificador de 400638133393, cujo código completo é 4006381333931:
| Dígito (da esquerda para a direita) | 4 | 0 | 0 | 6 | 3 | 8 | 1 | 3 | 3 | 3 | 9 | 3 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Peso (atribuído a partir da direita) | 1 | 3 | 1 | 3 | 1 | 3 | 1 | 3 | 1 | 3 | 1 | 3 |
| Produto | 4 | 0 | 0 | 18 | 3 | 24 | 1 | 9 | 3 | 9 | 9 | 9 |
- Soma: 4 + 0 + 0 + 18 + 3 + 24 + 1 + 9 + 3 + 9 + 9 + 9 = 89
- Próximo múltiplo de 10: 90
- Dígito verificador: 90 − 89 = 1, e o GTIN completo fica
4006381333931
Veja agora o GTIN-8 7351353, com 7 dígitos, em que o primeiro dígito recebe peso 3:
| Dígito | 7 | 3 | 5 | 1 | 3 | 5 | 3 |
|---|---|---|---|---|---|---|---|
| Peso | 3 | 1 | 3 | 1 | 3 | 1 | 3 |
| Produto | 21 | 3 | 15 | 1 | 9 | 5 | 9 |
Soma = 63, então o dígito é 70 − 63 = 7 e o código completo fica 73513537. Com os pesos invertidos, o resultado seria 5, o que produziria um código inválido.
Estrutura de arquivos
Para manter o tutorial simples, tudo fica em um único arquivo. Em um projeto maior, separe o CSS e o JavaScript em arquivos próprios.
calculadora-gtin/
└── index.html # interface, estilos e script
Passo 1: estrutura HTML com Bootstrap 5
Comece com o esqueleto HTML5 e carregue o CSS do Bootstrap e o Bootstrap Icons no <head>:
<!doctype html>
<html lang="pt-BR">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Calculadora do Dígito Verificador GTIN/EAN</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" rel="stylesheet" />
</head>
<body class="bg-body-tertiary">
<main class="container py-5">
<!-- cartão da calculadora -->
</main>
</body>
</html>
lang="pt-BR"informa o idioma aos leitores de tela e aos mecanismos de busca.- A meta
viewporté o que faz o layout responsivo funcionar em celulares. <main>marca o conteúdo principal da página, o que facilita a navegação por tecnologias assistivas.
O cartão e a escolha do modo
Dentro do <main>, um cartão centralizado reúne a calculadora. A escolha entre gerar e validar usa um button group do Bootstrap montado com botões de rádio. Assim o controle continua funcionando com teclado e é anunciado corretamente por leitores de tela:
<div class="row justify-content-center">
<div class="col-12 col-md-8 col-lg-6">
<div class="card shadow-sm border-0">
<div class="card-body p-4">
<h1 class="h4 mb-1">
<i class="bi bi-upc-scan" aria-hidden="true"></i>
Calculadora do dígito verificador GTIN/EAN
</h1>
<p class="text-body-secondary small mb-4">GTIN-8, GTIN-12 (UPC-A), GTIN-13 (EAN-13) e GTIN-14 (DUN-14)</p>
<fieldset class="mb-3">
<legend class="form-label fs-6">O que você quer fazer?</legend>
<div class="btn-group w-100" role="group">
<input type="radio" class="btn-check" name="modo" id="modoGerar" value="gerar" checked />
<label class="btn btn-outline-primary" for="modoGerar">Gerar dígito</label>
<input type="radio" class="btn-check" name="modo" id="modoValidar" value="validar" />
<label class="btn btn-outline-primary" for="modoValidar">Validar GTIN</label>
</div>
</fieldset>
<!-- formulário -->
</div>
</div>
</div>
</div>
O formulário
O campo de entrada usa inputmode="numeric" para abrir o teclado numérico no celular. Usamos type="text", e não type="number", porque o GTIN é um identificador, não um valor numérico: type="number" descartaria zeros à esquerda (comuns no UPC-A) e mostraria setas de incremento sem utilidade aqui.
<form id="formGtin" novalidate>
<label for="codigo" class="form-label" id="rotuloCodigo">Código sem o dígito verificador</label>
<div class="input-group has-validation">
<input
type="text"
class="form-control form-control-lg font-monospace"
id="codigo"
inputmode="numeric"
autocomplete="off"
maxlength="20"
aria-describedby="ajudaCodigo erroCodigo"
placeholder="Ex.: 789100010000"
/>
<button type="submit" class="btn btn-primary" id="btnCalcular">
<i class="bi bi-calculator-fill" aria-hidden="true"></i>
<span id="textoBotao">Calcular</span>
</button>
<div class="invalid-feedback" id="erroCodigo"></div>
</div>
<div class="form-text" id="ajudaCodigo">Informe 7, 11, 12 ou 13 dígitos. Espaços, pontos e hifens são ignorados.</div>
</form>
Alguns detalhes importantes:
<form>com botãotype="submit": a tecla Enter passa a disparar o cálculo sem nenhum código extra.novalidate: desliga os balões nativos do navegador para que as mensagens de erro sigam o padrão visual do Bootstrap.aria-describedby: associa a dica e a mensagem de erro ao campo, e o leitor de tela lê as duas ao focar o input.maxlength="20": dá margem para quem cola o código com separadores (por exemplo,789-1000-10000).
A área de resultado
O resultado fica em uma região com aria-live="polite", que faz os leitores de tela anunciarem o conteúdo sempre que ele muda. Ela começa oculta com o atributo hidden:
<div id="resultado" class="mt-4" aria-live="polite" hidden></div>
Por que não usar um modal para os erros? A versão anterior deste tutorial exibia erros em um modal. Na prática, o modal interrompe o fluxo, exige um clique extra para fechar e afasta a mensagem do campo com problema. Mostrar o erro abaixo do input é o padrão recomendado pelo próprio guia de validação do Bootstrap.
Passo 2: estilização
O Bootstrap cobre quase tudo. Só precisamos de alguns ajustes para destacar o GTIN no resultado:
<style>
.gtin-resultado {
font-size: clamp(1.5rem, 6vw, 2.25rem);
letter-spacing: 0.12em;
word-break: break-all;
}
.gtin-resultado .dv {
color: var(--bs-primary);
font-weight: 700;
text-decoration: underline;
}
</style>
clamp()deixa o tamanho da fonte fluido: legível no celular sem ficar exagerado no desktop.letter-spacingsepara os dígitos e facilita a conferência visual.- A classe
.dvdestaca o dígito verificador usando a variável de cor do Bootstrap. O sublinhado garante que o destaque não dependa só da cor.
Passo 3: a lógica em JavaScript
Vamos separar o código em duas camadas:
- Funções puras (
normalizarCodigo,calcularDigitoVerificador,gerarGtin,validarGtin): recebem valores e devolvem valores, sem tocar no DOM. Podem ser copiadas para um back-end Node.js ou para qualquer outro projeto. - Camada de interface: lê o formulário, chama as funções puras e exibe o resultado.
Normalizando a entrada
function normalizarCodigo(valor) {
return String(valor ?? "").replace(/\D/g, "");
}
A expressão regular /\D/g remove tudo o que não é dígito. Isso permite colar códigos com espaços, pontos ou hifens vindos de planilhas e sistemas. String(valor ?? '') evita erro caso a função receba null ou undefined.
Calculando o dígito verificador
Esta é a função central. Ela percorre o código da direita para a esquerda, alternando os pesos 3 e 1:
function calcularDigitoVerificador(codigoSemDigito) {
let soma = 0;
let peso = 3; // o dígito mais à direita sempre recebe peso 3
for (let i = codigoSemDigito.length - 1; i >= 0; i--) {
soma += Number(codigoSemDigito[i]) * peso;
peso = peso === 3 ? 1 : 3;
}
return (10 - (soma % 10)) % 10;
}
Por percorrer a partir da direita, a mesma função serve para os quatro formatos. Não é preciso tratar a quantidade de dígitos, par ou ímpar, como caso especial.
Identificando o tipo de GTIN
Um objeto de mapeamento relaciona a quantidade de dígitos informada ao formato:
const TIPOS_POR_TAMANHO_SEM_DV = {
7: "GTIN-8 (EAN-8)",
11: "GTIN-12 (UPC-A)",
12: "GTIN-13 (EAN-13)",
13: "GTIN-14 (DUN-14)",
};
Gerando um GTIN completo
function gerarGtin(valor) {
const codigo = normalizarCodigo(valor);
const tipo = TIPOS_POR_TAMANHO_SEM_DV[codigo.length];
if (!tipo) {
throw new Error(`Informe 7, 11, 12 ou 13 dígitos. Você informou ${codigo.length}.`);
}
const digito = calcularDigitoVerificador(codigo);
return { tipo, codigo, digito, gtin: codigo + digito };
}
Em vez de devolver só o dígito, a função devolve um objeto com tudo o que a interface precisa. Entradas inválidas geram uma exceção com mensagem pronta para o usuário.
Validando um GTIN existente
function validarGtin(valor) {
const gtin = normalizarCodigo(valor);
const tipo = TIPOS_POR_TAMANHO_SEM_DV[gtin.length - 1];
if (!tipo) {
throw new Error(`Um GTIN completo tem 8, 12, 13 ou 14 dígitos. Você informou ${gtin.length}.`);
}
const corpo = gtin.slice(0, -1);
const informado = Number(gtin.slice(-1));
const esperado = calcularDigitoVerificador(corpo);
return { tipo, gtin, valido: informado === esperado, informado, esperado };
}
A validação reaproveita o cálculo: separa o último dígito, recalcula o verificador sobre o restante e compara os dois.
Passo 4: interface, eventos e tratamento de erros
Com a lógica pronta, conectamos o formulário. Primeiro, as referências aos elementos:
const form = document.getElementById("formGtin");
const campo = document.getElementById("codigo");
const erro = document.getElementById("erroCodigo");
const resultado = document.getElementById("resultado");
Exibindo e limpando erros
function mostrarErro(mensagem) {
erro.textContent = mensagem;
campo.classList.add("is-invalid");
campo.setAttribute("aria-invalid", "true");
resultado.hidden = true;
campo.focus();
}
function limparErro() {
erro.textContent = "";
campo.classList.remove("is-invalid");
campo.removeAttribute("aria-invalid");
}
A classe is-invalid ativa a borda vermelha e exibe o .invalid-feedback do Bootstrap. O atributo aria-invalid informa o mesmo estado às tecnologias assistivas.
Montando o resultado com segurança
function criarElemento(tag, classes, texto) {
const el = document.createElement(tag);
if (classes) el.className = classes;
if (texto !== undefined) el.textContent = texto;
return el;
}
Todo conteúdo dinâmico entra via textContent, nunca via innerHTML. Aqui a entrada já é sanitizada para conter só dígitos, mas manter esse hábito evita falhas de XSS quando o código for adaptado para outros dados.
O evento de envio
form.addEventListener("submit", (evento) => {
evento.preventDefault();
limparErro();
try {
if (modoAtual() === "gerar") {
exibirGeracao(gerarGtin(campo.value));
} else {
exibirValidacao(validarGtin(campo.value));
}
} catch (e) {
mostrarErro(e.message);
}
});
preventDefault()impede que o formulário recarregue a página.- O
try/catchconverte as exceções das funções puras em mensagens no campo. - As funções
exibirGeracao,exibirValidacaoemodoAtualestão no código completo a seguir. Elas apenas montam os elementos do resultado e leem o rádio selecionado.
Código completo
Copie o conteúdo abaixo para um arquivo index.html e abra no navegador. Não é preciso servidor nem instalação.
<!doctype html>
<html lang="pt-BR">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Calculadora do Dígito Verificador GTIN/EAN</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" rel="stylesheet" />
<style>
.gtin-resultado {
font-size: clamp(1.5rem, 6vw, 2.25rem);
letter-spacing: 0.12em;
word-break: break-all;
}
.gtin-resultado .dv {
color: var(--bs-primary);
font-weight: 700;
text-decoration: underline;
}
</style>
</head>
<body class="bg-body-tertiary">
<main class="container py-5">
<div class="row justify-content-center">
<div class="col-12 col-md-8 col-lg-6">
<div class="card shadow-sm border-0">
<div class="card-body p-4">
<h1 class="h4 mb-1">
<i class="bi bi-upc-scan" aria-hidden="true"></i>
Calculadora do dígito verificador GTIN/EAN
</h1>
<p class="text-body-secondary small mb-4">GTIN-8, GTIN-12 (UPC-A), GTIN-13 (EAN-13) e GTIN-14 (DUN-14)</p>
<fieldset class="mb-3">
<legend class="form-label fs-6">O que você quer fazer?</legend>
<div class="btn-group w-100" role="group">
<input type="radio" class="btn-check" name="modo" id="modoGerar" value="gerar" checked />
<label class="btn btn-outline-primary" for="modoGerar">Gerar dígito</label>
<input type="radio" class="btn-check" name="modo" id="modoValidar" value="validar" />
<label class="btn btn-outline-primary" for="modoValidar">Validar GTIN</label>
</div>
</fieldset>
<form id="formGtin" novalidate>
<label for="codigo" class="form-label" id="rotuloCodigo">Código sem o dígito verificador</label>
<div class="input-group has-validation">
<input
type="text"
class="form-control form-control-lg font-monospace"
id="codigo"
inputmode="numeric"
autocomplete="off"
maxlength="20"
aria-describedby="ajudaCodigo erroCodigo"
placeholder="Ex.: 789100010000"
/>
<button type="submit" class="btn btn-primary" id="btnCalcular">
<i class="bi bi-calculator-fill" aria-hidden="true"></i>
<span id="textoBotao">Calcular</span>
</button>
<div class="invalid-feedback" id="erroCodigo"></div>
</div>
<div class="form-text" id="ajudaCodigo">Informe 7, 11, 12 ou 13 dígitos. Espaços, pontos e hifens são ignorados.</div>
</form>
<div id="resultado" class="mt-4" aria-live="polite" hidden></div>
</div>
</div>
</div>
</div>
</main>
<script>
"use strict";
/* ---------- Lógica pura (sem DOM) ---------- */
const TIPOS_POR_TAMANHO_SEM_DV = {
7: "GTIN-8 (EAN-8)",
11: "GTIN-12 (UPC-A)",
12: "GTIN-13 (EAN-13)",
13: "GTIN-14 (DUN-14)",
};
function normalizarCodigo(valor) {
return String(valor ?? "").replace(/\D/g, "");
}
function calcularDigitoVerificador(codigoSemDigito) {
let soma = 0;
let peso = 3; // o dígito mais à direita sempre recebe peso 3
for (let i = codigoSemDigito.length - 1; i >= 0; i--) {
soma += Number(codigoSemDigito[i]) * peso;
peso = peso === 3 ? 1 : 3;
}
return (10 - (soma % 10)) % 10;
}
function gerarGtin(valor) {
const codigo = normalizarCodigo(valor);
const tipo = TIPOS_POR_TAMANHO_SEM_DV[codigo.length];
if (!tipo) {
throw new Error(`Informe 7, 11, 12 ou 13 dígitos. Você informou ${codigo.length}.`);
}
const digito = calcularDigitoVerificador(codigo);
return { tipo, codigo, digito, gtin: codigo + digito };
}
function validarGtin(valor) {
const gtin = normalizarCodigo(valor);
const tipo = TIPOS_POR_TAMANHO_SEM_DV[gtin.length - 1];
if (!tipo) {
throw new Error(`Um GTIN completo tem 8, 12, 13 ou 14 dígitos. Você informou ${gtin.length}.`);
}
const corpo = gtin.slice(0, -1);
const informado = Number(gtin.slice(-1));
const esperado = calcularDigitoVerificador(corpo);
return { tipo, gtin, valido: informado === esperado, informado, esperado };
}
/* ---------- Interface ---------- */
const form = document.getElementById("formGtin");
const campo = document.getElementById("codigo");
const erro = document.getElementById("erroCodigo");
const resultado = document.getElementById("resultado");
const rotulo = document.getElementById("rotuloCodigo");
const ajuda = document.getElementById("ajudaCodigo");
const textoBotao = document.getElementById("textoBotao");
const TEXTOS = {
gerar: {
rotulo: "Código sem o dígito verificador",
ajuda: "Informe 7, 11, 12 ou 13 dígitos. Espaços, pontos e hifens são ignorados.",
botao: "Calcular",
placeholder: "Ex.: 789100010000",
},
validar: {
rotulo: "GTIN completo",
ajuda: "Informe 8, 12, 13 ou 14 dígitos, incluindo o dígito verificador.",
botao: "Validar",
placeholder: "Ex.: 7891000100004",
},
};
function modoAtual() {
return document.querySelector('input[name="modo"]:checked').value;
}
function criarElemento(tag, classes, texto) {
const el = document.createElement(tag);
if (classes) el.className = classes;
if (texto !== undefined) el.textContent = texto;
return el;
}
function mostrarErro(mensagem) {
erro.textContent = mensagem;
campo.classList.add("is-invalid");
campo.setAttribute("aria-invalid", "true");
resultado.hidden = true;
campo.focus();
}
function limparErro() {
erro.textContent = "";
campo.classList.remove("is-invalid");
campo.removeAttribute("aria-invalid");
}
function exibirGeracao({ tipo, codigo, digito, gtin }) {
const alerta = criarElemento("div", "alert alert-success mb-0");
alerta.append(criarElemento("p", "small text-uppercase fw-semibold mb-1", tipo));
const numero = criarElemento("p", "gtin-resultado font-monospace mb-2");
numero.append(codigo, criarElemento("span", "dv", String(digito)));
alerta.append(numero);
alerta.append(criarElemento("p", "mb-3", `Dígito verificador: ${digito}`));
const copiar = criarElemento("button", "btn btn-sm btn-outline-success");
copiar.type = "button";
copiar.innerHTML = '<i class="bi bi-clipboard" aria-hidden="true"></i> ';
copiar.append("Copiar GTIN");
copiar.addEventListener("click", async () => {
try {
await navigator.clipboard.writeText(gtin);
copiar.lastChild.textContent = "Copiado!";
} catch {
copiar.lastChild.textContent = "Não foi possível copiar";
}
});
alerta.append(copiar);
resultado.replaceChildren(alerta);
resultado.hidden = false;
}
function exibirValidacao({ tipo, gtin, valido, informado, esperado }) {
const alerta = criarElemento("div", `alert ${valido ? "alert-success" : "alert-danger"} mb-0`);
alerta.append(criarElemento("p", "small text-uppercase fw-semibold mb-1", tipo));
alerta.append(criarElemento("p", "gtin-resultado font-monospace mb-2", gtin));
const mensagem = valido
? "GTIN válido: o dígito verificador está correto."
: `GTIN inválido: o dígito verificador informado é ${informado}, mas o correto é ${esperado}.`;
alerta.append(criarElemento("p", "mb-0 fw-semibold", mensagem));
resultado.replaceChildren(alerta);
resultado.hidden = false;
}
document.querySelectorAll('input[name="modo"]').forEach((radio) => {
radio.addEventListener("change", () => {
const textos = TEXTOS[modoAtual()];
rotulo.textContent = textos.rotulo;
ajuda.textContent = textos.ajuda;
textoBotao.textContent = textos.botao;
campo.placeholder = textos.placeholder;
limparErro();
resultado.hidden = true;
campo.focus();
});
});
campo.addEventListener("input", limparErro);
form.addEventListener("submit", (evento) => {
evento.preventDefault();
limparErro();
try {
if (modoAtual() === "gerar") {
exibirGeracao(gerarGtin(campo.value));
} else {
exibirValidacao(validarGtin(campo.value));
}
} catch (e) {
mostrarErro(e.message);
}
});
</script>
</body>
</html>
Resultado do código
Ao abrir o index.html, você verá um cartão centralizado com o seletor Gerar dígito / Validar GTIN, o campo de código e o botão Calcular. Os casos abaixo usam códigos de exemplo reais e mostram exatamente o que a calculadora exibe.
Modo “Gerar dígito”
| Você digita | Tipo exibido | Dígito verificador | GTIN completo exibido |
|---|---|---|---|
7351353 | GTIN-8 (EAN-8) | 7 | 73513537 |
03600029145 | GTIN-12 (UPC-A) | 2 | 036000291452 |
400638133393 | GTIN-13 (EAN-13) | 1 | 4006381333931 |
789-1000-10000 | GTIN-13 (EAN-13) | 4 | 7891000100004 |
1400638133393 | GTIN-14 (DUN-14) | 8 | 14006381333938 |
No caso do EAN-13, a tela mostra:
GTIN-13 (EAN-13)
400638133393[1] ← o "1" aparece destacado em azul e sublinhado
Dígito verificador: 1
[ Copiar GTIN ]
Modo “Validar GTIN”
| Você digita | Mensagem exibida |
|---|---|
4006381333931 | GTIN válido: o dígito verificador está correto. |
4006381333932 | GTIN inválido: o dígito verificador informado é 2, mas o correto é 1. |
73513535 | GTIN inválido: o dígito verificador informado é 5, mas o correto é 7. |
Mensagens de erro
| Entrada | Modo | Mensagem abaixo do campo |
|---|---|---|
12345 | Gerar | Informe 7, 11, 12 ou 13 dígitos. Você informou 5. |
| (vazio) | Gerar | Informe 7, 11, 12 ou 13 dígitos. Você informou 0. |
123456789 | Validar | Um GTIN completo tem 8, 12, 13 ou 14 dígitos. Você informou 9. |
O campo fica com borda vermelha, recebe o foco de volta e a mensagem some assim que o usuário começa a digitar de novo.
Possíveis melhorias
- Gerar a imagem do código de barras: bibliotecas como o JsBarcode desenham EAN-13, EAN-8 e UPC em SVG ou canvas a partir do GTIN gerado. Se você quer ver isso pronto, o msdicas tem o Gerador de Etiquetas de Produtos, que usa o JsBarcode para montar uma etiqueta completa: código de barras EAN-8, UPC-A ou EAN-13 com cálculo automático do dígito verificador, nome do produto, layout nos formatos Pimaco e exportação em PDF pronta para imprimir.
- Validação em lote: aceitar uma lista de códigos (um por linha ou colada do Excel) e exibir uma tabela com os válidos e inválidos, algo útil para saneamento de cadastro de produtos no ERP.
- Módulo ES reutilizável: mover as funções puras para um
gtin.jscomexporte importá-las em qualquer página ou projeto que precise do cálculo. - Checagem de prefixo: alertar quando o GTIN-13 não começar com
789ou790, faixas atribuídas à GS1 Brasil. Isso não invalida o código, mas ajuda a identificar produtos importados.
Limite importante: um dígito verificador correto garante apenas que o número é matematicamente consistente. Ele não prova que o GTIN foi licenciado pela GS1 nem que pertence ao produto. Para a NF-e, a SEFAZ valida o GTIN informado nos campos
cEANecEANTribcontra o Cadastro Centralizado de GTIN. Por isso, gerar um GTIN “inventado” com dígito válido não resolve rejeições fiscais.
Conclusão
Você construiu uma calculadora do dígito verificador GTIN/EAN que gera e valida os quatro formatos do padrão GS1, com interface responsiva em Bootstrap 5, mensagens de erro acessíveis e lógica isolada em funções reutilizáveis. O ponto central do tutorial é o algoritmo módulo 10 com os pesos 3 e 1 aplicados a partir da direita, detalhe que separa uma implementação correta de uma que falha em três dos quatro formatos.
Para ver a ferramenta pronta em produção, acesse a calculadora de dígito verificador GTIN do msdicas. Se quiser se aprofundar nos recursos usados aqui, veja também estilização e validação de formulários com Bootstrap 5 e o guia básico de validação de formulários com JavaScript.
Referências
- GS1 — How to calculate a check digit manually: método oficial de cálculo do dígito verificador. gs1.org/services/how-calculate-check-digit-manually
- GS1 — Global Trade Item Number (GTIN): definição e formatos do GTIN. gs1.org/standards/id-keys/gtin
- GS1 Brasil: associação responsável pelo licenciamento de códigos no Brasil. gs1br.org
- Bootstrap 5.3 — Validation: padrão de mensagens
is-invalideinvalid-feedback. getbootstrap.com/docs/5.3/forms/validation - Bootstrap Icons: biblioteca de ícones usada na interface. icons.getbootstrap.com
- MDN — String.prototype.replace() e expressões regulares. developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/String/replace
- MDN — Atributo aria-live: regiões dinâmicas anunciadas por leitores de tela. developer.mozilla.org/pt-BR/docs/Web/Accessibility/ARIA/Attributes/aria-live
Comentários
Seja o primeiro a comentar!
Deixe seu comentário