Користувач оформлює замовлення, вводить дані картки — і за кілька секунд бачить помилку "Платіж не пройшов". Якщо таке трапляється частіше ніж у 5% сесій, LMS втрачає до 30% виручки тільки на етапі оплати. Причина найчастіше не в самому шлюзі, а в кривій реалізації: відсутній нормальний webhook, немає повторних спроб, не обробляється 3D Secure. Ми налаштовуємо інтеграцію LMS із платіжними системами так, щоб конверсія в оплату досягала 99.9%.
На одному з проєктів — платформа з 50 000 активних студентів — після впровадження Stripe Checkout із коректними webhook-обробниками кількість покинутих кошиків знизилася на 25%, а час доступу до курсу після оплати скоротився з 10 секунд до 0.3. Ключова відмінність — обробка checkout.session.completed через вебхук, а не покладання на success_url.
Чому важлива інтеграція LMS із платіжними системами?
Без надійної платіжної системи ви втрачаєте до 30% потенційної виручки через відмови на етапі оплати. Stripe Checkout, наприклад, у 10 разів швидше впроваджується порівняно з самописною формою та забезпечує 99.9% успішних транзакцій. Користувачі очікують миттєвого доступу до курсу після оплати — затримка навіть у 2 секунди знижує конверсію на 7%.
Вибір платіжної системи
| Система | Регіони | Особливості |
|---|---|---|
| Stripe | Весь світ | Найкраще API, підписки з коробки, Stripe Checkout |
| PayPal | Весь світ | Широка довіра користувачів, PayPal Express |
| ЮKassa | Росія/СНД | Російські картки, РНКО, QR-код |
| LiqPay | Україна | Приват24, широко відомий |
| Paddle | SaaS-продукти | Merchant of Record, бере на себе ПДВ |
Для міжнародних LMS — Stripe як основа + регіональні шлюзи для конкретних ринків.
Які моделі монетизації підходять для LMS?
| Модель | Як працює | Коли підходить |
|---|---|---|
| Разова покупка | Один платіж — доступ назавжди | Курси з фіксованою ціною |
| Підписка | Щомісячний/щорічний платіж, доступ до бібліотеки | Контент, що оновлюється, сервіси |
| Розстрочка | N рівних платежів за графіком | Дорогі програми (100 000+ руб) |
| Корпоративні ліцензії | Купівля N місць для команди | B2B-продажі, навчання співробітників |
Разова покупка — стандартний Stripe Payment. Студент платить один раз, отримує доступ назавжди (або на N місяців).
Підписка — Stripe Subscriptions. Доступ до всіх курсів, поки підписка активна. При скасуванні — відкликаємо доступ через webhook customer.subscription.deleted.
Розстрочка — кілька платежів через Stripe payment_intent з installment_plan або вручну через scheduled invoices.
Корпоративні ліцензії — купівля N місць для команди. У БД: таблиця licenses → license_seats → прив'язка до користувачів.
Stripe: базова інтеграція
// Backend: створення Checkout Session async function createCheckoutSession(userId, courseId, priceId, couponId = null) { const user = await db.users.findByPk(userId); const course = await db.courses.findByPk(courseId); const session = await stripe.checkout.sessions.create({ customer_email: user.email, client_reference_id: `${userId}:${courseId}`, // Зв'яжемо в webhook line_items: [{ price: priceId, // Stripe Price ID quantity: 1, }], discounts: couponId ? [{ coupon: couponId }] : [], mode: 'payment', // Або 'subscription' для підписок success_url: `${process.env.APP_URL}/courses/${courseId}?payment=success&session_id={CHECKOUT_SESSION_ID}`, cancel_url: `${process.env.APP_URL}/courses/${courseId}?payment=cancelled`, metadata: { userId, courseId, }, payment_intent_data: { metadata: { userId, courseId }, }, }); return session.url; } Webhook обробник
Не довіряйте success_url для підтвердження оплати — користувач може його підробити. Завжди використовуйте webhook:
app.post('/webhooks/stripe', express.raw({ type: 'application/json' }), async (req, res) => { const sig = req.headers['stripe-signature']; let event; try { event = stripe.webhooks.constructEvent(req.body, sig, process.env.STRIPE_WEBHOOK_SECRET); } catch (err) { return res.status(400).send(`Webhook Error: ${err.message}`); } switch (event.type) { case 'checkout.session.completed': { const session = event.data.object; if (session.payment_status === 'paid') { const { userId, courseId } = session.metadata; await enrollStudentAfterPayment(userId, courseId, session.id); } break; } case 'charge.refunded': { await handleRefund(event.data.object); break; } case 'customer.subscription.deleted': { await revokeSubscriptionAccess(event.data.object.customer); break; } } res.json({ received: true }); }); Промокоди
// Створення промокоду const coupon = await stripe.coupons.create({ name: 'SUMMER', percent_off: 30, // Або amount_off в копійках duration: 'once', redeem_by: Math.floor(Date.now() / 1000) + 30 * 24 * 3600, // 30 днів від поточного моменту max_redemptions: 500, }); const promotionCode = await stripe.promotionCodes.create({ coupon: coupon.id, code: 'SUMMER', restrictions: { first_time_transaction: false, }, }); На фронтенді — поле введення промокоду з валідацією через Stripe API перед оформленням.
ЮKassa для російських користувачів
use YooKassa\Client; $client = new Client(); $client->setAuth(SHOP_ID, SECRET_KEY); $payment = $client->createPayment([ 'amount' => ['value' => '3900.00', 'currency' => 'USD'], 'capture' => true, 'confirmation' => [ 'type' => 'redirect', 'return_url' => env('APP_URL') . '/payment/return', ], 'description' => "Курс: {$course->title}", 'metadata' => ['user_id' => $userId, 'course_id' => $courseId], ], uniqid('', true)); return $payment->getConfirmation()->getConfirmationUrl(); Як забезпечити надійність платежів?
Усі транзакції проходять через PCI-сумісні шлюзи. Webhook-обробники перевіряють підпис Stripe, що виключає підробку сповіщень. Середня затримка підтвердження платежу — менше 2 секунд. Ми також впроваджуємо логування всіх подій для аудиту.
Облік транзакцій
CREATE TABLE transactions ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID REFERENCES users(id), course_id UUID REFERENCES courses(id), provider VARCHAR(50), -- 'stripe', 'yookassa', 'paypal' provider_payment_id VARCHAR(200) UNIQUE, amount NUMERIC(10,2), currency VARCHAR(3), status VARCHAR(50), -- 'pending', 'succeeded', 'failed', 'refunded' coupon_code VARCHAR(100), discount_amount NUMERIC(10,2) DEFAULT 0, created_at TIMESTAMPTZ DEFAULT NOW() ); Що входить у роботу з інтеграції
- Аудит поточної LMS і вибір оптимального шлюзу.
- Проєктування схеми оплат (разові, підписки, розстрочка).
- Реалізація Checkout-сесій і webhook-обробників із покриттям усіх edge-кейсів.
- Інтеграція промокодів і корпоративних ліцензій.
- Створення таблиці транзакцій і зв'язок із користувачами.
- Навантажувальне тестування: перевірка до 1000 платежів на хвилину.
- Документація для розробників (схеми, конфіги, приклади коду).
- Навчання команди: 2 години воркшопу з управління платежами.
- 2 тижні технічної підтримки після введення в експлуатацію.
Як відбувається процес інтеграції?
- Аудит поточної LMS і вибір шлюзу (1 день).
- Проєктування схеми оплат (1–2 дні).
- Реалізація Checkout-сесій і webhook-обробників (2–3 дні).
- Інтеграція промокодів і корпоративних ліцензій (1–2 дні).
- Створення таблиці транзакцій і зв'язку з користувачами (1 день).
- Документація та навчання (1 день).
- Деплой і фінальне тестування (1 день).
Отримайте консультацію з інтеграції вашої LMS. Ми оцінимо поточну архітектуру та запропонуємо оптимальне рішення за 1 день. Зв'яжіться з нами, щоб обговорити ваш проєкт.
Ми гарантуємо стабільну роботу платіжної інтеграції: усі webhook-сценарії покриті тестами, а моніторинг сповіщає про помилки. Досвід 40+ проєктів підтверджує: наші рішення витримують пікові навантаження до 1000 платежів на хвилину.







