Мы в Туту 17 лет занимаемся электричками. Возможно, вы видели наше расписание ещё в детстве или студенчестве. Всё это время нас спрашивают, когда уже можно будет купить билет на интересующую электричку прямо через приложение. 17 долгих лет мы ждали наступления светлого будущего, и понадобилось закрыть на карантин полпланеты, чтобы цифровые билеты стали куда более востребованными.
Причина в том, что ещё никто не придумал, как продавать их так, чтобы:
- С одной стороны — ровно по той же цене, что в кассе;
- С другой — чтобы точно обошлось без злоупотребления типа «вижу контролёра в двух шагах — покупаю билет»;
-
Быстро, удобно и надёжно.
С третьим пунктом пока не срослось. Сейчас расскажу про то, как хитро эта схема уже работает. И скажу, что вижу все предпосылки к тому, чтобы дальше было ещё и удобно.
Давайте пройдёмся по тому, как пользователь покупает, и тому, что происходит в разных системах во время этого процесса.
Обычный хитрый путь без багов
Шаг 1: выбор билета и оплата. Тут всё довольно просто и привычно. Два наших мобильных приложения с расписанием получили кнопки «купить» для электричек ЦППК (пока только ЦППК, да, то есть большая часть московских направлений).
Цены в приложении ровно такие же, как в кассе. Мы используем те же механизмы, которые ЦППК использует для продажи билетов, это похоже на некое внутреннее техническое API. Понадобилось сделать большую обвязку вокруг всего этого, потому что готовые библиотеки и под iOS, и под андроид вели себя не на 100% стабильно. Разница между «не крэшится почти никогда» и «иногда крэшится» иногда означает создание более технологичных обёрток.
Но продолжим покупать билет:
Apple Pay и Google-кошелёк дались нам на этом проекте с трудом из-за особенностей шлюза. Эту историю лучше расскажет моя коллега позже. Изначально мы изучали возможность перебрасывать покупателя в официальное приложение ЦППК. Его разработала компания Movista, которая выиграла соответствующий тендер. После ряда экспериментов мы решили, что большая работа по интеграции всё же лучше, чем смена интерфейса при покупке.
Шаг 2: ПД. Тут нас ждёт следующий сюрприз невероятной силы: если в обычной кассе не нужно заполнять ФИО и номер паспорта, то в онлайне — нужно. Да, даже на билеты на электричку. Основание — приказ Минтранса №322.
Вот пруф:
Электронный билет на поезд пригородного сообщения без предоставления мест содержит следующую обязательную информацию о перевозке пассажира:
- железнодорожные станции (остановочные пункты) отправления и назначения;
- наименование перевозчика;
- категория поезда;
- вид билета;
- дата проезда и (или) срок действия;
- сведения о пассажире — фамилия, имя, отчество* (или инициалы), наименование, серия и номер документа, удостоверяющего личность;
- вид платежа.
3.4. При заказе электронного билета на поезд пригородного сообщения без предоставления мест пассажир указывает следующую информацию:
- железнодорожные станции (остановочные пункты) отправления и назначения;
- наименование перевозчика;
- категория поезда;
- вид билета;
- дата проезда и (или) срок действия;
- сведения о пассажире — фамилия, имя, отчество* (или инициалы), наименование, серия и номер документа, удостоверяющего личность;
- вид платежа.
Как вы можете догадаться, здесь пользователи пугаются, и мы постарались сделать всё, чтобы уменьшить их колебания. Но на бета-тестах было очень много недовольства исполнением этого приказа.
Если вы думаете, что после оплаты у вас на руках билет, то всё ещё нет. У вас на руках некий документ, который может стать билетом в момент активации на турникете на станции.
Поэтому шаг 3: пройти красный турникет. Это вообще-то лишний шаг, но это требование безопасности: нужно сначала купить билет, потом пройти через турникет:
Подходят красные турникеты (обычно их 1 или 2 на станциях ЦППК) и зелёные валидаторы. Сверху поста они есть крупно, обычно же выглядят это вот так:
Что происходит:
- Вы покупаете билет, мы создаём бронь на сервере.
- Вы оплачиваете билет, поступают данные от шлюза, что платёж успешен.
- ЦППК отправляет в телефон билет и base64-ключ, который составляет половину ключа для активации этого билета.
- Вторую половину ключа надо взять на турникете или валидаторе. Вы подходите к турникету, сканируете QR-код на нём.
- Дальше из двух половинок собирается ключ, который «открывает» билет. Вы прикладываете билет к турникету и проходите.
Важно:
- На турникете нет логики проверки QR-кода и билета вообще. Он просто показывает свои постоянно меняющиеся части ключа в виде QR-кодов с зашитыми туда метками станций.
- Не нужен интернет для соединения половинок ключа и получения билета. Всё случилось почти сразу после покупки, вы получили билет, и дальше всё делается в офлайне на телефоне внутри приложения — как его активация, так и его показ.
- Логика показа QR-кода и логика проверки билета — разные. Билет представляет собой обычный бумажный билет с точки зрения турникета — там точно такой же ключ. С точки зрения же пассажира это одно действие по поднесению телефона к турникету.
Если всё прошло хорошо, то вы получаете билет. Если всё прошло плохо (вместо турникета вы отсканировали его заботливо запасённую фотографию с другой станции), вы получаете либо невалидный билет (если вы активировали его вчерашним QR-кодом, например), либо же билет не активируется. Кстати, возможность получить невалидный билет и навела нас на мысль, что отреверсить код библиотек будет просто.
Осталась последняя задача: как контролёр сможет проверить электронный билет? Ведь он визуально не отличается от скриншота точно такого же билета! Оказывается, ЦППК нашла решение, близкое к гениальному: нужно открыть билет в приложении и тапнуть по нему. Активированный билет начнёт вращаться. Предполагается, что это надёжно защищает большинство населения от подделок в Фотошопе.
Повторную активацию мы добавили на тот случай, если вы выходите на станции по пути.
А теперь перейдём к сладкому — багам!
Красный турникет может не открыться. Просто взять и не открыться. Потому что что-то в его турникетных мозгах не сработает вовремя. Например, защита, которая не даёт вам пройти по одному и тому же QR-коду в два турникета сразу. Вероятность очень маленькая, но есть. В этом случае к вам подойдёт усталый дедушка, который дежурит по станции. Он такое повидал уже сотни раз и знает, что означает замешкавшийся человек у красного турникета. Проверит билет в приложении («Крутится? Крутится!») И спокойно вас пропустит.
Зелёный валидатор на платформе может не работать. Это Россия, а не Япония, поэтому у нас это может длиться и дольше 3 минут суммарно за год. В этом случае надо подойти к другому валидатору, а он на другой платформе. Вероятность тоже очень низкая, но есть. Обычный человек вряд ли встретится с такой ситуацией, но мы долго и остервенело тестировали, поэтому знаем.
Если вы отсканили QR-код на красном турникете в момент смены потока (когда вам говорят: «Идите на другой, тут люди с поезда выходят») — надо идти ровно через этот, иначе вы стриггерите тот самый код, который отвечает за то, чтобы по одному билету вы прошли не через все турникеты сразу. Соседний синхронизируется не сразу. Это означает или полминуты задержки, или же проверку билета дедушкой-дежурным. «Крутится? Крутится!».
Небольшой FAQ
— Можно ли купить электронный билет на электричку из метро?
Можно. Мы для того и сделали, чтобы вы покупали на эскалаторе.
— Если связь оборвётся после активации билета, билет останется?
Да. И будет крутиться.
— Нужен ли интернет, когда активируется билет на турникете?
Нет, всё происходит в офлайне внутри софта вашего телефона. Билет у вас уже есть, он просто расшифровывается.
— Если я вижу контролёра, поздняк метаться с покупкой электронного билета, да?
Да, если у вас нет под рукой QR-кода с ближайшей станции. И, зная наш менталитет, это не так чтобы полностью сарказм.
— Ха, а если я его сфотографировал утром при проходе через турникет?
Регулярно меняется в пределах нескольких минут.
— А если я понял закономерность этого кода?
Алгоритм кодирования меняется в полночь, и коды начинают отличаться от предыдущих очень резко.
— Если я активирую билет неправильным QR-кодом, то что?
То у вас будет невалидный билет. Либо билет на неправильную дату.
— Сколько действует электронный билет?
После активации билет действует до 03:00 следующих суток. То есть можно отсканировать его на турникете в 7 утра и использовать в 21. Никаких проблем.
— Что, если я сажусь на электричку в 00:01?
На стыке дат есть гейзенбаг в системе проверки билетов (бумажных тоже, то есть далеко не в нашем стеке), когда турникеты могут не среагировать на вчерашний билет. Обработка обычная — нужно будет позвать дежурного по турникетам, который посмотрит на крутящийся билет и пропустит.
— А если я прошёл турникет в 2:59?
Если за ту секунду, что прошли между активацией билета и проходом в турникет, кончились технические сутки, решать вопрос тоже надо через дедушку. Он всё стерпит.
Другие билеты
Мы ведём переговоры с другими перевозчиками по поводу продажи билетов по тем же ценам, что в кассе. По многим направлениям нет таких сложностей с активацией билета, например, на большинстве поездов Ленинградского можно покупать билет внутри поезда. Естественно, это создаёт известную уязвимость, и нужно найти некий компромисс, который всех устроит. Но, боюсь, это скорее область работы с обществом, нежели разработки. Хотя если есть идеи — мы будем рады их воплотить.
Автор: Андрей Мацуленко