Этим летом я решила создать интернет-магазин, чтобы организовать продажу моих толстовок с индивидуальным принтом. Вы можете посетить этот проект по адресу https://shopblth.com, но обратите внимание, что оформление заказа было настроено в режиме песочницы разработчика, поэтому в настоящее время в платежах будет отказано.

Содержание этого сообщения в блоге носит технический характер, поэтому может показаться немного сухим. Надеюсь, это послужит подходящим справочным руководством или хорошей отправной точкой для любых разработчиков, реализующих аналогичные проекты!

Обзор

Это полноценный проект Node.js. Служба под названием Okta используется для аутентификации пользователей. Серверная база данных обрабатывается через MongoDB, а интерфейсная часть была разработана с использованием компонентов CodyHouse Framework. Для оформления заказа используются умные кнопки PayPal. Все эти технологии подробно описаны в отдельном разделе, чтобы их было легче пропустить. Я также включил ключевые выводы из разработки этой системы с нуля.

Аутентификация пользователя Okta

Okta упрощает интеграцию учетных записей в веб-приложения и управление пользователями из их графического интерфейса. В этом проекте мне нужна аутентификация пользователя, чтобы сохранить товары из корзины покупателя в его аккаунте и упорядочить детали заказа по идентификатору покупателя. Я включил изображения того, как я интегрировал Okta в свой скрипт Node.js, и маршруты, которые я использовал для настройки своего веб-приложения. Я в основном следую этому руководству как справочнику.

Коллекции MongoDB

Чтобы понять этот раздел, важно понять иерархию элементов в MongoDB. Пары "ключ-значение" или поля можно сгруппировать в один объект, называемый документом. Несколько документов образуют собрание. Несколько коллекций образуют базу данных. У меня есть две коллекции в моей базе данных: одна коллекция клиентов и одна коллекция заказов.

Документ клиента содержит следующие поля: oktaSub, oktaName и oktaUsername. oktaSub - уникальный идентификатор, присвоенный пользователю, oktaName - полное имя зарегистрированного пользователя, а oktaUsername - адрес электронной почты пользователя. Все три поля «Клиент» имеют строковые значения.

Когда создается новый Заказ, он содержит следующие поля: oktaSub, S, M, L и openOrder. Как и раньше, oktaSub - это уникальный идентификатор пользователя. 'S', 'M' и 'L' принимают целочисленные значения, которые соответствуют количеству товаров каждого размера, которые пользователь добавил в свою корзину (S = маленький, M = средний, L = большой ). ‘OpenOrder’ имеет логическое значение и соответствует тому, был ли заказ выполнен, путем определения того, был ли окончательный заказ на покупку отправлен через PayPal.

Когда пользователь успешно отправляет платеж, в документ «Заказ» добавляются три дополнительных поля. Это поля paypalAddress, paypalArea и paypalName. «PaypalAddress» и «paypalArea» - две строки, которые при объединении образуют полный адрес доставки. Как следует из названия, «paypalName» относится к имени, зарегистрированному в учетной записи PayPal. Я включил это поле на случай, если оно отличается от «oktaName».

Новые документы клиента и заказа создаются после того, как пользователь входит в систему в первый раз. Документы нового заказа также могут быть созданы после успешного оформления заказа. Напомним, что это классифицируется по полю "openOrder", меняющему значения на "false" и добавлению трех полей "paypal".

Компоненты CodyHouse Framework

Фреймворки - это программные холсты, на которых можно разрабатывать более сложные приложения. CodyHouse Framework содержит готовые компоненты электронной коммерции со всеми необходимыми уже прикрепленными HTML, SCSS и JavaScript. В этом проекте я использую следующие компоненты, которые вы можете найти на их сайте: Продукт, Корзина, Диалог, Загрузчик заполнения, Герой, Оповещение.

Для настройки рабочей среды я следую этому руководству.

Умные кнопки PayPal

PayPal имеет обширный API для разработчиков, но самый простой способ интегрировать оплату - использовать JavaScript, представленный на сайте разработчика PayPal. Я следую их официальному руководству, связанному здесь.

К функции рендеринга кнопки PayPal привязаны две операции. Первый - «createOrder», который создает заказ на покупку, содержащий сумму транзакции. Второй - onApprove, который запускается после успешной оплаты. На этом этапе можно написать и выполнить пользовательские операции. В своем проекте я создаю невидимую форму и прикрепляю скрытые поля ввода, содержащие имя, адрес и место нахождения пользователя PayPal. Я также создаю скрытую кнопку отправки и нажимаю ее с помощью JavaScript, чтобы обработать ее в запросе AJAX. Код приведен ниже для большей ясности.

Ключевой вывод №1: умные кнопки PayPal предназначены для неизменяемых покупок.

Хотя PayPal специально об этом говорит, это предупреждение, которое я решил проигнорировать. Изначально я решил использовать умные кнопки, потому что код уже был предоставлен и его было легко интегрировать. Как показано на предыдущем изображении в разделе PayPal, при создании заказа на покупку необходимо указать стоимость транзакции. Для фиксированной цены присвоить это значение просто. Однако есть некоторые соображения безопасности при установке динамических цен.

Одна из больших проблем заключается в том, что общую сумму транзакции невозможно получить из HTML DOM. Элементы DOM можно редактировать со стороны пользователя и манипулировать ими, чтобы повлиять на окончательный промежуточный итог. Блокировщики рекламы, такие как uOrigin, используют этот метод в качестве одной из своих основных функций, поэтому намерение не всегда является злонамеренным, но все же может вызвать проблемы во время оформления заказа. Мое обходное решение состояло в том, чтобы обновлять глобальную переменную «промежуточного итога» после каждого запроса AJAX (подробнее об этом в Выводе №2, если вам интересно).

Я намеренно отложил публикацию этой статьи до тех пор, пока не отключил живые платежи, поскольку до сих пор не знаю, насколько «взломанным» является это решение. Я знаю, что это намного лучше, чем извлекать промежуточные итоги из элементов DOM, но размышления об этом по-прежнему вызывают у меня дискомфорт. Я полагаю, что правильное решение - справиться с этим беспорядком в маршруте Node.js и с помощью API разработчика PayPal.

Ключевой вывод №2: Обновление «промежуточных итогов» по ​​нажатию кнопок, а не из HTML ‹div›

Я упоминал об этом в Takeaway # 1, но общий урок, который я усвоил, заключается в том, что обновлять информацию на основе элементов DOM действительно глупо. Опять же, элементами DOM можно управлять со стороны пользователя. Значение чувствительных полей никогда не должно обновляться из элемента HTML. Обходной путь, который я использовал, заключался в отправке запроса AJAX при каждом нажатии кнопки, которое могло повлиять на серверную часть. Список всех соответствующих кнопок представлен на рисунке ниже.

Ключевой вывод №3: не обновляйте серверную часть с помощью файлов cookie браузера

Все эти выводы следуют одной и той же теме: не обновлять конфиденциальную информацию о вещах, которыми может манипулировать пользователь. Преимущество использования файлов cookie браузера заключается в том, что пользователям не требуется регистрироваться для сохранения корзины. К сожалению, файлы cookie могут быть удалены непреднамеренно, когда пользователь решит сбросить историю своего браузера. Мое обходное решение заключалось в том, чтобы требовать от пользователей входа в систему, чтобы сохранить свою корзину. Я использовал кнопки для обновления корзины пользователя с помощью запросов AJAX, как показано на рисунке в Takeaway # 2. Хотя для пользователя регистрация через Okta доставляет дополнительные хлопоты, я счел это необходимым неудобством.

Нерешенные вопросы

В этом разделе я хочу дать краткий обзор некоторых нерешенных проблем в этом проекте, которые я отложу на второй план. Я планирую прекратить использование этого проекта, но этот блог был бы неполным без отчета о некоторых нерешенных проблемах и улучшениях, которые можно было бы внести, чтобы помочь другим разработчикам.

Во-первых, одна проблема, с которой я боролся и в конечном итоге отказался от решения, - это обработка неудачных платежей PayPal. Если карта отклонена или пользователь неверно вводит свою информацию, пользователю необходимо обновить свою страницу, а не просто повторно ввести информацию. Простое повторное добавление их информации не вызовет ошибки, но приведет к «мягкой блокировке» доступа пользователя к остальной части процесса оформления заказа. Проведя небольшое исследование в Интернете, кажется, что PayPal не может запомнить ранее открытый сеанс запроса заказа после того, как пользователь не смог правильно оформить заказ.

Еще одна область улучшения может заключаться в замене промежуточного программного обеспечения «OIDC», которое я использовал для настройки Okta. Я не проводил много исследований в этой области, но считаю, что более распространенной практикой является использование Passport.js. Это даст разработчикам больше гибкости, включая возможность отправлять индивидуальные электронные письма с подтверждением после регистрации.

Заключительные замечания

За время работы над этим проектом я, вероятно, узнал о каждом компоненте полнофункционального приложения больше, чем весь мой предыдущий проект и опыт стажировки вместе взятые. Тем не менее, каждое лето я пытаюсь реализовать один из этих проектов, и мне всегда кажется, что я едва касаюсь поверхности. Я с нетерпением жду возможности использовать все, что я узнал, и развить это в своем следующем приключении. Спасибо за прочтение!