DevGang
Авторизоваться

Достигните мастерства NextJS: создайте страницу продаж с помощью Stripe и Airtable

В этом уроке вы узнаете, как создать целевую страницу продаж:

  • Создайте целую страницу продаж с помощью NextJS.
  • Совершайте платежи через Stripe.
  • Сохраните их данные в базе данных Airtable

Управление фоновыми заданиями для NextJS

Trigger.dev – это библиотека с открытым исходным кодом, которая позволяет создавать и отслеживать длительные задания для вашего приложения с помощью NextJS, Remix, Astro и многих других!

Настройки

Здесь я расскажу вам, как создать пользовательский интерфейс для целевой страницы курса. Создайте новый проект TypeScript Next.js, запустив приведенный ниже фрагмент кода.

npx create-next-app course-page

Установите пакет React Icons, чтобы мы могли использовать в приложении различные типы значков.

npm install react-icons --save

Приложение разделено на две страницы: домашнюю страницу, представляющую собой целевую страницу курса, и страницу успеха, которая отображается пользователю после совершения платежа.

Домашняя страница

Домашняя страница разделена на пять разделов: панель навигации, заголовок, функции, покупки и нижний колонтитул.

Обновите файл index.tsx, как показано ниже. Заполнители представляют каждый раздел целевой страницы.

import { Inter } from "next/font/google";
const inter = Inter({ subsets: ["latin"] });

export default function Home() {
  return (
    <main className={` ${inter.className}`}>
      {/* --- Navigation bar --- */}
      <p>Hello world</p>
      {/* --- Header --- */}

      {/* --- Features Section --- */}

      {/* --- Purchase Now Section--- */}

      {/* --- Footer Section --- */}
    </main>
  );
}

Замените заполнитель Navigation bar приведенным ниже фрагментом кода.

<nav className="sticky top-0 z-20 flex w-full items-center justify-between border-b-[1px] border-b-gray-200 bg-white p-4 md:h-[12vh] md:p-8">
  <h2 className="text-2xl font-bold text-purple-600">TechGrow</h2>
  <button className="rounded-2xl bg-purple-600 px-5 py-3 text-white hover:bg-purple-800">
    Get Started
  </button>
</nav>

Скопируйте приведенный ниже фрагмент кода в раздел Header. Вы можете получить изображение из репозитория GitHub.

<header className="flex min-h-[88vh] w-full flex-col items-center justify-between px-4 py-12 md:flex-row md:px-8">
  <div className="mb-8 w-full md:mb-0 md:w-[60%] md:pr-6">
    <h2 className="mb-4 text-5xl font-extrabold">
      Future-Proof Your Career with Top Digital Skills!
    </h2>
    <p className="mb-4 opacity-60">
      Unlock your full potential of a future-proof career through the power of
      top digital skills with our all-in-one growth package.
    </p>
    <button className="w-[200px] rounded-2xl bg-purple-600 px-5 py-3 text-lg font-semibold text-white hover:bg-purple-800">
      Get Started
    </button>
  </div>
  <div className="w-full md:w-[40%]">
    <Image src={headerImage} alt="Man smiling" className="rounded-lg" />
  </div>
</header>

В разделе Features Section показаны некоторые причины, по которым клиенту следует приобрести курс.

<section className="min-h-[88vh] w-full bg-purple-50 px-4 py-14 md:px-8 ">
  <h2 className="mb-4 text-center text-3xl font-extrabold">Why Choose Us?</h2>
  <p className="text-center opacity-50">
    Unlock your full potential of a future-proof career
  </p>
  <p className="mb-14 text-center opacity-50">
    that surpasses your expectation.
  </p>
  <div className="flex w-full flex-col items-center justify-between md:flex-row md:space-x-6">
    <div className="mb-6 w-full rounded-xl bg-white px-5 py-8 hover:border-[1px] hover:border-purple-600 hover:shadow-md md:mb-0 md:w-1/3">
      <div className="mb-2 max-w-max rounded-full bg-purple-50 p-4">
        <FaChalkboardTeacher className="text-2xl text-purple-800" />
      </div>
      <p className="mb-2 text-lg font-bold">Expert instructors</p>
      <p className="text-sm opacity-50">
        Learn from industry experts, gaining unique insights which cannot be
        found elsewhere.
      </p>
    </div>
    <div className="mb-6 w-full rounded-xl bg-white px-5 py-8 hover:border-[1px] hover:border-purple-600 hover:shadow-md md:mb-0 md:w-1/3">
      <div className="mb-2 max-w-max rounded-full bg-purple-50 p-4">
        <IoDocumentTextSharp className="text-2xl text-purple-800" />
      </div>
      <p className="mb-2 text-lg font-bold">Hands-On Projects</p>
      <p className="text-sm opacity-50">
        Learn practical, real-world digital skills through relevant projects and
        interactive sessions.
      </p>
    </div>
    <div className="mb-6 w-full rounded-xl bg-white px-5 py-8 hover:border-[1px] hover:border-purple-600 hover:shadow-md md:mb-0 md:w-1/3">
      <div className="mb-2 max-w-max rounded-full bg-purple-50 p-4">
        <BsFillClockFill className="text-2xl text-purple-800" />
      </div>
      <p className="mb-2 text-lg font-bold">Lifetime Access</p>
      <p className="text-sm opacity-50">
        Unlimited lifetime access for continuous learning and personal growth.
      </p>
    </div>
  </div>
</section>

Скопируйте приведенный ниже фрагмент кода в заполнитель раздела Purchase Now Section.

<div className="flex min-h-[70vh] w-full flex-col items-center justify-between bg-purple-700 px-4 py-14 md:flex-row md:px-12">
  <div className="mb-8 w-full md:mb-0 md:w-[50%] md:pr-6">
    <h2 className="mb-4 text-5xl font-extrabold text-purple-50">
      Start learning and grow your skills today!{" "}
    </h2>
    <p className="mb-4 text-purple-300">
      Unlock your full potential of a future-proof career through the power of
      top digital skills with our all-in-one growth package.
    </p>
    <div className="mb-6">
      <div className="mb-2 flex items-center space-x-3">
        <AiFillCheckCircle className="text-2xl text-green-300" />
        <p className="text-sm text-purple-50 opacity-80">24/7 availability</p>
      </div>
      <div className="mb-2 flex items-center space-x-3">
        <AiFillCheckCircle className="text-2xl text-green-300" />
        <p className="text-sm text-purple-50 opacity-80 ">
          Expert-led tutorials
        </p>
      </div>
      <div className="mb-2 flex items-center space-x-3">
        <AiFillCheckCircle className="text-2xl text-green-300" />
        <p className="text-sm text-purple-50 opacity-80 ">
          High-quality contents
        </p>
      </div>
      <div className="mb-2 flex items-center space-x-3">
        <AiFillCheckCircle className="text-2xl text-green-300" />
        <p className="text-sm text-purple-50 opacity-80 ">
          Hands-on practical and interactive sessions
        </p>
      </div>
    </div>
    <button className="w-[200px] rounded-2xl bg-purple-50 px-5 py-3 text-lg font-semibold text-purple-600 hover:bg-purple-100">
      Purchase Now
    </button>
  </div>
  <div className="flex w-full items-center justify-center md:w-[50%]">
    <Image src={buy} alt="Man smiling" className="rounded-lg" />
  </div>
</div>

Наконец, обновите Footer section, как показано ниже.

<footer className="flex min-h-[10vh] w-full items-center justify-center bg-white">
  <p className="text-sm text-purple-800">
    Copyright, &copy; {new Date().getFullYear()} All Rights Reserved Tech Grow
  </p>
</footer>

Успех

После успешной оплаты пользователи перенаправляются на страницу «Успех».

Создайте файл success.tsx и скопируйте в него приведенный ниже код.

import React from "react";
import Link from "next/link";

export default function Success() {
  return (
    <div className="flex min-h-[100vh] w-full flex-col items-center justify-center">
      <h2 className="mb-4 text-3xl font-bold">Payment Sucessful!</h2>
      <Link
        href="/"
        className="rounded-2xl bg-purple-50 px-5 py-3 text-lg font-semibold text-purple-600 hover:bg-purple-100"
      >
        Go Home
      </Link>
    </div>
  );
}

Поздравляем! Вы успешно создали пользовательский интерфейс приложения.

Начни собирать платежи

Stripe — это популярная платформа обработки онлайн-платежей, которая позволяет создавать продукты и интегрировать в свое приложение как одноразовые, так и регулярные способы оплаты.

Здесь я расскажу вам, как создать продукт в Stripe и как добавить страницу оформления заказа Stripe в ваше приложение Next.js.

Сначала вам необходимо создать учетную запись Stripe. Для этого урока вы можете использовать учетную запись в тестовом режиме.

Выберите Products в верхнем меню и нажмите кнопку Add Product, чтобы создать новый продукт. Укажите название продукта, цену, описание и способ оплаты. В качестве варианта оплаты выберите one-time.

Создайте файл .env.local и скопируйте в него идентификатор продукта.

PRODUCT_ID=<YOUR_PRODUCT_ID>

Затем нажмите Developers в верхнем меню, выберите API keys и создайте новый секретный ключ.

Сохраните секретный ключ в файле .env.local. Он аутентифицирует и позволяет вам получить доступ к Stripe из приложения.

STRIPE_API_KEY=<YOUR_STRIPE_SECRET_KEY>

Добавление страницы оформления заказа Stripe в Next.js

Для этого установите библиотеку Stripe Node.js.

npm install stripe

Создайте конечную точку API — api/payment в приложении Next.js и скопируйте приведенный ниже код в файл.

//👉🏻  Within the api/payment.ts file
import type { NextApiRequest, NextApiResponse } from "next";
import Stripe from "stripe";

const stripe = new Stripe(process.env.STRIPE_API_KEY!, {} as any);

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  const session = await stripe.checkout.sessions.create({
    line_items: [
      {
        price: process.env.PRODUCT_ID,
        quantity: 1,
      },
    ],
    mode: "payment",
    success_url: `http://localhost:3000/success?session_id={CHECKOUT_SESSION_ID}`,
    cancel_url: "http://localhost:3000",
  });

  res.status(200).json({ session: session.url });
}

Приведенный выше фрагмент кода создает сеанс оформления заказа для продукта и возвращает URL-адрес сеанса. URL-адрес сеанса — это ссылка, по которой собираются платежи за продукт, и вам необходимо перенаправить пользователей на этот URL-адрес.

Создайте функцию в файле index.tsx, которая получает URL-адрес сеанса из конечной точки API и перенаправляет пользователя на страницу. Выполняйте функцию, когда пользователь нажимает любую кнопку на веб-странице.

const handlePayment = async () => {
  try {
    const data = await fetch("/api/payment");
    const response = await data.json();
    window.location.assign(response.session);
  } catch (err) {
    console.error(err);
  }
};

Поздравляем! Вы успешно добавили страницу оформления заказа Stripe в свое приложение. В следующих разделах вы узнаете, как обрабатывать платежи и сохранять данные пользователей в базе данных Airtable с помощью Trigger.dev.

Обработка платежей с помощью Trigger.dev

Trigger.dev — это библиотека с открытым исходным кодом, которая позволяет вам создавать и отслеживать долго выполняющиеся задания для вашего приложения с помощью NextJS, Remix, Astro и многих других! С помощью Trigger.dev вы можете автоматизировать, планировать и откладывать задачи в своей кодовой базе и в таких сервисах, как репозитории GitHub, каналы Slack и т. д.

Подключите Stripe к Trigger.dev

Здесь вы узнаете, как обрабатывать платежи Stripe в вашем приложении с помощью веб-хуков Trigger.dev.

Веб-перехватчики Trigger.dev удобны в использовании и позволяют управлять процессами регистрации и отмены регистрации за вас. Кроме того, в случае ошибки он пытается повторно отправить событие до тех пор, пока не будет достигнут успех.

Все, что вам нужно сделать, это указать услугу и события, которые вы хотите слушать; Trigger.dev позаботится о конфигурациях.

Добавление Trigger.dev в приложение Next.js

Прежде чем продолжить, вам необходимо создать учетную запись Trigger.dev.

Создайте название организации и проекта для своих должностей.

Следуйте инструкциям. После того, как вы их выполнили, смело переходите к следующему разделу этой статьи.

В противном случае нажмите Environments & API Keys в боковом меню панели управления проектом.

Скопируйте ключ API вашего сервера DEV и запустите приведенный ниже фрагмент кода, чтобы установить Trigger.dev. Внимательно следуйте инструкциям.

npx @trigger.dev/cli@latest init

Запустите проект Next.js.

npm run dev

В другом терминале запустите следующий фрагмент кода, чтобы установить туннель между Trigger.dev и вашим проектом Next.js.

npx @trigger.dev/cli@latest dev

Наконец, переименуйте файл jobs/examples.ts в jobs/functions.ts. Здесь обрабатываются все задания.

Поздравляем! Вы успешно добавили Trigger.dev в свое приложение Next.js.

Слушайте Stripe успешных платежей

Установите пакет Stripe, предоставленный Trigger.dev.

npm install @trigger.dev/stripe@latest

Обновите файл jobs/functions.ts, как показано ниже.

import { client } from "@/trigger";
import { Stripe } from "@trigger.dev/stripe";

const stripe = new Stripe({
  id: "stripe",
  apiKey: process.env.STRIPE_API_KEY!,
});

client.defineJob({
  //👇🏻 job properties
  id: "save-customer",
  name: "Save Customer Details",
  version: "0.0.1",
  //👇🏻 event trigger
  trigger: stripe.onCheckoutSessionCompleted(),

  run: async (payload, io, ctx) => {
    const { customer_details } = payload;
    await io.logger.info("Getting event from Stripe!🎉");
    //👇🏻 logs customer's details
    await io.logger.info(JSON.stringify(customer_details));

    await io.logger.info("✨ Congratulations, A customer just paid! ✨");
  },
});

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

После того как пользователь совершает платеж, его данные сохраняются в консоли заданий на Trigger.dev.

Сохраните информацию о клиенте

После получения данных о клиенте из веб-перехватчика Stripe следующим шагом будет сохранение этих данных в базе данных. В этом разделе вы узнаете, как интегрировать Airtable в приложение Next.js и взаимодействовать с ним с помощью Trigger.dev.

Airtable — это простое в использовании облачное программное обеспечение, которое помогает организовывать информацию в настраиваемые таблицы. Это похоже на смесь электронной таблицы и базы данных, позволяющую вам совместно управлять данными, задачами или проектами визуально привлекательным способом.

Для начала создайте учетную запись Airtable и настройте рабочее пространство и базу. Рабочее пространство Airtable представляет собой папку, содержащую несколько баз данных, известных как базы. Каждая база может содержать несколько таблиц.

В базе создайте таблицу, содержащую столбцы Name и Email. Здесь будут храниться имя и адрес электронной почты клиента, полученные из Stripe.

Нажмите кнопку Help на панели навигации и выберите API Documentation.

Прокрутите страницу, найдите и скопируйте идентификатор базы и таблицы и сохраните их в файл .env.local.

AIRTABLE_BASE_ID=<YOUR_AIRTABLE_BASE_ID>
AIRTABLE_TABLE_ID=<YOUR_AIRTABLE_TABLE_ID>

Затем создайте личный токен доступа, щелкнув свой аватар и выбрав Developer Hub. Предоставьте токену область чтения и записи.

Сохраните вновь созданный токен в файл .env.local.

AIRTABLE_TOKEN=<YOUR_PERSONAL_ACCESS_TOKEN>

Затем установите пакет Airtable, предоставленный Trigger.dev.

npm install @trigger.dev/airtable

Обновите файл jobs/functions.js, чтобы сохранить имя и адрес электронной почты пользователя в Airtable после завершения оплаты.

import { Airtable } from "@trigger.dev/airtable";
import { client } from "@/trigger";
import { Stripe } from "@trigger.dev/stripe";

// -- 👇🏻 Airtable instance --
const airtable = new Airtable({
  id: "airtable",
  token: process.env.AIRTABLE_TOKEN,
});
// -- 👇🏻 Stripe instance --
const stripe = new Stripe({
  id: "stripe",
  apiKey: process.env.STRIPE_API_KEY!,
});

client.defineJob({
  id: "save-customer",
  name: "Save Customer Details",
  version: "0.0.1",
  // -- 👇🏻 integrates Airtable --
  integrations: { airtable },
  trigger: stripe.onCheckoutSessionCompleted(),

  run: async (payload, io, ctx) => {
    const { customer_details } = payload;
    await io.logger.info("Getting event from Stripe!🎉");
    await io.logger.info(JSON.stringify(customer_details));

    await io.logger.info("Adding data to Airtable🎉");

    // --👇🏻 access the exact table via its ID --
    const table = io.airtable
      .base(process.env.AIRTABLE_BASE_ID!)
      .table(process.env.AIRTABLE_TABLE_ID!);

    // -- 👇🏻 adds a new record to the table --
    await table.createRecords("create records", [
      {
        fields: {
          Name: customer_details?.name!,
          Email: customer_details?.email!,
        },
      },
    ]);

    await io.logger.info("✨ Congratulations, New customer added! ✨");
  },
});

Приведенный выше фрагмент кода интегрирует Airtable с Trigger.dev, обеспечивает доступ к таблице и ее имени и адресу электронной почты клиента.

Поздравляем! Вы завершили проект для этого урока.

Заключение

Trigger.dev предлагает три метода связи: веб-перехватчик, расписание и событие. Расписание идеально подходит для повторяющихся задач, события активируют задание при отправке полезных данных, а веб-перехватчики запускают задания в реальном времени при возникновении определенных событий.

Источники:

#JavaScript
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

В этом месте могла бы быть ваша реклама

Разместить рекламу