Реализация оплаты бронирования онлайн на сайте
Онлайн-оплата при бронировании решает сразу две задачи: подтверждает намерение клиента и снижает процент неявок. Варианты: полная предоплата, залог (фиксированная сумма или процент), или оплата по факту с сохранением карты.
Модели оплаты
| Модель | Описание | Подходит для |
|---|---|---|
| Полная предоплата | Вся сумма при бронировании | Мастер-классы, туры |
| Депозит | Фиксированная сумма или % | Рестораны, салоны |
| Холдирование карты | Сумма заморожена, списывается позже | Прокат, аренда |
| Оплата по факту | Карта сохранена, оплата после услуги | Регулярные клиенты |
Интеграция с Stripe (полная предоплата)
class BookingPaymentService
{
public function createPaymentIntent(Booking $booking): array
{
$stripe = new \Stripe\StripeClient(config('services.stripe.secret'));
$intent = $stripe->paymentIntents->create([
'amount' => $booking->total_cents, // в копейках/центах
'currency' => 'rub',
'metadata' => [
'booking_id' => $booking->id,
'customer_id' => $booking->customer_id,
],
'automatic_payment_methods' => ['enabled' => true],
]);
$booking->update([
'payment_intent_id' => $intent->id,
'payment_status' => 'pending',
]);
return ['client_secret' => $intent->client_secret];
}
}
// Frontend: Stripe Elements
import { loadStripe } from '@stripe/stripe-js';
import { Elements, PaymentElement, useStripe, useElements } from '@stripe/react-stripe-js';
const stripePromise = loadStripe(import.meta.env.VITE_STRIPE_KEY);
function BookingPaymentForm({ clientSecret }: { clientSecret: string }) {
const stripe = useStripe();
const elements = useElements();
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
if (!stripe || !elements) return;
const { error } = await stripe.confirmPayment({
elements,
confirmParams: {
return_url: `${window.location.origin}/bookings/success`,
},
});
if (error) console.error(error.message);
}
return (
<form onSubmit={handleSubmit}>
<PaymentElement />
<button type="submit" className="btn-primary mt-4">Оплатить</button>
</form>
);
}
Webhook подтверждения оплаты
Route::post('/webhooks/stripe', function (Request $request) {
$event = \Stripe\Webhook::constructEvent(
$request->getContent(),
$request->header('Stripe-Signature'),
config('services.stripe.webhook_secret')
);
if ($event->type === 'payment_intent.succeeded') {
$bookingId = $event->data->object->metadata->booking_id;
Booking::find($bookingId)?->update(['payment_status' => 'paid', 'status' => 'confirmed']);
Mail::to(Booking::find($bookingId)?->customer_email)
->send(new BookingConfirmedMail(Booking::find($bookingId)));
}
return response('ok');
});
Российские платёжные системы
Для российского рынка: ЮKassa (Яндекс), CloudPayments, Тинькофф Касса, Сбербанк Эквайринг. API у каждой своё, но паттерн тот же: создание платёжной сессии → форма на стороне провайдера или embed → webhook с подтверждением.
Сроки
Оплата при бронировании через ЮKassa или Stripe с webhook-подтверждением: 4–6 рабочих дней.







