Рубрики
Без рубрики

Создание приложения для электронной коммерции с использованием Java и React

Как легко создать приложение для электронной коммерции с корзиной покупок и платежами с помощью Java, JHipster, Spring Boot, React и Adyen payments. Помеченный как java, react, spring, хипстер.

Приложения для электронной коммерции являются основой современного мира онлайн-покупок. В этом посте мы увидим, как легко создать приложение для электронной коммерции с помощью 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:

Для этой функции мы также добавляем/обновляем нижеприведенное на стороне сервера:

Эти обновления довольно просты благодаря фреймворку, предоставляемому 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 (
    
      
        {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 */}
))}

Total price:

) : ( !loading &&
No items found
)} ) : (
Not authorized. Please log in first
)}
); }; const mapStateToProps = ({ authentication, shoppingCart }: IRootState) => ({ isAuthenticated: authentication.isAuthenticated, cart: shoppingCart.entity, loading: shoppingCart.loading }); const mapDispatchToProps = { getEntityForCurrentUser, removeOrder }; type StateProps = ReturnType; 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 ResponseEntity paymentMethods() 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 (
      
        
          

Make payment

You are paying total of € {cart.totalPrice}

); } } const mapStateToProps = ({ checkout, shoppingCart }: IRootState) => ({ //... }); const mapDispatchToProps = { //... }; type StateProps = ReturnType; 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”