Наивная проверка номера карты выглядит обманчиво просто: взять строку и посчитать контрольную сумму. На практике так делать нельзя, потому что проверка номера карты — это последовательность шагов, и порядок этих шагов определяет, получит ли пользователь понятную подсказку или столкнётся с таинственной ошибкой. Ниже — что именно защищает такая проверка, в каком порядке выполнять её шаги, какие сообщения показывать человеку и какие места в реализации ломаются чаще всего.
Что проверка ловит, а что нет
Проверка номера не имеет отношения к деньгам на счёте. Она решает одну задачу: отсеять данные, которые заведомо не могут быть номером карты, до того как они уйдут на сервер и тем более к поставщику платежей.
Границы этой задачи стоит держать в голове постоянно. Проверка не подтверждает, что счёт существует, что карта не заблокирована и что операция пройдёт. Всё это выясняется только запросом к банку. Зато она отлично отсеивает опечатки, лишние символы и случайно вставленный текст — то есть основную массу ошибок ввода.
В каком порядке выполнять проверки?
Порядок не произвольный: каждый следующий шаг предполагает, что предыдущий уже пройден.
- Очистка. Оставьте только цифры, убрав пробелы, дефисы, точки и невидимые символы, которые попадают в строку при копировании из таблиц и мессенджеров.
- Алфавит. Убедитесь, что буквы и знаки не просочились: если после очистки осталось что-то кроме цифр, это ошибка формата, и её нужно назвать отдельно.
- Длина. Сверьте количество цифр с допустимым для заявленной платёжной системы. Помните, что шестнадцать — не единственный законный вариант.
- Диапазон. Проверьте, что начало номера принадлежит известной платёжной системе. Неизвестное начало — это не «неверный номер», а «мы не поддерживаем такую карту», и это разные сообщения.
- Контрольная цифра. Только в самом конце считайте сумму по алгоритму Луна.
Контрольная сумма стоит последней не случайно. Она ничего не знает ни о длине, ни о диапазонах, поэтому, если поставить её первой, вы будете сообщать пользователю о несоответствии суммы там, где на самом деле неверна длина. Подробнее об этом правиле — в разборе алгоритма Луна.
Что писать пользователю при ошибке
Сообщение об ошибке — часть продукта, а не техническая деталь. Человек, который ошибся на одну цифру, должен понять, что делать дальше, а не перебирать варианты наугад.
- Опечатка в цифрах. «Проверьте номер карты» — без указания, какая именно цифра неверна.
- Неправильная длина. «Похоже, номер введён не полностью» или «в номере лишние цифры».
- Незнакомое начало. «Такую платёжную систему мы не принимаем» — это честнее, чем «неверный номер».
- Посторонние символы. «В номере карты допустимы только цифры».
- Пустое поле. «Введите номер карты», а не то же сообщение, что для неверной суммы.
Отдельное правило: не показывайте пользователю, прошла ли проверка контрольной суммы. Это подсказка для того, кто подбирает данные, и никакой пользы обычному человеку она не несёт.
Какие дефекты встречаются чаще всего
Список типовых ошибок короткий, но повторяется он из проекта в проект.
- Единственная проверка — контрольная сумма. Такой код пропускает строку, которая случайно сошлась по сумме, но не подходит по длине или началу.
- Жёсткая длина. Реализация помнит только про шестнадцать цифр и отвергает всё остальное, включая законные пятнадцатизначные номера.
- Проверка на пустую строку после других шагов. Пользователь оставил поле пустым, а ему сообщают о неверной контрольной цифре — потому что пустая строка успешно прошла очистку и попала дальше.
- Разные правила в браузере и на сервере. Форма пропускает данные, а сервер их отвергает, и человек видит необъяснимый отказ после нажатия кнопки.
- Обрезка ввода по маске. Поле само дописывает разделители и молча отбрасывает последнюю цифру: пользователь уверен, что ввёл всё, а система видит неполный номер.
- Зависимость от пробелов. Код сравнивает начало номера со строкой, в которой есть пробел, и перестаёт узнавать карты, если данные пришли без разделителей.
Каждый из этих дефектов легко ловится одним тестом, если тест проверяет не только результат, но и причину отказа. Разбор конкретных наборов значений для таких проверок стоит вести отдельно, а не смешивать с рабочими данными.
Как выглядит набор проверочных случаев?
Удобно свести проверки в таблицу, где каждая строка ломает ровно один шаг. Тогда дефект сразу видно по тому, какая причина отказа вернулась.
| Что подаём | Чего ожидаем |
|---|---|
| Пустое поле | Сообщение о необходимости заполнить поле |
| Буквы вместо цифр | Ошибка формата, а не ошибка длины |
| Слишком короткая строка цифр | Сообщение о неполном номере |
| Строка с лишней цифрой | Сообщение о лишних цифрах |
| Неизвестное начало | Отдельная причина: система не поддерживается |
| Цифры с пробелами и дефисами | Успешная очистка и проход проверки |
| Значение с ведущим нулём | Ведущий ноль сохраняется при обработке |
| Строка, испорченная на одну цифру | Сообщение о необходимости проверить номер |
Такой набор полезно прогонять целиком при каждом изменении правил: он недорогой, а ловит регрессии раньше, чем они попадут к пользователям.
Можно ли проверять только в браузере
Нет. Проверка в браузере существует для удобства: чтобы человек получил подсказку сразу, не дожидаясь ответа сервера. Но она не является защитой, потому что её легко обойти, а данные в систему попадают не только через форму: их присылают мобильные приложения, интеграции, импорт из файлов и старые версии клиентов, которые кто-то ещё не обновил.
Полноценная проверка всегда дублируется на сервере. Если правило живёт в двух местах, оно неизбежно разъедется — поэтому логику стоит описать один раз и держать в одном источнике, а не переписывать заново для каждого клиента.
Что важно разработчику
Главная ловушка — числовое преобразование. Длинную строку цифр нельзя переводить в число: в языках с плавающей точкой теряются младшие разряды, а ведущие нули исчезают при любом преобразовании. Номер обрабатывается как последовательность символов, а не как значение. Тесты на этом месте должны включать строку с ведущим нулём и очень длинную строку.
Вторая ловушка — доверие к формату отображения. Если интерфейс показывает номер группами по четыре цифры, сервер может получить пробелы и дефисы, если очистка сделана только на клиенте. Очищайте данные повторно на входе, даже если кажется, что клиент уже всё сделал.
Третья ловушка — сообщения об ошибках в виде кодов. Пользователь не должен видеть внутренние обозначения, но разработчику они нужны: полезно возвращать и понятный текст, и машинный код причины, чтобы аналитика показывала, каких именно ошибок больше.
Четвёртая — тестовые данные. Для проверки порядка шагов нужны значения, которые ломаются ровно на одном шаге каждое: только по длине, только по началу, только по контрольной цифре. Подходящий набор выдаёт генератор: его номера структурно корректны, но никогда не выпускались ни одним банком и не принадлежат никому, поэтому ими безопасно наполнять тесты. И последнее: если правило проверки меняется — например, вы начинаете принимать новую платёжную систему, — прогоните весь набор тестов заново, а не только новый сценарий.
Что делать дальше
Выпишите шаги проверки в том порядке, в котором они должны выполняться, и сверьте с текущей реализацией: если контрольная сумма считается до проверки длины, у вас есть дефект, который стоит исправить. Затем проверьте, что каждое сообщение об ошибке понятно человеку без технического образования. Оставшиеся сценарии — отказ, повторная попытка, возврат — собраны в чек-листе платёжной формы, а устройство самого номера разобрано в материале про формат карты.