NDA
Обучение
США
Порталы и сервисы
IOS, Android
Апрель 2024
Американский стартап решил выйти на рынок онлайн-образования с платформой для изучения иностранных языков, в которую входят сайт и мобильные приложения под iOS и Android.
На платформе регистрируются преподаватели, подтверждают свою квалификацию и предлагают услуги. Уроки проходят в виде аудио- и видеозвонков, можно заниматься индивидуально или в группе, а также участвовать в коллективных беседах. Ученики выбирают язык, цену, форму; занятия оплачиваются поурочно, допустимо поменять преподавателя.
За помощью в создании платформы заказчик обратился в Doubletapp.
Команда Doubletapp с нуля разработала и запустила сайт для пользователей и административную панель для владельцев платформы, а также мобильные приложения под iOS и Android. Функциональность сайта и приложений одинаковы, личные настройки синхронизированы.
Так как заказчик ориентируется на международную аудиторию — его интересует и американский, и европейский, и ближневосточный рынок — для изучения доступны европейские языки (английский, арабский, французский, немецкий, итальянский и испанский), а также арабский. Доступна также локализация и адаптация интерфейса платформы под эти языки.
Пользователям сайта доступны две роли — преподавателей и учеников. Преподаватель регистрируется на портале, предоставляет документы об образовании, их изучает и одобряет администратор сайта. После этого он может начинать вести уроки и получать за это деньги.
Те, кто регистрируется в качестве учеников, разделены на две категории — до 13 лет и старше. Это вызвано юридическими причинами — дети младшего возраста не могут сами заплатить за урок, поэтому зарегистрировать ребенка и проводить оплату должен ответственный взрослый.
Владелец сервиса и члены его команды взаимодействуют с преподавателями и учениками через административную панель. Это веб-приложение, с помощью которого можно мониторить поведение участников и приостанавливать участие в общении тех, кто ведет себя неэтично. Через админпанель можно также размещать на платформе статьи и новости, редактировать их и добавлять иллюстрации.
Онлайн-уроки идут в форме Chat room — групповых занятий по предварительно согласованному расписанию и Exchange room — индивидуальных встреч. Дополнительно студенты и преподаватели могут общаться в чатах, куда помимо текста можно загрузить медиаконтент или PDF-файлы.
Мы разработали два веб-приложения — сайт и административную панель. Сайт написан на React, с ним использовали Next.js для SEO-оптимизации. Язык программирования для веба — TypeScript.
Владелец платформы управляет площадкой через АДМИНИСТРАТИВНУЮ ПАНЕЛЬ.
В блог на сайте через текстовый редактор можно загружать новости и статьи, форматировать и редактировать их, добавлять иллюстрации. Мы использовали коробочное решение, но оно не позволяло полностью реализовать ТЗ, поэтому дописали собственный плагин и подобрали библиотеку, которая могла поддерживать дополнительные самописные плагины для реализации кастомных решений внутри текстового редактора.
Второй блок задач администратора — модерация: разрешение конфликтов, удаление с платформы нарушителей порядка, прием и рассмотрение заявок от преподавателей. Соискатель при регистрации указывает, что он хотел бы давать уроки, у него открывается форма для загрузки подтверждающих документов. Администратор просматривает новые заявки, выдает апрув или отказывает. В случае подтверждения заявки у преподавателя меняется статус и права доступа.
У пользователей платформы разные наборы доступных инструментов и разный вид страницы сайта — в зависимости от роли. Например, преподаватель может запустить чат-рум, а ученик — только вступить в него или выйти. Для реализации этой логики использовали паттерн attribute-based access control — он позволяет описывать возможности каждой из ролей. Все построено на том, что у нас есть конфигурация, где для каждой роли выставлено положение true, либо false, и от этого меняется внешний вид приложения и логика его работы.
ЧАТЫ могут создавать и писать и в них все пользователи сервиса. Для загрузки текста и вложений используется открытый протокол WebSocket. Он позволяет установить прямое соединение и «слушать» события, которые приходят с сервера. То есть по умолчанию мы не можем узнать, что на сервере что-то изменилось. А благодаря WebSocket у нас идет двусторонняя связь: один пользователь отправил сообщение, оно улетело на сервер, сервер уже второму клиенту спустил событие — у нас новое сообщение, и оно отобразилось.
ДЛЯ ПРОВЕДЕНИЯ ПЛАТЕЖЕЙ использовали open-source библиотеку Stripe. Это готовая платежная система, которая предоставляет свои компоненты для защиты данных и конвертации разных валют.
ОРГАНИЗАЦИЯ ВИДЕОКОНФЕРЕНЦИЙ решалась через интеграцию SDK Jitsi для React. Опенсорсное решение позволило реализовать качественную видеосвязь с необходимым по ТЗ функционалом.
Уроки на платформе — по сути видеозвонки, и заказчик вначале предлагал сделать интеграцию через Zoom. Но в этом случае нужно было решать вопрос с владельцами Zoom, заказчику это не подошло, и он предложил взять опенсорсную систему интернет-телефонии Jitsi. Сервис Jitsi для видеосвязи всех устроил, потому что он работал и с веб-приложениями на React, и с мобильными приложениями на Flutter.
Опенсорсное решение пришлось дорабатывать под нужды проекта, например, вводить ОГРАНИЧЕНИЕ ВРЕМЕНИ УРОКА. Технически пользователи Jitsi могут вести общение часами, из коробки ограничения нет, а на учебной платформе нужно ограничить время урока, так как оно оплачивается. Создатель Chat room сам указывает продолжительность встречи и выбирает время в диапазоне от 15 минут до двух часов. Для решения задачи доработали плагин Time restricted plugin: он обращается на наш бэкенд по ID встречи, а в ответе запроса приходит длительность встречи. Jitsi внутри себя обращается к нашему бэкенду, получает информацию о встрече, и, соответственно, заканчивает встречу в заданное время.
Следующая задача — ОТСЛЕЖИВАТЬ, КОГДА ЧЕЛОВЕК ВОШЕЛ НА ВСТРЕЧУ И ПОКИНУЛ ЕЕ. Плюс нужно убрать возможность для пользователя заходить одновременно на несколько встреч. В Jitsi из коробки этого также нет. Здесь использовали плагин Event Sync, он нужен, чтобы вебхук получал события от Jitsi. То есть на бэкенд приходит событие — встреча создалась, человек вошел на встречу, человек вышел из встречи, встреча завершилась. И мы на уровне бэкенда можем отслеживать, что человек, например, находится на другой встрече, поэтому он не сможет войти на вторую встречу. Или, допустим, человек уже находится на встрече, и он не сможет дважды подключиться на одну и ту же встречу. Благодаря этому плагину мы получаем эту информацию и сохраняем ее в базе данных.
Однако вебхук работает по протоколу HTTP, а события по протоколу HTTP обрабатываются не по порядку: могла возникнуть ситуация, что сначала человек вошел на встречу, а потом встреча создалась. Для решения нужно, чтобы все запросы, которые отправлял Jitsi, были синхронными. Целостности данных добились следующим образом: использовали доработанный плагин Event Sync, добавили очередь RabbitMQ: Jitsi отправляет HTTP-запрос в очередь в RabbitMQ, и события обрабатываются по порядку.
РАСПРЕДЕЛЕНИЕ РОЛЕЙ на платформе происходит с помощью JWT-токенов. Плагин, с помощью которого выдаются права модератора, называется Token Moderation. Бэкенд генерирует JWT-токен, передает этот токен на фронтенд, фронтенд передает этот токен в SDK Jitsi. Если это Flutter (мобильная версия) — то во Flutter SDK, если это React (веб-версия) — то в React SDK. И на уровне вот этого JWT-токена прописывается в пейлоаде информация о том, что конкретный пользователь — модератор, и ему даются модераторские права: удалять или добавлять пользователей на встречу.
Перейдем к РЕАЛИЗАЦИИ ОПЛАТ. Заказчик планировал использовать PayPal, но проект задумывался как международный, и есть сложности с прохождением оплат в разных странах. В итоге выбрали сервис Stripe, который агрегирует несколько способов оплаты, и ими удобно управлять. Сценарий реализации: события с вебхука Stripe поступают в очередь RabbitMQ и обрабатываются.
Выплаты преподавателям происходят 1-го числа каждого месяца: создается задача, проходит по всем преподавателям и выплачивается гонорар за прошедший месяц за вычетом услуг платформы. У преподавателей есть страничка, где они могут посмотреть список транзакций, а у владельцев платформы в Stripe — дашборд, где можно смотреть все выплаты, формировать отчет и экспортировать его в Excel.
Ученики регистрировались на платформе и оплачивали уроки через подписную модель. Мы проверили, удобно ли пользователям взаимодействовать с платформой, и для этого создали ТЕСТОВЫЕ СТЕНДЫ. Например, мы регистрировали Stripe Customer, клиента Stripe, и проводили с помощью реальных банковских карт все финансовые операции типа оплаты и подписки: человек оформил подписку, нужно, чтобы через месяц деньги списались. Приходит ли на почту ссылка для перехода и подтверждения платежа? Работает ли автоматическая отписка, если платеж не поступил в оговоренный срок? В самом Stripe есть инструментарий, который позволяет перематывать время подписки, чтобы можно было протестировать все операции.
ПРОБЛЕМА С НАГРУЗКОЙ — случай, когда участников урока окажется слишком много, решалась на сервере, где развернут Jitsi. Путем тестирования мы подобрали оптимальный объем памяти.
Для разработки мобильных приложений мы выбрали быстрые экономичные решения — Flutter: труд разработчиков стоит дорого, и быстрее в плане разработки — значит дешевле. В ограниченные сроки необходимо было разработать идентичные приложения под iOS и Android, и технология идеально подходила под эту задачу.
В отличии от web-приложений, мобильные должны проходить ревью в AppStore и Google Play. И если с Google Play не возникло никаких проблем, то с AppStore пришлось гораздо сложнее. Так как приложение очень сложное: поддерживает множество ролей, детские и родительские аккаунты, видеозвонки и чаты, ревью у Apple заняло гораздо больше времени, чем обычно. Приходилось много отвечать на их вопросы и доказывать, что приложения соответствует политикам Apple. В результате приложение было одобрено и уже доступно в обоих магазинах.
В целом работы велись по гибкой системе взаимодействия между разработчиками, зачастую одновременно и параллельно. Например, бэкенд только закончил фичу авторизации, и тут же фронтенд и мобильщики берут ее в работу.
В целом существуют две стратегии ведения проекта — Waterfall и Agile. В первом случае нужно сначала все ТЗ четко утвердить и не отступать от плана. Мы работаем по второй, более гибкой модели, потому что заказчик вносит новые пожелания, какие-то технические реализации могут быть недоступны или на ходу кто-то придумывает, что можно сделать лучше.
Разработчики отмечают, что на проекте сложилась творческая атмосфера, он всем нравился, разработчики вносили много предложений и улучшений, работали с азартом.
Сергей Анчутин
Генеральный директор (CEO)
Doubletapp сотрудничал с заказчиком в формате аутсорс. Для заказчика такой формат был удобен тем, что ему не пришлось нанимать собственную команду разработки с рынка, он получил готовых сработанных специалистов с большим опытом. Менеджмент осуществлялся тоже на нашей стороне, и заказчик не задумывался о загрузке специалистов, декомпозиции и распределении задач. Для заказчика это был дебютный проект. Он пришел к нам с идеей и набросками дизайна, и перед началом работ мы вместе переводили его идею в ТЗ, придумывали, что именно мы хотим сделать, как оно будет работать, как это можно реализовать в принципе, корректировали дизайн. По итогу совместной работы стартап получил новый раунд инвестиций на развитие платформы.
Doubletapp с удовольствием обсудит вашу задачу