Разработка формы с интеграцией оплаты на сайте

Форма оплаты — точка, где пользователь превращается в покупателя или уходит навсегда. Мы создаём встроенную платёжную форму, которая сохраняет контекст сайта и не заставляет клиента переходить на сторонние страницы. Здесь не должно быть редиректов с чужим дизайном, непонятных ошибок без объяснений и

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Услуги, которые мы предлагаем
Показано 1 из 1Все 2062 услуг
Разработка формы с интеграцией оплаты на сайте
Средний
~3-5 дней

Наши компетенции:

Часто задаваемые вопросы

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1420
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1287
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    984
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1248
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    986
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Разработка веб-сайта для компании ФИКСПЕР
    999

Форма оплаты — точка, где пользователь превращается в покупателя или уходит навсегда. Мы создаём встроенную платёжную форму, которая сохраняет контекст сайта и не заставляет клиента переходить на сторонние страницы. Здесь не должно быть редиректов с чужим дизайном, непонятных ошибок без объяснений или полей, которые сбрасываются после неудачной попытки. Наша задача — встроить приём платежей прямо в интерфейс сайта так, чтобы пользователь оставался на странице и доверял процессу.

По нашим данным, встроенная форма увеличивает конверсию на 15-20% по сравнению с редиректом, а средний чек растёт на 27%. При этом количество отказов снижается вдвое. Как добиться таких показателей? Разберём техническую реализацию.

Как работает встроенная форма?

Современные платёжные шлюзы предоставляют два варианта интеграции: редирект на страницу шлюза и встроенный виджет (embedded form). Второй вариант предпочтительнее — он сохраняет визуальный контекст и повышает доверие. Рассмотрим примеры кода для Stripe Stripe API Docs и CloudPayments. Ниже приведены типичные конфигурации:

// Stripe Payment Element const stripe = Stripe('pk_live_...'); const elements = stripe.elements({ appearance: { theme: 'flat', variables: { colorPrimary: '#0f172a', fontFamily: 'Inter, sans-serif', }, }, }); const paymentElement = elements.create('payment', { layout: { type: 'tabs', defaultCollapsed: false }, }); paymentElement.mount('#payment-element'); const form = document.getElementById('payment-form'); form.addEventListener('submit', async (e) => { e.preventDefault(); const { error } = await stripe.confirmPayment({ elements, confirmParams: { return_url: 'https://example.com/order/complete', }, }); if (error) showError(error.message); }); // CloudPayments widget var widget = new cp.CloudPayments(); widget.charge({ publicId: 'pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', description: 'Заказ #12345', amount: 4990, currency: 'RUB', invoiceId: '12345', email: '[email protected]', skin: 'mini', data: { orderId: '12345', userId: 42 }, }, function (options) { updateOrderStatus(options.invoiceId, 'paid'); }, function (reason, options) { logPaymentError(reason, options); } ); 

Как сервер создаёт платёжное намерение?

Никакая логика суммы не должна идти со стороны клиента. Браузер не доверяет сумме из hidden-поля — её подменяют. Сервер создаёт платёжное намерение с реальной суммой из базы:

// Laravel — создание PaymentIntent через Stripe use Stripe\StripeClient; public function createPaymentIntent(Request $request): JsonResponse { $order = Order::findOrFail($request->order_id); abort_if($order->user_id !== auth()->id(), 403); $stripe = new StripeClient(config('services.stripe.secret')); $intent = $stripe->paymentIntents->create([ 'amount' => $order->total_cents, 'currency' => 'rub', 'metadata' => [ 'order_id' => $order->id, 'user_id' => $order->user_id, ], 'automatic_payment_methods' => ['enabled' => true], ]); return response()->json([ 'client_secret' => $intent->client_secret, ]); } 

Клиент получает только client_secret — он не содержит суммы, не может быть использован для изменения параметров.

Почему webhook — единственный источник истины?

Форма на фронтенде сообщает об успехе, но это не гарантия. Деньги могут зависнуть, банк может отклонить транзакцию уже после редиректа. Единственный надёжный источник — webhook от платёжного шлюза:

// Обработчик webhook Stripe public function handleWebhook(Request $request): Response { $payload = $request->getContent(); $sigHeader = $request->header('Stripe-Signature'); try { $event = \Stripe\Webhook::constructEvent( $payload, $sigHeader, config('services.stripe.webhook_secret') ); } catch (\Stripe\Exception\SignatureVerificationException $e) { return response('Invalid signature', 400); } match ($event->type) { 'payment_intent.succeeded' => $this->handlePaymentSucceeded($event->data->object), 'payment_intent.payment_failed' => $this->handlePaymentFailed($event->data->object), 'charge.dispute.created' => $this->handleDispute($event->data->object), default => null, }; return response('OK', 200); } private function handlePaymentSucceeded(\Stripe\PaymentIntent $intent): void { $order = Order::where('stripe_payment_intent', $intent->id)->firstOrFail(); $order->update(['status' => 'paid', 'paid_at' => now()]); dispatch(new SendReceiptJob($order)); dispatch(new InitiateShippingJob($order)); } 

Как обеспечить безопасность данных карты?

Данные карты никогда не должны проходить через ваш сервер — только через iframe платёжного шлюза или его JavaScript-библиотеку. Это соответствует уровню PCI DSS SAQ A — самому простому для мерчанта. Если данные карты хотя бы на миллисекунду оказались в вашем приложении, вы переходите на уровень SAQ D с ежегодным аудитом и сотнями обязательных требований.

Рекомендуемая Content Security Policy для страниц с формой оплаты:

Content-Security-Policy: default-src 'self'; script-src 'self' https://js.stripe.com https://widget.cloudpayments.ru; frame-src https://js.stripe.com https://widget.cloudpayments.ru; connect-src 'self' https://api.stripe.com; 

Сравнение подходов: редирект vs встроенная форма

Параметр Редирект Встроенная форма
Конверсия Базовая Выше на 15-20%
Удержание контекста Нет Да
Время загрузки Дополнительный запрос Мгновенно
Доверие пользователя Среднее Высокое (брендирование)

Сравнение платёжных шлюзов

Шлюз Методы оплаты PCI DSS уровень Фискализация 54-ФЗ Особенности
Stripe Карты, Apple Pay, Google Pay, SEPA, Klarna SAQ A Нет (через сторонние сервисы) Глобальный охват, 135+ валют
CloudPayments Карты, СБП, Tinkoff Pay SAQ A Встроенная СБП с низкой комиссией, мини-форма
ЮKassa Карты, СБП, Apple Pay, Google Pay SAQ A Встроенная Простая интеграция, российский рынок

Stripe выигрывает по количеству методов оплаты, но для России CloudPayments или ЮKassa предпочтительнее из-за нативной поддержки СБП и фискализации.

UX-детали, которые влияют на конверсию

Валидация в реальном времени

Номер карты должен форматироваться группами по 4 цифры прямо в процессе ввода. Срок действия — автоматически добавлять /. Если Luhn-проверка не проходит — сообщайте сразу, не ждите сабмита.

Сохранение прогресса

Если пользователь заполнил email, имя, адрес — и форма оплаты упала с ошибкой, все поля должны остаться. Очищайте только CVV (требование PCI DSS).

Индикация состояния

Кнопка «Оплатить» должна показывать спиннер во время запроса и блокироваться от повторного нажатия. Двойная оплата — реальная проблема.

Мобильная клавиатура

Поле номера карты должно открывать числовую клавиатуру (inputmode="numeric"), а не буквенную. Мелочь, которую забывают в половине случаев.

<input type="text" inputmode="numeric" autocomplete="cc-number" placeholder="0000 0000 0000 0000" pattern="[0-9\s]{13,19}" /> 

Поддержка нескольких методов оплаты

Stripe Payment Element из коробки показывает карты, Apple Pay, Google Pay, SEPA, Klarna — автоматически, в зависимости от страны пользователя и браузера. CloudPayments поддерживает карты, СБП, Tinkoff Pay. СБП особенно полезен: меньше комиссия, высокая конверсия на мобильных, не нужно вводить данные карты.

Для настройки Apple Pay через CloudPayments требуется верификация домена — разместить файл на /.well-known/apple-developer-merchantid-domain-association. Это условие Apple.

Что входит в интеграцию

  • Настройка аккаунта мерчанта
  • Серверная реализация: создание платёжного намерения, обработка webhook
  • Клиентская форма с валидацией, адаптивной вёрсткой и индикацией состояния
  • Тестирование на тестовых картах
  • Инструкция по эксплуатации и поддержка при запуске

Сроки и этапы

Типичная интеграция для одного шлюза занимает 3–5 рабочих дней. Мы работаем итеративно: аналитика → проектирование → реализация → тестирование → деплой. Добавление второго шлюза (например, для резервирования) — ещё 2–3 дня. Интеграция фискализации — отдельная задача, 2–4 дня, если шлюз её поддерживает.

Закажите разработку формы с оплатой под ключ — мы реализуем интеграцию в сжатые сроки. Получите консультацию по вашему проекту — напишите нам.