Приложения для электронной коммерции являются основой современного мира онлайн-покупок. В этом посте мы увидим, как легко создать приложение для электронной коммерции с помощью Java, JHipster, Spring Boot и React. Поскольку мы будем создавать приложение, в этом посте основное внимание будет уделено созданию корзины покупок и интеграции платежей, а не созданию веб-приложения Java.
Инструменты и технологии, которые мы будем использовать
Мы будем использовать приведенные ниже инструменты и технологии для создания этого приложения:
JHipster : JHipster – это платформа для быстрой разработки приложений. Он может быстро создавать веб-приложения и микросервисы с помощью производственного кода. Перейдите к инструкции по установке , чтобы настроить его. Hipster может создавать приложения с широким спектром языков, фреймворков и конфигураций. В этом уроке мы будем придерживаться следующих основных опций. Для этого вам не нужно ничего устанавливать, так как Hipster справится с этим за вас.
- SpringFramework : Spring – это платформа приложений на Java, которая поставляется со всеми прибамбасами и прибамбасами, необходимыми для разработки приложений Java корпоративного уровня. Он поставляется с пружинным загрузчиком, который делает разработку более быстрой и удобной. Это позволяет нам больше сосредоточиться на наших бизнес-потребностях, а не тратить время на настройку технических интеграций.
- React : Популярная библиотека пользовательского интерфейса JavaScript, которая помогает создавать современные масштабируемые интерфейсы. Мы будем писать код React с использованием TypeScript. Мы также будем использовать несколько других компонентов, таких как Redux и React Router из экосистемы React.
- Bootstrap : Платформа пользовательского интерфейса для веб-приложений с различными темами и настройками.
- Gradle : Gradle – это инструмент оркестровки сборки Java, который предоставляет настраиваемый и простой в использовании язык для конкретной области (DSL).
- Веб-пакет : Инструмент для создания интерфейсов для современных веб-приложений
- Платежная платформа Adyen : Adyen является одной из ведущих платежных платформ для среднего и крупного бизнеса. Он предоставляет множество вариантов оплаты и предоставляет SDK для легкой интеграции. И так уж получилось, что я тоже работаю на Адьена 😄
- Docker : Технология контейнеризации, которую мы будем использовать для быстрого запуска нашей базы данных. Убедитесь, что у вас установлены Docker и Docker compose. Если вы можете запустить локальную установку MySQL, вам не понадобится Docker.
- Git : Распределенная система контроля версий для управления исходным кодом. Убедитесь, что у вас установлен Git.
Предпосылка
Чтобы эффективно следовать этому руководству, вам необходимо быть знакомым, по крайней мере, с приведенными ниже инструментами и технологиями
- Ява
- Пружинный Каркас
- Реагировать
- Возвращение
- Начальная загрузка
У нас есть образец приложения , созданный для сопровождения этого поста. Каждый раздел здесь указывает на конкретную фиксацию в примере приложения, чтобы помочь вам лучше понять, что меняется.
Разработка модели сущности
Поскольку мы собираемся создать каркас вашего приложения, важно убедиться, что у нас есть правильная модель сущности для приложения электронной коммерции. Мы будем использовать язык домена Hipster(JDL) чтобы сделать это. Ниже приведена модель JDL для приложения электронной коммерции:
/** Product sold by the Online store */ entity Product { name String required description String price BigDecimal required min(0) size Size required image ImageBlob } enum Size { S, M, L, XL, XXL } /** Product categories to group products */ entity ProductCategory { name String required description String } /** Additional details for users as we can't modify built-in user entity vis JDL */ entity CustomerDetails { gender Gender required phone String required addressLine1 String required addressLine2 String city String required country String required } enum Gender { MALE, FEMALE, OTHER } /** Shopping cart to hold users orders */ entity ShoppingCart { placedDate Instant required status OrderStatus required totalPrice BigDecimal required min(0) paymentMethod PaymentMethod required } enum OrderStatus { COMPLETED, PAID, PENDING, CANCELLED } enum PaymentMethod { CREDIT_CARD, IDEAL } /** Product order keeps track of orders */ entity ProductOrder { quantity Integer required min(0) totalPrice BigDecimal required min(0) } // Every user will have a customer detail relationship OneToOne { CustomerDetails{user(login) required} to User } // Many product orders can be tracked back to a product relationship ManyToOne { ProductOrder{product(name) required} to Product } relationship OneToMany { // Every customer can have many shopping carts CustomerDetails{cart} to ShoppingCart{customerDetails required}, // Every shopping cart can have many product orders ShoppingCart{order} to ProductOrder{cart required}, // Every product category can have many products ProductCategory{product} to Product{productCategory(name) required} } service * with serviceClass paginate Product, CustomerDetails, ProductCategory with pagination
Сущность User
встроена в Hipster, и поэтому нам не нужно определять ее в JDL. Однако мы можем определить их отношения. Вот визуализация UML того же самого:
Перейдите на страницу JDLStudio , если вы хотите визуализировать модель и внести какие-либо изменения.
Затем создайте новую папку и сохраните вышеизложенное в файл с именем app.jdl
в этой папке.
Строительные леса для приложения
Теперь, когда у нас есть наша модель, мы можем продолжить и создать веб-приложение Java с помощью JHipster. Во-первых, давайте определим наше приложение. Добавьте приведенный ниже фрагмент в файл ( app.jdl
), который мы создали ранее.
application { config { baseName store packageName com.adyen.demo.store authenticationType jwt prodDatabaseType mysql buildTool gradle clientFramework react useSass true enableTranslation false } entities * }
Мы только что определили приложение с именем магазин , которое использует JSON Web Токен (JWT) в качестве механизма аутентификации, MySQL в качестве производственной базы данных, Gradle в качестве инструмента сборки и React в качестве клиентской платформы. Вы можете увидеть все опции, поддерживаемые Hipster здесь . Мы также определили, что приложение использует все сущности, которые мы определили с помощью сущностей *
.
Теперь давайте вызовем Hipster для создания приложения. Выполните приведенную ниже команду внутри папки, в которой мы создали app.jdl
:
jhipster import-jdl app.jdl
Это позволит создать наше приложение, установить все необходимые зависимости, а также инициализировать и зафиксировать все в Git. Убедитесь, что в вашей системе установлен Git.
Давайте проверим приложение. Выполните приведенную ниже команду, чтобы запустить приложение в режиме разработки:
./gradlew
После запуска приложения посетите https://localhost:8080 и используйте пользователей по умолчанию, указанных на главной странице, для входа в систему и изучения приложения. Вы можете найти фиксацию в примере приложения.
Вы также можете запустить сгенерированные модульные и интеграционные тесты с помощью этой команды:
./gradlew npm_test test integrationTest
До сих пор сгенерированное приложение не имеет какой-либо конкретной бизнес-логики или пользовательских экранов. Это просто грубое приложение для модели, которую мы определили. Если вы знакомы с Spring Framework и React, вы должны легко ориентироваться в созданном исходном коде. Приложение Spring/React, созданное Hipster, не является предметом этого поста, и для этого я рекомендую вам ознакомиться с документацией, предоставленной JHipster, Spring и React.
Создание целевой страницы продуктов
Теперь, когда наше приложение и все API CRUD готовы, давайте создадим целевую страницу продукта, на которой перечислены все товары, предлагаемые магазином.
Мы преобразуем src/main/webapp/приложение/модули/главная/главная.задачи
в целевую страницу нашего продукта. Это включает в себя обновление JSX для отображения списка продуктов и использование редуктора product redux для извлечения данных из API продукта. Здесь полная разница для главная страница.tsx
и здесь приведен весь список изменений для этого шага.
Запустите приложение на стороне клиента в режиме разработки, чтобы ускорить разработку. Продолжайте запускать приложение в терминале, используя ./gradlew
если он еще не запущен с предыдущего шага. В новом терминале запустите запуск npm
и он запустит сервер разработки для клиентской стороны, который вызывает ПРОКСИ-API для серверной части и откроет новое окно браузера, указывающее на https://localhost:9000 .
На данный момент интерфейс и серверная часть работают в режиме разработки с функцией горячей перезагрузки. Это означает, что все приложение автоматически перезагрузится, когда мы внесем какие-либо изменения (браузер также перезагрузится). Для изменений в бэкэнде перезагрузка произойдет при компиляции с использованием вашей ИДЕИ или при запуске ./gradlew Компиляция
.
Обновление home.tsx
согласно списку изменений и посмотрите изменения, отраженные на домашней странице.
Создание корзины покупок
Теперь давайте создадим постоянную страницу корзины покупок, где мы сможем перечислить все товары, добавленные пользователем в корзину. Пользователь также может начать проверку с этой страницы. В корзине покупок будут храниться добавленные товары до завершения оплаты, даже если пользователь выйдет из системы или использует приложение на другом компьютере, поскольку состояние сохраняется автоматически с помощью сгенерированного CRUD API:
Для этой функции мы также добавляем/обновляем нижеприведенное на стороне сервера:
- конфигурации безопасности для обеспечения того, чтобы пользователь мог обновлять только свою корзину покупок при входе в систему. Только администраторы смогут просматривать корзину покупок других пользователей и управлять всеми сущностями.
- Новые конечные точки REST для добавления и удаления товаров в корзину и из нее.
- Методы обслуживания
- Операции с базами данных .
Эти обновления довольно просты благодаря фреймворку, предоставляемому Hipster и Spring.
На стороне клиента мы обновим:
- редуктор корзины покупок для связи с новыми конечными точками.
- Добавьте новый маршрут и модуль для отображения корзины покупок.
На странице Реакции корзины покупок используется приведенный ниже фрагмент кода. Обратите внимание, что содержимое списка очень похоже на страницу со списком товаров.
//import ...; export interface ICartProp extends StateProps, DispatchProps {} export const Cart = (props: ICartProp) => { useEffect(() => { props.getEntityForCurrentUser(); }, []); const remove = id => () => { props.removeOrder(id); }; const { isAuthenticated, cart, loading } = props; return (); }; const mapStateToProps = ({ authentication, shoppingCart }: IRootState) => ({ isAuthenticated: authentication.isAuthenticated, cart: shoppingCart.entity, loading: shoppingCart.loading }); const mapDispatchToProps = { getEntityForCurrentUser, removeOrder }; type StateProps = ReturnType
{isAuthenticated ? ( <> Your shopping cart
You have {cart?.orders?.length} items in your cart
{cart.orders && cart.orders.length > 0 ? ( <>{cart.orders.map((order, i) => ({/*... list content */}))}) : ( !loading &&Total price:
No items found)} ) : ()}Not authorized. Please log in first ; type DispatchProps = typeof mapDispatchToProps; export default connect(mapStateToProps, mapDispatchToProps)(Cart);
Вот весь список изменений для этой функции. Внесите изменения в приложение и посмотрите изменения, отраженные на странице корзины покупок.
Пожалуйста, обратите внимание, что я также внес некоторые улучшения в поддельные данные, сгенерированные JHipster в этом коммите , и улучшил страницы товаров и корзины в этом коммите . Я также исправил тесты в этом коммите . Обновите свое приложение также в соответствии с этими списками изменений.
Интеграция платежей
Теперь, когда наша корзина готова, мы можем интегрировать API оформления заказа Adyen для совершения платежей. Во-первых, убедитесь, что вы зарегистрировались для тестовой учетной записи Adyen. Следовать это руководство для получения ключей API и учетной записи продавца. Вам также потребуется сгенерировать исходный ключ для каждого домена, который вы используете для сбора платежей. В нашем случае для использования в разработке нам необходимо создать исходный ключ для http://localhost:9000
и http://localhost:8080
.
Мы будем использовать библиотеку Java API Adyen для выполнения вызовов API. Мы добавим зависимость в вашу сборку Gradle .
implementation group: "com.adyen", name: "adyen-java-api-library", version: "5.0.0"
Нам также необходимо исключить домен Adyen из политики безопасности контента , определенной в src/main/java/com/adyen/demo/store/config/SecurityConfiguration.java
.
Мы создадим новый контроллер Spring REST, который будет использовать библиотеку Java Adyen и выполнять вызовы API платежей для нас. Здесь находится src/main/java/com/adyen/demo/store/web/rest/CheckoutResource.java
класс. Вот метод из этого класса.
@PostMapping("/checkout/payment-methods") public ResponseEntitypaymentMethods() throws EntityNotFoundException, IOException, ApiException { PaymentMethodsRequest paymentMethodsRequest = new PaymentMethodsRequest(); paymentMethodsRequest.setMerchantAccount(merchantAccount); paymentMethodsRequest.setCountryCode("NL"); paymentMethodsRequest.setShopperLocale("nl-NL"); paymentMethodsRequest.setChannel(PaymentMethodsRequest.ChannelEnum.WEB); Amount amount = getAmountFromCart(); paymentMethodsRequest.setAmount(amount); log.debug("REST request to get Adyen payment methods {}", paymentMethodsRequest); PaymentMethodsResponse response = checkout.paymentMethods(paymentMethodsRequest); return ResponseEntity.ok() .body(response); }
Контроллер гарантирует, что все действия выполняются с активной корзиной покупок пользователя, вошедшего в сеанс. Это гарантирует, что такие проблемы безопасности, как атаки “человек посередине” и подмена запросов, не возникнут. После успешного завершения оплаты мы закрываем активную корзину покупок, гарантируя, что у каждого пользователя одновременно будет только одна активная корзина покупок.
На стороне клиента мы создадим страницу React для отображения вариантов оплаты и статуса оплаты результата , редуктора redux/| для общения с новыми конечными точками API. Мы также загрузим и добавим клиентские ресурсы Adyen в ваш index.html файл.
Вот важные фрагменты страницы оформления заказа, так как именно здесь мы обрабатываем интеграцию Adyen с javascript из React.
//import ...; export interface ICheckoutProp extends StateProps, DispatchProps {} class CheckoutContainer extends React.Component{ private paymentContainer = React.createRef (); //... componentDidMount() { this.props.getEntityForCurrentUser(); this.props.getAdyenConfig(); this.props.getPaymentMethods(); } componentDidUpdate(prevProps: ICheckoutProp) { const { paymentMethodsRes, config, paymentRes, paymentDetailsRes, errorMessage } = this.props; if (errorMessage && errorMessage !== prevProps.errorMessage) { window.location.href = `/status/error?reason=${errorMessage}`; return; } if (paymentMethodsRes && config && (paymentMethodsRes !== prevProps.paymentMethodsRes || config !== prevProps.config)) { this.checkout = new AdyenCheckout({ ...config, paymentMethodsResponse: this.removeNilFields(paymentMethodsRes), onAdditionalDetails: this.onAdditionalDetails, onSubmit: this.onSubmit }); } if (paymentRes && paymentRes !== prevProps.paymentRes) { this.processPaymentResponse(paymentRes); } if (paymentRes && paymentDetailsRes !== prevProps.paymentDetailsRes) { this.processPaymentResponse(paymentDetailsRes); } } removeNilFields = obj => { //... }; processPaymentResponse = paymentRes => { if (paymentRes.action) { this.paymentComponent.handleAction(paymentRes.action); } else { //... window.location.href = `/checkout/status/${urlPart}?reason=${paymentRes.resultCode}&paymentType=unknown`; } }; onSubmit = (state, component) => { if (state.isValid) { this.props.initiatePayment({ ...state.data, origin: window.location.origin }); this.paymentComponent = component; } }; onAdditionalDetails = (state, component) => { this.props.submitAdditionalDetails(state.data); this.paymentComponent = component; }; handlePaymentSelect = (type: string) => () => { this.checkout.create(type).mount(this.paymentContainer?.current); }; render() { const { cart } = this.props; return ( ); } } const mapStateToProps = ({ checkout, shoppingCart }: IRootState) => ({ //... }); const mapDispatchToProps = { //... }; type StateProps = ReturnType
Make payment
You are paying total of € {cart.totalPrice}
|
; type DispatchProps = typeof mapDispatchToProps; export default connect(mapStateToProps, mapDispatchToProps)(CheckoutContainer);
Вот весь список изменений для этой функции. Внесите соответствующие изменения в приложение и посмотрите изменения, отраженные на странице корзины покупок. Обязательно сначала установите следующие переменные среды.
export ADYEN_API_KEY=yourAdyenApiKey export ADYEN_MERCHANT_ACCOUNT=yourAdyenMerchantAccount export ADYEN_ORIGIN_KEY=yourAdyenOriginKeyForCorrectDomain
Запуск приложения в рабочем состоянии
Теперь, когда мы внесли все необходимые изменения, давайте скомпилируем и запустим наше приложение в рабочем режиме.
Во-первых, давайте запустим сгенерированные модульные и интеграционные тесты, чтобы убедиться, что мы ничего не сломали:
./gradlew npm_test test integrationTest
Теперь давайте запустим базу данных MySQL, поскольку наше приложение использует базу данных H2 в памяти для разработки и MySQL для производства, это облегчает разработку. Мы будем использовать Docker compose для запуска базы данных. Вы также можете вручную запустить базу данных MySQL, если хотите.
docker-compose -f src/main/docker/mysql.yml up -d
Приведенная выше команда запустит базу данных MySQL из включенного файла Docker compose. Теперь выполните приведенную ниже команду, чтобы запустить приложение в рабочем режиме:
./gradlew -Pprod
Вы также можете упаковать приложение с помощью команды ./gradlew --Ппрод чистый загрузочный ящик
а затем запустите JAR, используя java -jar build/библиотеки/*.jar
Теперь посетите https://localhost:8080 и используйте пользователей по умолчанию, указанных на главной странице, для входа в систему и изучения приложения. Вы можете использовать тестовые карты от Adyen для имитации платежей
Вывод
Это оно. Мы успешно создали приложение для электронной коммерции в комплекте с проверкой товара и потоком платежей, которое может принимать несколько форм оплаты. Я настоятельно рекомендую вам ознакомиться с образцом приложения , чтобы получить лучшее представление о том, что было создано.
В примере приложения также есть поток регистрации пользователей это вы можете проверить
Я надеюсь, что это поможет всем, кто пытается создать корзины покупок и потоки платежей для своего приложения электронной коммерции Java.
Если вам понравилась эта статья, пожалуйста, оставьте лайк или комментарий. Дайте нам знать, если вы хотите видеть больше подобного контента в наших блогах.
Кредит на изображение обложки: Photo by Павел фельбер Bauer on Unsplash
Оригинал: “https://dev.to/adyen/building-an-e-commerce-application-using-java-react-2iln”