Валидация номеров кредитных карт с помощью регулярных выражений

Регулярное выражение — это последовательность символов, описывающая шаблон поиска. RegEx часто применяют для поиска, валидации и преобразования текстов. В этой статье показано, как с помощью RegEx проверять номера Mastercard, Visa и American Express, а также какие дополнительные проверки стоит добавить и когда RegEx недостаточно.
Когда стоит использовать RegEx для валидации номера карты?
RegEx полезны, когда нужно оперативно отсеять явно неверные данные до обращения к платёжному шлюзу. Это экономит время пользователей и предотвращает лишние попытки транзакций, которые могут стоить денег при оплате третьей стороной (где списывают плату за каждую попытку).
Важно: RegEx проверяет только синтаксис (цифры, длину, префикс). Он не проверяет: принадлежность карты, истечение срока, код CVV или проходной ли номер (Luhn). Бренды карт периодически меняют диапазоны IIN/BIN, поэтому регулярки нужно обновлять по надёжным источникам.
Полезные сценарии RegEx:
- Предварительная валидация на клиенте (формы в браузере/мобильном приложении).
- Определение бренда карты по префиксу для показа логотипа.
- Поиск и извлечение номеров из текстовых логов (scrubbing нужно делать осторожно).
Примечание: код в примерах доступен в репозитории на GitHub под лицензией MIT (убедитесь в актуальности шаблонов перед продакшеном).
Важные термины (1‑строчные определения)
- IIN/BIN: первые 6 цифр номера карты, определяющие эмитента.
- Luhn: алгоритм контрольной суммы для проверки корректности ряда цифр.
Важно: RegEx — только часть валидации. Всегда добавляйте Luhn и серверную валидацию через платёжный шлюз.
RegEx для проверки номера Mastercard
Условия правильного номера Mastercard:
- Набор должен состоять только из цифр (без пробелов и спецсимволов).
- Длина номера — 16 цифр.
- Номер начинается либо с диапазона 51–55, либо с диапазона 2221–2720.
Объяснение двух вариантов префикса:
- Если номер начинается с 51–55 — затем идут 14 любых цифр (чтобы получить в сумме 16).
- Если номер начинается с 2221–2720 — затем идут 12 любых цифр.
Регулярное выражение, покрывающее вышеперечисленное:
^((5[1-5][0-9]{14})|(222[1-9][0-9]{12}|22[3-9][0-9]{13}|2[3-6][0-9]{14}|27[0-1][0-9]{13}|2720[0-9]{12}))$Примечание: выражение выше более явно группирует альтернативы. Альтернативный сокращённый вариант, встречающийся в примерах:
^5[1-5][0-9]{14}|^(222[1-9]|22[3-9]\d|2[3-6]\d{2}|27[0-1]\d|2720)[0-9]{12}$Пример использования в Python (с учётом корректного регулярного выражения):
import re
def check_mastercard(card_no):
regex = r"^((5[1-5][0-9]{14})|(222[1-9][0-9]{12}|22[3-9][0-9]{13}|2[3-6][0-9]{14}|27[0-1][0-9]{13}|2720[0-9]{12}))$"
return bool(re.match(regex, card_no))
card1 = "5110762060017101"
card2 = "8632458236982734"
print(card1, "->", "Valid" if check_mastercard(card1) else "Not Valid")
print(card2, "->", "Valid" if check_mastercard(card2) else "Not Valid")RegEx для проверки номера Visa
Условия для Visa:
- Только цифры, без пробелов и символов.
- Номер начинается с 4.
- Длина номера — либо 13, либо 16 цифр (старые карты — 13, современные — 16).
Регулярное выражение для Visa:
^4[0-9]{12}(?:[0-9]{3})?$Пример на Python:
import re
def check_visa(card_no):
regex = r"^4[0-9]{12}(?:[0-9]{3})?$"
return bool(re.match(regex, card_no))
card1 = "4539890694174109"
card2 = "49237429498"
print(card1, "->", "Valid" if check_visa(card1) else "Not Valid")
print(card2, "->", "Valid" if check_visa(card2) else "Not Valid")RegEx для проверки номера American Express
Условия для AmEx:
- Только цифры, без пробелов и символов.
- Длина номера — 15 цифр.
- Номер начинается с 34 или 37.
Регулярное выражение:
^3[47][0-9]{13}$Пример на Python:
import re
def check_amex(card_no):
regex = r"^3[47][0-9]{13}$"
return bool(re.match(regex, card_no))
card1 = "372831730491196"
card2 = "84732593847743042"
print(card1, "->", "Valid" if check_amex(card1) else "Not Valid")
print(card2, "->", "Valid" if check_amex(card2) else "Not Valid")Что RegEx не делает (когда он не годится)
- Не проверяет контрольную сумму (алгоритм Luhn). Номер может соответствовать формату, но быть вымышленным.
- Не проверяет срок действия карты и код CVV.
- Не гарантирует, что карта активна или поддерживается вашим процессором.
- Не заменяет серверную валидацию и проверки на стороне платёжного шлюза.
Рекомендуемая многоуровневая методика валидации карт (мини‑методология)
- Клиентская RegEx-валидация: проверка формата, длины и префикса для быстрого UX.
- Проверка Luhn на клиенте или сервере для отсева случайных наборов цифр.
- Серверная валидация с использованием платёжного шлюза (фиксация и авторизация минимальной суммы при необходимости).
- BIN/IIN lookup по API (по необходимости) для получения информации об эмитенте и типе карты.
Пример реализации Luhn в Python (для надёжной проверки)
def luhn_check(card_number: str) -> bool:
digits = [int(d) for d in card_number[::-1]]
total = 0
for i, d in enumerate(digits):
if i % 2 == 1:
doubled = d * 2
total += doubled - 9 if doubled > 9 else doubled
else:
total += d
return total % 10 == 0
print(luhn_check("5110762060017101")) # True или FalseАльтернативные подходы и рекомендации
- BIN/IIN lookup: используйте публичные или коммерческие базы для определения эмитента и страны карты.
- Платёжные API: многие платёжные провайдеры предлагают endpoint для валидации карт без проведения транзакции.
- Маскирование и хранение: номера карт нельзя хранить в открытом виде — используйте токенизацию и следуйте стандартам PCI DSS.
Быстрые эвристики и mental models
- Сначала проверьте, что строка содержит только цифры (trim и удаление пробелов/тире для удобства ввода).
- Затем проверьте длину и префикс (RegEx). Это даёт мгновенную обратную связь пользователю.
- Потом примените Luhn — это фильтр второго уровня.
- Финальная проверка — авторизация через платёжный шлюз.
Критерии приёмки
- Форма не принимает номера с буквами или спецсимволами.
- Номера проходят RegEx для соответствующего бренда и Luhn.
- Для валидного номера выполняется успешная пробная авторизация (на сервере) или получение положительного ответа от платёжного API.
Тестовые случаи и примеры для QA
- Корректный Mastercard 16 цифр, подходящий префикс, проходящий Luhn — должен принять.
- Номер с пробелами и тире — перед проверкой пробелы удаляются, затем применяются проверки.
- Номер правильной длины, но не проходящий Luhn — отклонить.
- Номер с неправильным префиксом (например, 8632…) — отклонить на уровне RegEx.
Потенциальные риски и рекомендации по смягчению
- Риск: устаревший список диапазонов IIN/BIN. Смягчение: обновляйте списки из надёжных источников или используйте коммерческие сервисы.
- Риск: утечка номеров карт. Смягчение: не логируйте полные PAN, маскируйте и используйте токены.
Пример решения: поток принятия номера (Mermaid)
flowchart TD
A[Пользователь вводит номер] --> B{Удалить пробелы и тире}
B --> C[RegEx: формат/длина/префикс]
C -->|Не прошёл| D[Показать ошибку: неверный формат]
C -->|Прошёл| E[Luhn проверка]
E -->|Не прошёл| F[Показать ошибку: неверный номер]
E -->|Прошёл| G[Серверная проверка 'платёжный шлюз']
G -->|Одобрено| H[Транзакция/токенизация]
G -->|Отклонено| I[Показать ошибку: отклонено шлюзом]Роль‑ориентированные чеклисты
- Разработчик: реализовать RegEx, Luhn, очистку ввода, покрыть тестами.
- QA: написать автоматические тесты для валидных/невалидных номеров, покрыть крайние случаи.
- Продуктовый менеджер: определить UX (сообщения об ошибках), требования безопасности и токенизации.
Краткое резюме
RegEx — быстрый способ отсеять неподходящие номера карт по формату, длине и префиксу. Обязательно комбинируйте RegEx с Luhn и серверной проверкой через платёжный шлюз. Для производственных систем используйте токенизацию и соответствуйте требованиям безопасности (PCI DSS).
Итоговые рекомендации:
- Используйте RegEx для мгновенной валидации на клиенте.
- Добавьте Luhn и серверную проверку.
- Обновляйте диапазоны IIN/BIN или применяйте коммерческие базы.
Похожие материалы
Диптихи и триптихи: Photoshop и бесплатные инструменты
Умные папки Mac — полное руководство
Делиться историями Instagram в Facebook
Устранение защиты от записи на USB-накопителе
Удаление раздела «Рекомендуемое» в Windows 11