Достигните мастерства 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, © {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 предлагает три метода связи: веб-перехватчик, расписание и событие. Расписание идеально подходит для повторяющихся задач, события активируют задание при отправке полезных данных, а веб-перехватчики запускают задания в реальном времени при возникновении определенных событий.