Алгоритм Луна: як перевірити номер картки у формі
Алгоритм Луна (Luhn algorithm) — це контрольна математична перевірка, яку часто застосовують для виявлення помилок у введеному номері платіжної картки.
Важливо: успішна перевірка Luhn не підтверджує, що картка існує, активна або може виконати платіж. Вона лише перевіряє структуру номера й контрольну цифру. Реальну перевірку виконують платіжний шлюз і банк.
Як працює алгоритм
- Беремо цифри номера справа наліво.
- Починаючи з передостанньої цифри, подвоюємо кожну другу цифру.
- Якщо результат більший за 9, віднімаємо 9.
- Додаємо змінені та незмінені цифри.
- Якщо сума ділиться на 10 без остачі, номер проходить перевірку.
Приклад
Для номера 4441114449324050 після обробки цифр отримуємо суму 70. Оскільки 70 % 10 = 0, номер проходить перевірку Luhn.
Перевірка у полі картки
- Запускайте перевірку на
inputабо після втрати фокусу черезblur. - Перед перевіркою видаляйте пробіли й дефіси.
- Показуйте помилку лише після введення достатньої кількості цифр, наприклад 13–19.
- Не надсилайте номер картки на власний сервер без потреби та не зберігайте його в логах.
- Для платежів використовуйте PCI DSS-сумісний платіжний шлюз і токенізацію.
JavaScript
function isValidCardNumber(value) {
const num = value.replace(/\D/g, '');
if (num.length < 13 || num.length > 19) return false;
let sum = 0;
let shouldDouble = false;
for (let i = num.length - 1; i >= 0; i--) {
let digit = Number(num[i]);
if (shouldDouble) {
digit *= 2;
if (digit > 9) digit -= 9;
}
sum += digit;
shouldDouble = !shouldDouble;
}
return sum % 10 === 0;
}
PHP
function isValidCardNumber(string $value): bool {
$num = preg_replace('/\D/', '', $value);
if (strlen($num) < 13 || strlen($num) > 19) {
return false;
}
$sum = 0;
$shouldDouble = false;
for ($i = strlen($num) - 1; $i >= 0; $i--) {
$digit = (int) $num[$i];
if ($shouldDouble) {
$digit *= 2;
if ($digit > 9) $digit -= 9;
}
$sum += $digit;
$shouldDouble = !$shouldDouble;
}
return $sum % 10 === 0;
}
Python
def is_valid_card_number(value: str) -> bool:
num = ''.join(ch for ch in value if ch.isdigit())
if not 13 <= len(num) <= 19:
return False
total = 0
should_double = False
for ch in reversed(num):
digit = int(ch)
if should_double:
digit *= 2
if digit > 9:
digit -= 9
total += digit
should_double = not should_double
return total % 10 == 0
Rust
pub fn is_valid_card_number(value: &str) -> bool {
let digits: Vec<u32> = value
.chars()
.filter_map(|c| c.to_digit(10))
.collect();
if !(13..=19).contains(&digits.len()) {
return false;
}
let mut sum = 0;
let mut should_double = false;
for mut digit in digits.iter().rev().copied() {
if should_double {
digit *= 2;
if digit > 9 { digit -= 9; }
}
sum += digit;
should_double = !should_double;
}
sum % 10 == 0
}
Висновок
Luhn — це швидкий спосіб відсіяти помилки введення на клієнті до відправлення форми. Але це лише синтаксична перевірка, а не авторизація платежу: остаточний результат завжди повертає платіжний провайдер.
Коментарі (0)