Você está construindo um formulário de checkout e precisa validar o campo de cartão antes de enviar os dados pro gateway de pagamento. A solução mais comum e recomendada é usar o algoritmo de Luhn para checar se o número tem o formato matemático correto.

Neste artigo, você vai entender exatamente como o algoritmo funciona, ver um exemplo numérico passo a passo e implementar uma função JavaScript pronta pra usar no seu projeto.

O que é o algoritmo de Luhn

O algoritmo de Luhn, também chamado de "fórmula do módulo 10" ou "mod-10", foi criado por Hans Peter Luhn em 1954 e virou padrão da indústria para validar números de cartão de crédito. Ele calcula um dígito verificador (o último dígito do número) que permite detectar erros de digitação, como trocar dois dígitos de lugar ou digitar um número errado.

A ideia é simples: o emissor do cartão (banco ou bandeira) gera o número de forma que, quando você aplica a fórmula do Luhn, o resultado seja divisível por 10. Se não for, o número tem erro de formatação.

Isso é feito no lado do cliente (no navegador) antes de mandar os dados pro servidor. Assim você evita enviar requisições inválidas pro gateway de pagamento e melhora a experiência do usuário com feedback imediato.

Passo a passo do algoritmo com exemplo numérico

Vamos validar o número de teste da Visa que várias plataformas de pagamento usam em sandbox: 4242 4242 4242 4242. Primeiro, removemos espaços e traços, ficando com 4242424242424242.

Agora aplicamos o algoritmo de Luhn:

  1. Comece pelo dígito mais à direita (o último 2) e vá para a esquerda. Esse primeiro dígito nunca é dobrado.
  2. Dobre o valor de cada segundo dígito a partir daí, ou seja, pule um, dobre o próximo, pule um, dobre o próximo, e assim por diante.
  3. Se o dobro resultar em dois dígitos, some os dois algarismos entre si (ou subtraia 9, é equivalente).
  4. Some todos os dígitos (os dobrados/ajustados e os que não foram alterados).
  5. Se o total for divisível por 10, o número é válido pelo algoritmo de Luhn.

Exemplo prático com 4242424242424242

O número tem 16 dígitos, alternando 4 e 2. Começando pelo dígito mais à direita (que não é dobrado) e indo para a esquerda, os dígitos que caem na posição "dobrar" são sempre os 4, e os que caem na posição "não dobrar" são sempre os 2. Isso acontece porque o número inteiro segue esse padrão alternado.

  • Dígitos que não são dobrados (8 dígitos, todos 2): 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 = 16
  • Dígitos dobrados (8 dígitos, todos 4): cada 4 dobrado vira 8 (4 × 2 = 8, não passa de 9, não precisa ajustar). 8 + 8 + 8 + 8 + 8 + 8 + 8 + 8 = 64

Somando os dois grupos: 16 + 64 = 80.

Como 80 é divisível por 10 (resto 0), esse número passa na validação do algoritmo de Luhn.

Implementação em JavaScript puro

Abaixo está uma função completa que remove espaços, traços e outros caracteres não numéricos, depois aplica o algoritmo de Luhn:

function validarCartaoCredito(numero) {
  // Remove tudo que não for dígito
  const digitos = numero.replace(/\D/g, "");

  // Cartões têm entre 13 e 19 dígitos (a maioria 16)
  if (digitos.length < 13 || digitos.length > 19) {
    return false;
  }

  let soma = 0;
  let deveDobrar = false; // começa pelo último dígito (não dobra)

  // Percorre da direita para a esquerda
  for (let i = digitos.length - 1; i >= 0; i--) {
    let d = parseInt(digitos[i], 10);

    if (deveDobrar) {
      d *= 2;
      // Se resultou em dois dígitos, soma os algarismos (ou subtrai 9)
      if (d > 9) {
        d -= 9;
      }
    }

    soma += d;
    deveDobrar = !deveDobrar; // alterna para o próximo dígito
  }

  return soma % 10 === 0;
}

// Testando com o número de teste da Visa
console.log(validarCartaoCredito("4242 4242 4242 4242")); // true
console.log(validarCartaoCredito("4242424242424242")); // true
console.log(validarCartaoCredito("1234 5678 1234 5678")); // false

Essa função é o que você usa no onblur ou onsubmit do seu formulário. Se quiser testar online antes de integrar, temos um validador de cartão de crédito online, gratuito que aplica exatamente essa lógica.

O que esse algoritmo NÃO garante

Aqui vai o disclaimer que muita gente pula (e depois se arrepende): o algoritmo de Luhn valida apenas o FORMATO/estrutura matemática do número. Ele NÃO verifica:

  • Se o cartão existe de verdade
  • Se está ativo ou bloqueado
  • Se tem limite disponível
  • Se pertence à pessoa que está preenchendo o formulário
  • Se não é um cartão reportado como roubado/fraudado

Isso só o emissor do cartão (banco ou bandeira) consegue checar, via gateway de pagamento real (Stripe, Pagar.me, Mercado Pago, etc.). O Luhn é só um "filtro de digitação". Ele evita que você mande 1234 5678 1234 5678 pro gateway e receba um erro bobo que poderia ter sido pego antes.

Não escreva no seu código nada que sugira que validar com Luhn significa "cartão válido pra cobrar", porque não é verdade.

Erros comuns

Se você já implementou validação de cartão, provavelmente já viu (ou cometeu) algum desses:

Validar só pela quantidade de dígitos

Muitos formulários só checam se o número tem 16 dígitos. Isso deixa passar 1111111111111111, que tem 16 dígitos mas falha no Luhn. O inverso também acontece: American Express tem 15 dígitos, então validar só por "tem que ter 16" quebra o fluxo pra quem usa Amex.

Não remover espaços/traços antes de validar

O usuário digita 4242-4242-4242-4242 ou 4242 4242 4242 4242. Se você não limpar isso antes de aplicar o Luhn, a validação falha mesmo com o número correto. A linha numero.replace(/\D/g, '') resolve isso.

Tratar Luhn como verificação antifraude

Isso é clássico: o time de produto pede "valida se o cartão é válido" e o dev implementa Luhn achando que tá fazendo verificação de fraude. Não tá. Fraude requer análise de risco, tokenização, 3D Secure, regras do gateway. Nada disso o Luhn faz.

Usar números de teste como se fossem reais

Os números de teste que gateways como Stripe e PayPal disponibilizam são válidos pelo Luhn, mas não são cartões reais. Eles só funcionam em ambiente de sandbox. Nunca use em produção e nunca tente "testar se funciona" em gateway real. Isso é violação dos termos e pode gerar bloqueio.

Se precisar de dados de teste válidos pelo Luhn pra testar formulários, nosso gerador de cartão de crédito para testes cria números estruturalmente corretos (mas não reais) pra você usar no QA.

Perguntas frequentes

Como saber se um número de cartão é válido?

Depende do que você quer dizer com "válido". Se for formato correto, use o algoritmo de Luhn, que é o que a maioria dos gateways espera no front-end. Se for cartão que realmente funciona, só o gateway de pagamento (via emissor) consegue responder, depois que você tenta cobrar.

Dá pra testar um formulário de pagamento sem usar cartão real?

Sim. Use os números de teste que cada gateway fornece (Stripe, Pagar.me, Mercado Pago, etc.). Eles são válidos pelo Luhn e simulam cenários como "pagamento aprovado", "saldo insuficiente", "3D Secure", etc. Nunca use cartões reais de terceiros. Use só os de sandbox.

Validar cartão de crédito é a mesma coisa que verificar se ele está ativo?

Não. Validar (com Luhn) checa se o número tem a estrutura matemática correta. Verificar se está ativo, tem limite ou não tá bloqueado é papel do banco, feito via gateway, quando você tenta processar o pagamento.

O que é o algoritmo de Luhn?

É uma fórmula matemática (módulo 10) que calcula um dígito verificador pra detectar erros de digitação em números como cartões de crédito, IMEI de celular, etc. Foi criado em 1954 por Hans Peter Luhn e virou padrão da indústria.

Posso usar o Luhn pra evitar fraude?

Não. O Luhn só pega erro de digitação. Fraude requer análise comportamental, verificação de endereço, 3D Secure, regras de risco do gateway. Nada disso o Luhn faz.

Qual a diferença entre "número válido pelo Luhn" e "cartão válido pra cobrar"?

"Número válido pelo Luhn" significa formato matemático correto. "Cartão válido pra cobrar" significa que o emissor confirmou que o cartão existe, tá ativo, tem limite e não tá bloqueado. Só o gateway junto com o emissor respondem a segunda pergunta.

Fechamento

Se você tá implementando validação de cartão num formulário de checkout, o algoritmo de Luhn é o primeiro passo, e o mais importante, pra evitar erros bobos de digitação. Implemente a função acima, teste com os números de sandbox do seu gateway e lembre sempre: Luhn valida formato, não valida se o cartão funciona de verdade.

Quer testar sua implementação antes de subir pra produção? Experimente nosso validador de cartão de crédito online. Ele aplica exatamente a mesma lógica que você vai usar no código.