Como validar número de cartão de crédito (algoritmo de Luhn)

O último dígito de um cartão de crédito é um dígito verificador, calculado pelo algoritmo de Luhn. Ele pega erros de digitação, como um número trocado, antes de o pagamento chegar ao banco. Este guia explica o cálculo, mostra a validação em JavaScript, Python e PHP e lista o que o Luhn não garante e os cuidados com dados de cartão.

Por Leonardo Gaertner · Publicado em

Como o algoritmo funciona

  • Comece pelo último dígito e vá para a esquerda.
  • Dobre um dígito sim, outro não, a partir do segundo da direita. Se o dobro passar de 9, subtraia 9 (14 vira 5).
  • Some tudo. O número é válido se a soma terminar em 0, ou seja, se for múltiplo de 10.

O Luhn pega todos os erros de um único dígito e quase todas as trocas de dois dígitos vizinhos (a exceção é 09 com 90). É a mesma ideia dos dígitos verificadores do CPF, com outra conta: veja o guia de validação de CPF. Para conferir um número na hora, use o validador de cartão de crédito.

Em JavaScript

A conta do Luhn fica separada da regra do cartão (de 12 a 19 dígitos), porque ela também vale para números de outros tamanhos, como o IMEI dos celulares. A função digitoLuhn calcula o dígito final, útil para montar números de teste.

JavaScript
// Algoritmo de Luhn: da direita para a esquerda, dobra um dígito sim, outro não
function luhnConfere(digitos) {
  let soma = 0;
  for (let i = 0; i < digitos.length; i++) {
    let n = Number(digitos[digitos.length - 1 - i]);
    if (i % 2 === 1) {
      n *= 2;
      if (n > 9) n -= 9; // 7 × 2 = 14, e 1 + 4 = 5 (o mesmo que 14 - 9)
    }
    soma += n;
  }
  return soma % 10 === 0;
}

// Cartão: de 12 a 19 dígitos e o Luhn conferindo
function cartaoValido(numero) {
  const d = numero.replace(/\D/g, '');
  return d.length >= 12 && d.length <= 19 && luhnConfere(d);
}

// Dígito que completa um número para passar no Luhn (útil para gerar dados de teste)
function digitoLuhn(base) {
  for (let dv = 0; dv <= 9; dv++) {
    if (luhnConfere(`${base}${dv}`)) return dv;
  }
}

Em Python e PHP

Python
import re


def luhn_confere(digitos: str) -> bool:
    soma = 0
    for i, c in enumerate(reversed(digitos)):
        n = int(c)
        if i % 2 == 1:
            n = n * 2 - 9 if n * 2 > 9 else n * 2
        soma += n
    return soma % 10 == 0


def cartao_valido(numero: str) -> bool:
    d = re.sub(r"\D", "", numero)
    return 12 <= len(d) <= 19 and luhn_confere(d)
PHP
<?php
function luhnConfere(string $digitos): bool
{
    $soma = 0;
    foreach (str_split(strrev($digitos)) as $i => $c) {
        $n = (int) $c;
        if ($i % 2 === 1) {
            $n = $n * 2 > 9 ? $n * 2 - 9 : $n * 2;
        }
        $soma += $n;
    }
    return $soma % 10 === 0;
}

function cartaoValido(string $numero): bool
{
    $d = preg_replace('/\D/', '', $numero);
    return strlen($d) >= 12 && strlen($d) <= 19 && luhnConfere($d);
}

O que o Luhn não garante

  • Que o cartão existe, está ativo ou tem limite: isso só a operadora responde, na autorização do pagamento.
  • A bandeira: os primeiros dígitos (o BIN) indicam o emissor. Visa começa com 4, Mastercard com 51 a 55 ou 2221 a 2720, American Express com 34 ou 37. As faixas de Elo e Hipercard são muitas e mudam; deixe a identificação com o gateway de pagamento.
  • Para testar, use os números de teste publicados pelo seu gateway, como 4111 1111 1111 1111, que passam no Luhn e não cobram nada, ou crie números fictícios com o gerador de cartão de crédito.

Cuidados com dados de cartão

  • Não guarde o número completo nem o código de segurança. Quem guarda dados de cartão precisa seguir o padrão PCI DSS, que é exigente. Use a tokenização do gateway: o número vai direto para ele, e você guarda só um token.
  • Nunca registre o número do cartão em logs, nem em mensagens de erro.
  • A validação no navegador só ajuda quem digita. O pagamento é decidido pelo gateway.
  • Para mostrar o cartão salvo, use só os 4 últimos dígitos.

Achou um erro neste guia? Avise por e-mail.

Perguntas frequentes

Como validar um número de cartão de crédito?

Confira o tamanho (de 12 a 19 dígitos) e aplique o algoritmo de Luhn: dobre um dígito sim, outro não, a partir do segundo da direita, subtraia 9 dos dobros acima de 9 e veja se a soma é múltipla de 10.

Passar no Luhn quer dizer que o cartão é verdadeiro?

Não. O Luhn só mostra que o número foi digitado sem erro. Se o cartão existe e tem limite, só a operadora responde, quando o pagamento é autorizado.

Quais números de cartão usar em testes?

Os números de teste publicados pelo seu gateway de pagamento, como 4111 1111 1111 1111 para Visa. Eles passam na validação e funcionam no ambiente de testes, sem cobrar nada.

Onde mais o algoritmo de Luhn é usado?

No IMEI dos celulares e em vários números de identificação pelo mundo. A conta é sempre a mesma; muda só o tamanho do número.