Валидация кредитных карт: алгоритм Луна
Алгоритм Луна, проверка номеров карт, определение типа карты (Visa, MC, Amex), безопасность.
Посчитайте прямо здесь: Card Number → Validation Result
Открыть инструмент целиком →Введение
При вводе номера карты в интернет-магазине вы наверняка замечали: опечатка в одной цифре почти сразу подсвечивается красным. Как сайт понимает, что номер неверен, ещё до обращения в банк? Ответ — алгоритм Луна. Это простая математическая проверка, которая отсеивает большинство случайных ошибок ввода. В статье разберём, как устроен алгоритм, как по номеру определить тип карты и какие ограничения важно учитывать. Проверить карту можно в нашемвалидаторе кредитных карт.
Что такое алгоритм Луна
Алгоритм Луна разработан инженером IBM Хансом Питером Луном в 1954 году. Это контрольная сумма, которая обнаруживает любую одиночную ошибку в цифре номера, а также большинство перестановок соседних цифр (например, когда пользователь случайно набрал «32» вместо «23»).
Алгоритм не гарантирует, что карта реальна — он лишь проверяет, что номер мог быть выдан банком. Однако этого достаточно, чтобы отсеять опечатки ещё до запроса к платёжному шлюзу.
Как работает алгоритм
Шаги вычисления контрольной суммы по Луну:
- Отбросить пробелы и нецифровые символы.
- Начать с последней цифры и двигаться влево.
- Каждую вторую цифру (счёт с конца, начиная с предпоследней) умножить на 2.
- Если результат умножения больше 9, вычесть из него 9 (или сложить цифры результата).
- Сложить все полученные цифры.
- Если сумма делится на 10 без остатка — номер валиден.
Пример для номера 4539 1488 0343 6467
Номер: 4 5 3 9 1 4 8 8 0 3 4 3 6 4 6 7
Удвоить (x2): 8 6 2 8 0 8 8 8
↓1+8=9
Цифры: 8 5 6 9 2 4 7 8 0 3 8 3 3 4 3 7
Сумма = 8+5+6+9+2+4+7+8+0+3+8+3+3+4+3+7 = 80
80 mod 10 = 0 → номер валиденРеализация алгоритма
JavaScript
function luhnCheck(cardNumber) {
// Убираем всё, кроме цифр
const digits = String(cardNumber).replace(/\D/g, '');
if (digits.length < 13 || digits.length > 19) {
return false;
}
let sum = 0;
let shouldDouble = false;
// Идём справа налево
for (let i = digits.length - 1; i >= 0; i--) {
let digit = parseInt(digits[i], 10);
if (shouldDouble) {
digit *= 2;
if (digit > 9) digit -= 9;
}
sum += digit;
shouldDouble = !shouldDouble;
}
return sum % 10 === 0;
}
luhnCheck('4539148803436467'); // true
luhnCheck('4539148803436460'); // falsePython
def luhn_check(card_number: str) -> bool:
digits = [int(c) for c in str(card_number) if c.isdigit()]
if not 13 <= len(digits) <= 19:
return False
total = 0
should_double = False
for digit in reversed(digits):
if should_double:
digit *= 2
if digit > 9:
digit -= 9
total += digit
should_double = not should_double
return total % 10 == 0
print(luhn_check('4539148803436467')) # TrueGo
package main
import (
"fmt"
"unicode"
)
func luhnCheck(cardNumber string) bool {
var digits []int
for _, r := range cardNumber {
if unicode.IsDigit(r) {
digits = append(digits, int(r-'0'))
}
}
if len(digits) < 13 || len(digits) > 19 {
return false
}
sum := 0
shouldDouble := false
for i := len(digits) - 1; i >= 0; i-- {
d := digits[i]
if shouldDouble {
d *= 2
if d > 9 { d -= 9 }
}
sum += d
shouldDouble = !shouldDouble
}
return sum%10 == 0
}
func main() {
fmt.Println(luhnCheck("4539148803436467")) // true
}Определение типа карты по BIN
Первые 6–8 цифр номера карты — это BIN (Bank Identification Number), или IIN. По ним можно определить платёжную систему, банк-эмитент, тип карты (дебетовая или кредитная) и страну. Платёжная система определяется по первым цифрам:
| Платёжная система | Начальные цифры | Длина |
|---|---|---|
| Visa | 4 | 13, 16, 19 |
| Mastercard | 51–55, 2221–2720 | 16 |
| American Express | 34, 37 | 15 |
| Discover | 6011, 622126–622925, 644–649, 65 | 16, 19 |
| МИР | 2200–2204 | 16–19 |
| JCB | 3528–3589 | 16–19 |
| Diners Club | 300–305, 3095, 36, 38, 39 | 14–19 |
Пример определения платёжной системы
function detectCardType(number) {
const n = number.replace(/\D/g, '');
if (/^4/.test(n)) return 'visa';
if (/^(5[1-5]|2(2[2-9]|[3-6]\d|7[01]|720))/.test(n)) return 'mastercard';
if (/^3[47]/.test(n)) return 'amex';
if (/^(6011|65|64[4-9])/.test(n)) return 'discover';
if (/^220[0-4]/.test(n)) return 'mir';
if (/^3(?:0[0-5]|095)/.test(n)) return 'diners';
if (/^(?:352[89]|35[3-8]\d)/.test(n)) return 'jcb';
return 'unknown';
}Что алгоритм НЕ проверяет
Лун-проверка ловит случайные опечатки, но не гарантирует, что карта:
- Реально существует. Можно придумать число, удовлетворяющее формуле Луна, но не привязанное ни к какому счёту.
- Активна. Срок действия и статус карты можно проверить только через платёжный шлюз.
- Имеет средства. Баланс и лимиты — также за пределами алгоритма.
- Не украдена. Проверка по базам украденных карт — отдельная процедура.
Поэтому валидация по Луну — это лишь первая линия обороны. После неё следует проверка срока действия, CVV и, при необходимости, 3-D Secure.
Практическое применение
В веб-формах
Валидация по Луну подключается на этапе ввода. Когда пользователь набирает номер, клиентский JavaScript проверяет сумму и подсвечивает поле, если она не сходится. Это снижает количество ошибочных отправок формы.
В платёжных шлюзах
Серверная проверка также обязательна. Даже если клиентский скрипт пропустил ошибку, шлюз не отправит запрос в банк с невалидным номером — это экономит комиссию за попытку.
В системах учёта
Алгоритм Луна применяют не только для карт. Им нумеруют:
- IMEI телефонов.
- Национальные идентификаторы поставщиков (GS1).
- Номера социального страхования (в некоторых странах).
- Штрих-коды SimCards.
Ограничения
У алгоритма есть несколько ограничений:
- Он не ловит перестановку вида «09 ↔ 90» — обе эти пары дают одинаковый вклад в сумму.
- Он не защищает от подделки — формула публичная.
- Он не проверяет срок действия, имя владельца и CVV.
- Некоторые карты могут иметь нестандартную длину, что усложняет проверки.
Безопасность при работе с номерами карт
- Не храните PAN. Если бизнес-требования не требуют хранения полного номера — не храните его.
- Используйте токенизацию. Многие шлюзы возвращают токен вместо PAN — работайте с ним.
- Маскируйте номер. В логах и UI показывайте только последние 4 цифры:
**** **** **** 6467. - Шифруйте при передаче. Только HTTPS, никакой передачи PAN в URL.
- Соответствуйте PCI DSS. Если вы обрабатываете карты — сертификация обязательна.
- Не логируйте CVV. Это запрещено стандартом PCI DSS.
Регулярные выражения для валидации
Часто валидация номера карты объединяет проверку длины и платёжной системы в одно регулярное выражение:
const CARD_PATTERNS = {
visa: /^4[0-9]{12}(?:[0-9]{3})?(?:[0-9]{3})?$/,
mastercard: /^(5[1-5][0-9]{14}|2(2[2-9][0-9]{12}|[3-6][0-9]{13}|7[01][0-9]{12}|720[0-9]{12}))$/,
amex: /^3[47][0-9]{13}$/,
discover: /^6(?:011|5[0-9]{2})[0-9]{12}$/,
mir: /^220[0-4][0-9]{12,15}$/,
};
function validateCard(number, type) {
const clean = number.replace(/\D/g, '');
const pattern = CARD_PATTERNS[type];
return pattern ? pattern.test(clean) && luhnCheck(clean) : luhnCheck(clean);
}Расчёт контрольной цифры по шагам
Соберём номер целиком на классическом примере 7992739871 — найдём его контрольную цифру. Записываем цифры справа налево и удваиваем каждую вторую: если произведение больше девяти, вычитаем из него девять (это то же самое, что сложить цифры произведения: 16 → 1 + 6 = 7).
| Цифра (справа налево) | Позиция | Действие | Вклад в сумму |
|---|---|---|---|
| 1 | 2-я | 1 × 2 = 2 | 2 |
| 7 | 3-я | без изменений | 7 |
| 8 | 4-я | 8 × 2 = 16 → 7 | 7 |
| 9 | 5-я | без изменений | 9 |
| 3 | 6-я | 3 × 2 = 6 | 6 |
| 7 | 7-я | без изменений | 7 |
| 2 | 8-я | 2 × 2 = 4 | 4 |
| 9 | 9-я | без изменений | 9 |
| 9 | 10-я | 9 × 2 = 18 → 9 | 9 |
| 7 | 11-я | без изменений | 7 |
Сумма вкладов — 67. Контрольная цифра дополняет сумму до ближайшего кратного десяти: 70 − 67 = 3. Полный номер 79927398713 проходит проверку: при суммировании уже с контрольной цифрой получится ровно 70, а 70 делится на десять без остатка. Если бы сумма была 68, контрольной стала бы 2 — дополнение всегда одно, от нуля до девяти.
Частые вопросы
Что даёт алгоритм Луна и что он не может?
Он ловит опечатки: одиночную ошибку в цифре и почти все перестановки соседних цифр — это его единственная задача. Номер 4539…6467 и 4539…6463 различаются одной цифрой, и Луна это заметит. Зато он ничего не знает о существовании карты: номер, который прошёл проверку, может быть давно закрыт, не выпущен или придуман. Для реальной проверки карты нужен запрос в платёжную систему.
Как проверить номер карты алгоритмом Луна вручную?
За минуту: запишите цифры справа налево, удвойте каждую вторую, большие произведения приведите к цифре (16 → 7), сложите всё вместе с неподудвоенными. Итог делится на десять — номер корректен. Наш калькулятор карт делает то же самое мгновенно и сразу показывает, на каком шаге сумма перестала сходиться.
Почему карта проходит Луна, но не работает?
Потому что Луна проверяет только арифметику записи. Карта может не работать из-за истёкшего срока, блокировки, нулевого лимита или того, что номер вообще выдан не был — при этом проверку контрольной цифры он проходит. Обратный случай тоже бывает: опечатка в двух цифрах (9 ↔ 6) иногда сохраняет контрольную сумму, и мёртвый номер выглядит живым.
Где ещё используется алгоритм Луна, кроме банковских карт?
Идея «контрольная цифра ловит опечатки» работает везде, где номер набирают руками: IMEI телефонов, номера соцстрахования в Канаде и США, идентификаторы в медицине, штрих-коды EAN. Формула везде та же, отличается позиция удваиваемых цифр и модуль сравнения.
Заключение
Алгоритм Луна — простой, но эффективный способ отсеять опечатки в номере карты до обращения к платёжной системе. Он не заменяет полноценную проверку через шлюз, но существенно снижает количество ошибочных запросов и улучшает пользовательский опыт. Если вы разрабатываете форму оплаты или обрабатываете идентификаторы с контрольной суммой — Лун будет полезен. Проверить любой номер карты можно в нашем валидаторе кредитных карт.
Попробуйте эти инструменты
Похожие статьи
Как создать надёжный пароль: генератор паролей
Правила создания паролей, длина, символы, энтропия, менеджеры паролей, двухфакторная аутентификация.
MD5 хеш: что это и безопасно ли использовать
Алгоритм MD5, хеширование, коллизии, почему MD5 не для паролей, где ещё можно использовать.
SHA-256 — что это такое простыми словами: как работает и где применяется
SHA-256 — что это за хеш простыми словами: как работает алгоритм, где применяется (биткоин, SSL, подписи), чем отличается от MD5 и SHA-1.
UUID — что это такое: версии, GUID и чем они отличаются
UUID — что это такое простыми словами: устройство идентификатора, версии v4 и v7, чем GUID отличается от UUID и где идентификаторы используются.