Разработка мобильного приложения для краудфандинга
Несколько лет назад одна из наших платформ для краудфандинга столкнулась с проблемой: в последний час кампании число одновременных запросов на оформление бэкингов выросло в 10 раз, и база данных не справилась с транзакциями — часть платежей повисла в статусе pending, бэкеры получили двойные списания. После аудита мы переписали механизм авторизации и добавили шардирование по project_id. Эта ошибка стоила клиенту значительных репутационных потерь — и помогла нам отточить архитектуру, которую теперь используем во всех проектах. В статье разберём ключевые компоненты, которые превращают MVP в production-grade платформу: от escrow-моделей до быстрых выплат. Опираемся на опыт 50+ финтех- и маркетплейс-решений.
Как реализовать надёжное условное списание средств?
All-or-Nothing (AoN) — средства списываются только при достижении цели. Если кампания не собрала нужную сумму — все платежи возвращаются. Реализация: при бэкинге делаем authorization hold на карте (средства заморожены, но не списаны). При успехе кампании — capture, при провале — void.
# Stripe: создание PaymentIntent с capture_method=manual
import stripe
def back_project(user_id: str, project_id: str, amount: int, reward_tier_id: str) -> dict:
payment_intent = stripe.PaymentIntent.create(
amount=amount,
currency="usd",
capture_method="manual", # не списывать сразу
metadata={
"user_id": user_id,
"project_id": project_id,
"reward_tier_id": reward_tier_id
},
confirm=False # подтвердим на клиенте
)
return {"client_secret": payment_intent.client_secret}
def capture_all_backers(project_id: str):
"""Вызывается при успешном завершении кампании"""
backers = db.get_backers(project_id, status="authorized")
for backer in backers:
stripe.PaymentIntent.capture(backer.payment_intent_id)
db.update_backer_status(backer.id, "captured")
def refund_all_backers(project_id: str):
"""Вызывается при провале кампании"""
backers = db.get_backers(project_id, status="authorized")
for backer in backers:
stripe.PaymentIntent.cancel(backer.payment_intent_id)
db.update_backer_status(backer.id, "cancelled")
Проблема: авторизация на карте действует ограниченный срок — у Stripe это 7 дней для большинства карт, максимум 31 деньStripe Documentation: "Authorization holds". Кампании длиннее 30 дней — нельзя удерживать авторизацию всё это время. Решение: списывать сразу (Keep-it-All модель) или выполнять повторную авторизацию незадолго до истечения.
Keep-it-All (KiA) — средства списываются сразу при бэкинге, независимо от достижения цели. Технически проще, но менее привлекательна для бэкеров. Популярна для благотворительных и творческих проектов. По данным Statista, AoN-кампании собирают в среднем на 40% больше средств, чем KiA, поэтому для коммерческих проектов мы рекомендуем именно первую модель.
| Параметр | All-or-Nothing | Keep-it-All |
|---|---|---|
| Момент списания | При успехе кампании | Сразу при бэкинге |
| Доверие бэкеров | Высокое | Среднее |
| Сложность реализации | Высокая (авторизация, таймауты) | Низкая |
| Подходит для | Коммерческие проекты | Благотворительность, творчество |
Почему AoN предпочтительнее для больших проектов?
По данным Stripe, около 70% успешных краудфандинговых кампаний используют AoN. Бэкеры чувствуют себя увереннее, зная что их деньги не пропадут, если цель не будет достигнута.Уровни вознаграждений (Reward Tiers)
Каждый проект предлагает несколько уровней: «Поддержать» за $10, «Ранний доступ» за $50, «Эксклюзивный набор» за $200. У каждого уровня — количество доступных слотов и текущая заполненность.
// iOS: экран выбора уровня вознаграждения
struct RewardTierView: View {
let tier: RewardTier
let onSelect: () -> Void
var body: some View {
VStack(alignment: .leading, spacing: 8) {
HStack {
Text("$\(tier.amount)")
.font(.title2.bold())
Spacer()
if let limit = tier.backerLimit {
Text("\(tier.backerCount)/\(limit) поддержали")
.font(.caption)
.foregroundColor(tier.isSoldOut ? .red : .secondary)
}
}
Text(tier.title).font(.headline)
Text(tier.description).font(.body).foregroundColor(.secondary)
if let estimatedDelivery = tier.estimatedDelivery {
Label("Доставка: \(estimatedDelivery)", systemImage: "shippingbox")
.font(.caption)
}
Button(tier.isSoldOut ? "Разобрано" : "Выбрать уровень") {
if !tier.isSoldOut { onSelect() }
}
.disabled(tier.isSoldOut)
}
.padding()
.background(.regularMaterial)
.clipShape(RoundedRectangle(cornerRadius: 12))
}
}
Ограниченные слоты требуют pessimistic locking на сервере: при оформлении бэкинга блокируем строку reward_tier для проверки и декремента счётчика в одной транзакции.
Прогресс кампании и социальная механика
Страница проекта — центральный контент. Прогресс-бар собранных средств, обратный отсчёт до конца кампании, лента обновлений от автора, комментарии бэкеров.
Технически самый нагруженный момент: последний день кампании. Все бэкеры проверяют прогресс одновременно. WebSocket для реального времени или aggressive polling (каждые 10 секунд в последние часы) — с кешированием на CDN.
// Android: WebSocket для живого обновления прогресса
class CampaignProgressViewModel(
private val campaignId: String,
private val wsClient: WebSocketClient
) : ViewModel() {
val progress = MutableStateFlow<CampaignProgress?>(null)
init {
wsClient.connect("wss://api.yourplatform.com/campaigns/$campaignId/live")
viewModelScope.launch {
wsClient.messages.collect { message ->
val update = json.decodeFromString<CampaignProgressUpdate>(message)
progress.value = update.progress
}
}
}
override fun onCleared() {
wsClient.disconnect()
}
}
Обновления проекта и коммуникация с бэкерами
Автор публикует обновления о ходе работ. Бэкеры получают push-уведомления о каждом новом обновлении. Сегментация: уведомление только тем, кто поддержал именно этот проект.
FCM topic-based messaging для этого не подходит — нужна таргетированная рассылка через серверный список получателей. Для каждого проекта хранится список device_tokens бэкеров.
Как проходит верификация авторов (KYC) и почему это критически важно?
Публичный сбор средств привлекает мошеннические проекты. Базовая защита:
- Ручная модерация новых проектов перед публикацией
- Верификация личности автора через KYC (паспорт + селфи) — обязательна для вывода средств
- Автоматическое ограничение на вывод до подтверждения KYC
Процесс верификации пошагово:
- Автор заполняет профиль в приложении.
- Нажимает "Пройти верификацию" — система генерирует accessToken для KYC-провайдера.
- Открывается нативный SDK (Sumsub, Veriff или Onfido), где автор делает фото паспорта и селфи.
- SDK передаёт данные провайдеру, который проверяет документы и возвращает статус.
- Если статус
approved, автор может запросить вывод средств. Еслиrejected— отправляется на повторную проверку с комментарием.
Интеграция с KYC-провайдерами: Sumsub, Veriff, Onfido. Мобильное приложение инициирует KYC через SDK провайдера — процесс полностью в нативном UI. Гарантируем безопасность данных — все SDK сертифицированы.
// iOS: Sumsub KYC flow
import IdensicMobileSDK
let sdk = SNSMobileSDK.build(
accessToken: kycAccessToken
)
.withHandlers(
onStatusDidChange: { [weak self] sdk, prevStatus in
if sdk.mainState == .approved {
self?.onKYCApproved()
}
},
onEvent: { sdk, event in }
)
.assemble()
sdk.present(from: self)
Вывод средств для авторов
После успешного завершения кампании автор хочет получить деньги. Схема вывода:
- KYC пройден → можно запросить вывод
- Платформа удерживает комиссию (обычно 5–10%)
- Остаток выводится через Stripe Connect (payout на банковский счёт) или международным переводом
Stripe Connect — стандарт для маркетплейсов с выплатами. Каждый автор — отдельный Connected Account.
Что входит в нашу работу
- Аналитика требований и проектирование архитектуры
- Разработка под iOS (Swift 5.9+, SwiftUI) и Android (Kotlin, Jetpack Compose)
- Интеграция платежей (Stripe, Braintree) и KYC-провайдеров
- Настройка push-уведомлений (FCM/APNs), deep linking, App Tracking Transparency
- Модерация контента и anti-fraud алгоритмы
- Деплой в App Store и Google Play, тесты и поддержка
Ориентиры по срокам
| Scope | Срок |
|---|---|
| Базовая версия: просмотр и поддержка проектов, оплата, история | 6–8 недель |
| Кабинет автора: создание проектов, обновления, аналитика | +3–4 недели |
| All-or-Nothing с escrow и автоматическим capture/refund | +2 недели |
| KYC и вывод через Stripe Connect | +2–3 недели |
Стоимость рассчитывается индивидуально после анализа требований. Чтобы обсудить детали вашего проекта, оставьте заявку — мы свяжемся в течение дня. Получите консультацию по архитектуре — наши инженеры помогут выбрать оптимальное решение.







