Реалізація донатів/подарунків під час прямої трансляції в мобільному додатку

TRUETECH займається розробкою, підтримкою та обслуговуванням мобільних додатків iOS, Android, PWA. Маємо великий досвід та експертизу для публікації мобільних додатків до популярних маркетів Google Play, App Store, Amazon, AppGallery та інші.

Розробка та підтримка будь-яких видів мобільних додатків:

Інформаційні та розважальні мобільні програми
Новинки, ігри, довідники, онлайн-каталоги, погодні, фітнес та здоров'я, туристичні, освітні, соціальні мережі та месенджери, квіз, блоги та подкасти, форуми, агрегатори
Мобільні програми електронної комерції
Інтернет-магазини, B2B-додатки, маркетплейси, онлайн-обмінники, кешбек-сервіси, біржі, дропшиппінг-платформи, програми лояльності, доставка їжі та товарів, платіжні системи
Мобільні програми для управління бізнес-процесами
CRM-системи, ERP-системи, управління проектами, інструменти для команди продажів, облік фінансів, управління виробництвом, логістика та доставка, управління персоналом, системи моніторингу даних
Мобільні програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, платформи надання електронних послуг, платформи кешбеку, відеохостинги, тематичні портали, платформи онлайн-бронювання та запису, платформи онлайн-торгівлі

Це лише деякі з типів мобільних додатків, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1735 послуг
Реалізація донатів/подарунків під час прямої трансляції в мобільному додатку
Середній
~5 днів
Часті запитання

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

Етапи розробки

Останні роботи

  • image_mobile-applications_feedme_467_0.webp
    Розробка мобільного додатка для компанії FEEDME
    792
  • image_mobile-applications_xoomer_471_0.webp
    Розробка мобільного додатку для компанії XOOMER
    671
  • image_mobile-applications_rhl_428_0.webp
    Розробка мобільного додатку для компанії RHL
    1097
  • image_mobile-applications_zippy_411_0.webp
    Розробка мобільного додатку для компанії ZIPPY
    969
  • image_mobile-applications_affhome_429_0.webp
    Розробка мобільного додатку для компанії Affhome
    914
  • image_mobile-applications_flavors_409_0.webp
    Розробка мобільного додатку для компанії FLAVORS
    495

Реалізація донатів/подарунків під час прямої трансляції в мобільному додатку

Донати в стрімі — це не просто платіж. Це real-time подія: користувач надіслав подарунок → анімація пролітає поверх відео → глядачі бачать ім'я донатера в ленті → стример отримує сповіщення. Між натисканням кнопки та появою анімації має пройти менше секунди. Це вимагає продуманої інтеграції: платіжний процесор → бекенд → WebSocket → клієнт.

Архітектура: три паралельні потоки

Донат проходить через три незалежні шари одночасно:

  1. Платіжний потік — списання через Stripe/IAP/Google Play Billing з підтвердженням
  2. Real-time потік — WebSocket-подія всім глядачам трансляції
  3. Лента донатів — оновлення UI-счетчика та скрол-лога

Помилка в одному потоці не повинна блокувати інші. Анімація подарунка показується після підтвердження платежу, не до.

Віртуальна валюта: чому не прямі платежі

Більшість стриминг-додатків використовують віртуальну валюту (монети, кристали) замість прямих транзакцій:

  • App Store та Google Play беруть 30% з in-app покупок, але віртуальна валюта дозволяє розділити покупку монет (IAP) та трату монет (серверна логіка) — списання відбувається на сервері, App Store не бере участі
  • Користувач купує пачку монет через IAP, витрачає у будь-який час — асинхронно від платіжного флоу
  • Агрегація дрібних донорів: надіслати 5 рублів напрямку — дорого за комісіями, надіслати 5 монет з куплених раніше — дешево
// Покупка монет через Google Play Billing
val productDetails = // загруженi через BillingClient.queryProductDetailsAsync

val billingFlowParams = BillingFlowParams.newBuilder()
    .setProductDetailsParamsList(
        listOf(
            BillingFlowParams.ProductDetailsParams.newBuilder()
                .setProductDetails(productDetails)
                .build()
        )
    )
    .build()

billingClient.launchBillingFlow(activity, billingFlowParams)

Типи подарунків: об'єкт GiftItem

data class GiftItem(
    val id: String,
    val name: String,           // "Роза", "Ракета", "Корона"
    val coinCost: Int,          // вартість в монетах
    val animationUrl: String,   // Lottie JSON або MP4
    val displayDurationMs: Long // як довго показувати анімацію
)

Анімації подарунків — Lottie (JSON, ~50-200 KB) або короткі MP4 (~500 KB). Lottie краще: масштабується без артефактів, підтримує прозорість, не потребує медіа-декодера.

Real-time: WebSocket подія подарунка

Після списання монет на сервері (атомарна операція в БД) — публікуємо подію в WebSocket-канал трансляції:

{
  "type": "gift",
  "streamId": "stream-abc123",
  "senderId": "user-456",
  "senderName": "Олексій",
  "senderAvatar": "https://cdn.example.com/avatars/456.jpg",
  "giftId": "gift-rocket",
  "giftName": "Ракета",
  "coinAmount": 50,
  "timestamp": "2024-06-15T14:30:01.234Z"
}

Сервер повинен перевірити баланс монет перед публікацією. Ніколи не довіряйте клієнту: клієнт говорить «відправити ракету за 50 монет» → сервер перевіряє баланс, списує, потім публікує подію. Не навпаки.

Клієнт: черга анімацій

Кілька глядачів можуть одночасно надіслати подарунки. Не можна показувати всі анімації паралельно — екран перетворюється на хаос. Потрібна черга:

class GiftAnimationQueue {
    private var queue: [GiftEvent] = []
    private var isPlaying = false

    func enqueue(_ event: GiftEvent) {
        queue.append(event)
        if !isPlaying { playNext() }
    }

    private func playNext() {
        guard !queue.isEmpty else { isPlaying = false; return }
        isPlaying = true
        let event = queue.removeFirst()

        showGiftAnimation(event) { [weak self] in
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
                self?.playNext()
            }
        }
    }

    private func showGiftAnimation(_ event: GiftEvent, completion: @escaping () -> Void) {
        let animationView = LottieAnimationView(name: event.giftId)
        animationView.frame = overlayView.bounds
        overlayView.addSubview(animationView)

        animationView.play { _ in
            animationView.removeFromSuperview()
            completion()
        }
    }
}

На Android аналогічна черга через Lottie AnimationView та LinkedList<GiftEvent> з Handler.

Лента донатів: RecyclerView з prepend

Нові донати додаються на початок списку, не в кінець:

class DonationAdapter : RecyclerView.Adapter<DonationViewHolder>() {
    private val donations = mutableListOf<DonationItem>()

    fun prepend(donation: DonationItem) {
        donations.add(0, donation)
        notifyItemInserted(0)
        recyclerView.scrollToPosition(0)
    }
}

Обробка offline-глядачів

Глядачі можуть переподключитися в середині трансляції. При переподключенні не потрібно відтворювати всі пропущені анімації — показуємо лише лог донатів текстом та останні N подій.

Топ донатерів: агрегація в реальному часі

// Redis ZSET для топ донатерів трансляції
// ZINCRBY stream:{streamId}:donations {coinAmount} {userId}
// ZREVRANGE stream:{streamId}:donations 0 9 WITHSCORES — топ 10

Оновлюється при кожному донаті, розсилається всім глядачам щокожні 5–10 секунд через окремий WebSocket-канал.

Що входить в роботу

  • Серверна логіка списання монет (атомарна транзакція)
  • WebSocket-рассилка подій всім глядачам
  • Черга анімацій подарунків на клієнті (Lottie)
  • Лента донатів з prepend-логікою
  • Топ донатерів в реальному часі
  • Обробка reconnect та відновлення стану

Тривалість

5 днів. Серверна частина з WebSocket та біллінгом монет — 2 дні. Клієнтська частина з анімаціями та лентою — 2 дні. Інтеграція, тестування, edge cases — 1 день. Вартість розраховується індивідуально.