Добавление Stripe Checkout в приложение Next.js

Что такое Stripe и зачем он нужен
Stripe — платформа для приёма и управления онлайн-платежами. Она предлагает готовую страницу Checkout, поддержку карт, Apple Pay/Google Pay, локальные методы оплаты, подписки, выставление счетов и инструменты борьбы с мошенничеством. Использовать Stripe обычно быстрее и безопаснее, чем писать собственный платёжный шлюз.
Ключевые понятия в одну строку:
- Публичный ключ (publishable key): безопасно хранится на клиенте, нужен для загрузки Stripe.js.
- Секретный ключ (secret key): хранится только на сервере, используется для создания сессий и выполнения операций.
- Checkout Session: одноразовая сессия Stripe, которая перенаправляет пользователя на проверенную страницу оплаты.
Основные варианты использования (primary intent и варианты)
- Подключить Stripe Checkout к Next.js
- Быстрый приём платежей на сайте
- Обработка подписок через Checkout
- Локализация и кастомизация страницы Checkout
- Тестирование и запуск в production
Установка аккаунта Stripe и получение API-ключей
- Перейдите на сайт Stripe и зарегистрируйтесь (Sign up).
- Подтвердите e‑mail и активируйте аккаунт.
- В Dashboard откройте Developers → API keys.
- Скопируйте Publishable key и Secret key.
- В процессе активации оплат (Activate payments) заполните данные о бизнесе для production. Для разработки используйте Test mode.
- Сохраните ключи в файле .env на вашем проекте:
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_xxx
STRIPE_SECRET_KEY=sk_test_xxxВажное: секретный ключ никогда не должен попадать в клиентский код или в публичные репозитории.
Установка npm-пакетов
Установите официальные библиотеки Stripe и клиентскую утилиту:
npm install stripe
npm install @stripe/stripe-js axios- stripe: используется на сервере для создания сессий и работы с API.
- @stripe/stripe-js: загрузчик Stripe.js на клиенте.
- axios: пример HTTP-клиента для вызова вашего API-маршрута.
Создание API-маршрута для Checkout (pages/api/checkout-session.js)
Создайте файл pages/api/checkout-session.js и инициализируйте Stripe с секретным ключом из окружения. Ниже — минимально рабочий пример для Next.js API route.
// pages/api/checkout-session.js
import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
export default async function handler(req, res) {
if (req.method !== 'POST') {
res.setHeader('Allow', 'POST');
return res.status(405).end('Method Not Allowed');
}
const { cart } = req.body; // ожидается массив line items по спецификации Stripe
try {
const session = await stripe.checkout.sessions.create({
payment_method_types: ['card'],
line_items: cart,
mode: 'payment',
success_url: `${req.headers.origin}/success?session_id={CHECKOUT_SESSION_ID}`,
cancel_url: `${req.headers.origin}/cancel`,
});
return res.status(200).json({ id: session.id, url: session.url });
} catch (err) {
console.error('Stripe create session error:', err);
return res.status(err.statusCode || 500).json({ error: err.message });
}
}Пояснения полей:
- payment_method_types: массив поддерживаемых методов (карты, локальные методы и т.д.).
- line_items: список продуктов в формате Stripe (см. документацию для price, quantity и т.д.).
- mode: ‘payment’ для одноразовой оплаты, ‘subscription’ для подписок.
- success_url и cancel_url: куда Stripe перенаправит пользователя.
Критерии приёмки:
- POST-запрос возвращает id сессии и URL.
- В случае ошибки возвращается правильный HTTP-статус и сообщение.
Формат line_items — краткий справочник
Stripe ожидает line_items в форме:
[
{
"price": "price_1Hh1...",
"quantity": 1
}
]Или при использовании object-based items:
[
{
"price_data": {
"currency": "usd",
"product_data": { "name": "T-shirt" },
"unit_amount": 2000
},
"quantity": 1
}
]Используйте price IDs из Dashboard для постоянных товаров или price_data для динамического расчёта.
Компонент Checkout на клиенте (components/Checkout.js)
Создайте компонент, который вызовет ваш API и перенаправит клиента на Stripe Checkout.
// components/Checkout.js
import { loadStripe } from '@stripe/stripe-js';
import axios from 'axios';
const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY);
export default function Checkout({ cart }) {
const handleCheckout = async () => {
try {
const stripe = await stripePromise;
const response = await axios.post('/api/checkout-session', { cart });
const sessionId = response.data.id;
const result = await stripe.redirectToCheckout({ sessionId });
if (result.error) {
// Показать пользователю понятное сообщение
alert(result.error.message);
}
} catch (error) {
console.error('Checkout error:', error);
alert('Ошибка при переходе к оплате. Повторите попытку.');
}
};
return (
);
}Примечание: redirectToCheckout возвращает результат только если произошло локальное исключение. Обычно браузер автоматически перенаправляет.
Страницы успеха и отмены (pages/success.js, pages/cancel.js)
Создайте простые страницы, на которые Stripe будет направлять пользователей.
// pages/success.js
export default function Success() {
return Оплата прошла успешно. Спасибо за покупку!;
}
// pages/cancel.js
export default function Cancel() {
return Платёж отменён. Вы можете вернуться в корзину и попробовать снова.;
}Если вы используете Next.js 13 с app-directory, перенесите эти компоненты в папку app и настройте маршруты согласно документации Next.js.
Тестирование: режим Test и живой режим
- В Test mode Stripe предоставляет тестовые карты. Используйте их для симуляции успешных и неуспешных платежей.
- Перед релизом переключитесь в Live mode и замените ключи в .env на production-ключи.
- Проверьте webhooks (например, событие checkout.session.completed) в обоих режимах.
Важно: webhooks требуют публичного URL. Для локальной разработки используйте stripe CLI или ngrok.
Вебхуки: подтверждение платежа и пост-обработка
После успешной оплаты полезно обрабатывать событие checkout.session.completed через webhook, чтобы:
- Подтвердить заказ в базе данных.
- Отправить чек или письмо-подтверждение.
- Запустить fulfilment (логистика, цифровая доставка).
Пример проверки подписи webhook (фрагмент):
import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
export default async function handler(req, res) {
const sig = req.headers['stripe-signature'];
const payload = req.rawBody; // в Next.js нужно собрать сырое тело
try {
const event = stripe.webhooks.constructEvent(payload, sig, process.env.STRIPE_WEBHOOK_SECRET);
// Обработать event.type
res.json({ received: true });
} catch (err) {
console.error('Webhook signature verification failed:', err.message);
res.status(400).send(`Webhook Error: ${err.message}`);
}
}Кастомизация Checkout из Dashboard и при создании сессии
Через Dashboard можно задать бренд: логотип, цвет, домен. При создании сессии вы можете также передать:
- locale: язык интерфейса Checkout.
- billing_address_collection: ‘required’ чтобы собирать адрес плательщика.
- shipping_address_collection: для физических товаров.
- discounts, coupons: чтобы применить скидки.
Эти настройки помогут сделать оплату удобной и соответствующей вашему дизайну.
Лучшие практики безопасности и соответствия
- Храните секретный ключ только на сервере.
- Используйте HTTPS в продакшне.
- Работайте в режиме Test при разработке.
- Проверяйте подпись webhook через STRIPE_WEBHOOK_SECRET.
- Ограничьте доступ к API-ключам и ротацию ключей в политике безопасности.
Распространённые ошибки и как их исправлять
- “Invalid API Key provided”: проверьте, что STRIPE_SECRET_KEY верно прописан и не используется публичный ключ на сервере.
- “Session not found” при redirectToCheckout: убедитесь, что вы используете sessionId (или session.url) из ответа сервера, и что сессия создана корректно.
- Клиент не получает redirect: проверьте, возвращаете ли вы session.url и не затираете ли значение при проксировании.
- Webhook не приходит локально: используйте stripe CLI или ngrok и проверьте, включен ли корректный webhook endpoint в Dashboard.
Альтернативные подходы
- Stripe Elements: если нужен полностью кастомный UI на стороне клиента. Больше контроля, но выше сложность и требования PCI.
- Stripe Payment Intents API: для более тонкого управления платежами и 3DS.
- Использование serverless функций (Vercel, Netlify Functions) вместо pages/api — концептуально то же, но учтите таймауты и права доступа.
Когда Checkout НЕ подходит:
- Нужен полностью кастомный UX при вводе карты прямо в форме (требуется Elements).
- Необходимо хранить платёжные данные на вашем сервере (обычно не рекомендуется).
Шаблон проверки готовности к релизу (SOP)
- Тестовые платежи прошли успешно в Test mode (успех, отказ, SCA).
- Webhooks обрабатываются и в базе данных появятся записи заказов.
- Страницы success и cancel информативны и понятны пользователю.
- Ключи для production сохранены в безопасном хранилище.
- HTTPS включён и CORS настроен корректно.
Роли и их чек-листы
Разработчик:
- Настроил .env и проверил ключи.
- Покрыл тестами логику создания сессий.
- Защитил endpoint webhook.
Продукт-менеджер:
- Определил требуемые методы оплаты.
- Настроил брендирование и тексты на страницах success/cancel.
QA:
- Прогнал сценарии: успешная оплата, отказ, SCA, отмена пользователем.
- Проверил реакции на сетевые ошибки.
Быстрая методология внедрения (mini-methodology)
- Регистрируйте аккаунт Stripe и получите ключи.
- Настройте .env и установите пакеты.
- Реализуйте API-маршрут для создания сессии.
- Добавьте компонент Checkout на страницу корзины.
- Тестируйте в Test mode, проверьте webhooks.
- Перейдите в Live mode и мониторьте первые транзакции.
Чек-лист для релиза и мониторинга
- Мониторинг ошибок (Sentry, логирование).
- Метрики оплаты: успешные, отказы, chargebacks.
- Настроенные алерты на аномалии.
Быстрый сниппет — отправка уведомления после webhook
// пример псевдо-кода в обработчике webhook
if (event.type === 'checkout.session.completed') {
const session = event.data.object;
// Найти заказ по session.client_reference_id или metadata
// Обновить статус заказа и отправить e-mail
}Decision flow: когда использовать Checkout vs Elements
flowchart TD
A[Нужен быстрый старт и стандартная страница оплаты?] -- Да --> B[Stripe Checkout]
A -- Нет --> C[Требуется кастомизация UX?]
C -- Да --> D[Stripe Elements / Payment Intents]
C -- Нет --> BЗаключение
Stripe Checkout упрощает интеграцию платёжного интерфейса в Next.js-приложение. Он обеспечивает безопасность, соответствие требованиям PCI и быстрый запуск. Для большинства сценариев электронной коммерции это оптимальный выбор: меньше кода, меньше ответственности за хранение платёжных данных и удобный набор функций для подписок и локальных платёжных методов.
Ключевые следующие шаги: протестируйте все сценарии в Test mode, настройте webhook для пост-обработки заказов и подготовьте переход в Live mode с проверкой необходимых бизнес-данных.
Важно
- Всегда храните секретные ключи в .env и не публикуйте их в репозиториях.
- Тщательно тестируйте сценарии SCA и отказов.
Краткое резюме
- Настройте Stripe и получите ключи.
- Создайте API для сессий и компонент Checkout.
- Тестируйте, обрабатывайте webhooks и переходите в продакшн.
Похожие материалы
Инфографика в PowerPoint: практическое руководство
Kids Mode в Microsoft Edge — настройка и советы
Найти и удалить скрытые LaunchDaemons и LaunchAgents
Лучшие фильтры TikTok и как их использовать
Как полностью сбросить Mac и переустановить macOS