Реализация Split-платежей (расщепление оплаты) на сайте
Split-платежи — разбивка одной транзакции покупателя на несколько получателей одновременно. Типичный кейс — маркетплейс с 50 продавцами, где каждый заказ нужно разделить между продавцом, платформой и партнёрской программой. Без системы split-платежей бухгалтер тратит 3 часа в день на ручную разноску — с нашей реализацией время сокращается до 15 минут, а 95% возвратов обрабатываются автоматически. Другие сценарии: booking-сервис с комиссией агрегатора, подписка с revenue share между партнёрами.
Мы проектируем и реализуем split-платежи под ключ: от выбора провайдера до мониторинга и фискализации. Реализация занимает от 5 до 14 рабочих дней в зависимости от количества получателей, логики распределения и используемого платёжного провайдера. Закажите аудит вашей платёжной системы — найдём узкие места и предложим оптимальное решение.
Почему split-платежи требуют правильной архитектуры?
Некорректное расщепление приводит к финансовым расхождениям, проблемам с рефандами и налоговым рискам. Например, если не использовать transfer_group в Stripe, при возврате трансферы не отменяются автоматически, и деньги могут потеряться. Архитектура должна учитывать обработку ошибок, округление копеек и мониторинг. Наши инженеры с 10-летним опытом строят надёжные схемы, которые экономят до 20% времени на бухгалтерию.
Как выбрать модель расщепления?
Есть два принципиально разных подхода — Charge + Transfer и Direct Charge, и выбор между ними определяет всё остальное.
| Параметр | Charge + Transfer | Direct Charge |
|---|---|---|
| Движение денег | Средства приходят на счёт платформы, затем переводятся продавцам | Покупатель платит напрямую продавцу, платформа получает комиссию |
| Ответственность за KYC | Платформа обязана проверять продавцов | Продавцы проходят KYC самостоятельно |
| Контроль над рефандами | Платформа управляет возвратами централизованно | Возвраты — на стороне продавца, платформа может не участвовать |
| Сложность интеграции | Выше, требуется настройка webhook-ов и трансферов | Ниже, но нужна обработка application fee |
| Юридические риски | Выше (платформа — налоговый агент) | Ниже, но требуется договор с каждым продавцом |
Для большинства маркетплейсов на ранней стадии проще Charge + Transfer — меньше юридической сложности при онбординге продавцов.
Как работает Charge + Transfer в Stripe?
Stripe Connect — де-факто стандарт для split-платежей. Сначала создаём PaymentIntent на полную сумму, затем в обработчике webhook выполняем трансферы:
$paymentIntent = \Stripe\PaymentIntent::create([
'amount' => $order->total_cents,
'currency' => 'eur',
'payment_method_types' => ['card'],
'metadata' => [
'order_id' => $order->id,
'split_recipients' => json_encode($order->recipients),
],
]);
// В webhook-обработчике
public function handlePaymentSucceeded(array $payload): void
{
$intent = $payload['data']['object'];
$recipients = json_decode($intent['metadata']['split_recipients'], true);
foreach ($recipients as $recipient) {
\Stripe\Transfer::create([
'amount' => $recipient['amount_cents'],
'currency' => $intent['currency'],
'destination' => $recipient['stripe_account_id'],
'transfer_group' => $intent['transfer_group'],
'source_transaction' => $intent['charges']['data'][0]['id'],
]);
}
}
transfer_group связывает все трансферы с исходным платежом — это критично для корректного рефанда. source_transaction гарантирует, что трансфер выполняется только из средств конкретного платежа, а не из общего баланса. Подробнее о механизме — в документации Stripe Connect: Charge Transfers.
Хранение конфигурации расщепления
Правила split хранятся в БД, не в коде — иначе каждое изменение комиссии требует деплоя. Пример схемы: таблица split_rules с полями entity_type, entity_id, rule_type (percentage, fixed, remainder), value, priority. Расчёт долей происходит перед созданием трансферов, причём правило remainder должно быть ровно одно — это защита от округления и накопленных ошибок. Сумма долей обязана совпадать с total до копейки.
class SplitCalculator
{
public function calculate(int $totalCents, array $rules): array
{
$allocated = 0;
$result = [];
// Сначала фиксированные суммы
foreach ($rules as $rule) {
if ($rule['rule_type'] === 'fixed') {
$result[] = ['recipient' => $rule['entity_id'], 'amount' => $rule['value']];
$allocated += $rule['value'];
}
}
// Затем процентные
foreach ($rules as $rule) {
if ($rule['rule_type'] === 'percentage') {
$amount = (int) round($totalCents * $rule['value'] / 100);
$result[] = ['recipient' => $rule['entity_id'], 'amount' => $amount];
$allocated += $amount;
}
}
// Остаток — платформе или last-in-line получателю
$remainder = $totalCents - $allocated;
foreach ($rules as $rule) {
if ($rule['rule_type'] === 'remainder') {
$result[] = ['recipient' => $rule['entity_id'], 'amount' => $remainder];
break;
}
}
return $result;
}
}
Как обрабатывать возвраты при split-платежах?
Возврат при расщеплённом платеже — самое болезненное место. Stripe автоматически не отзывает трансферы при рефанде на PaymentIntent — это нужно делать явно. Алгоритм: 1) рефанд основного платежа, 2) реверс трансферов пропорционально сумме возврата. Если на аккаунте получателя недостаточно средств для реверса, Stripe вернёт ошибку — тогда требуется ручное дебетование.
public function refund(Order $order, int $refundCents): void
{
// 1. Рефанд основного платежа
\Stripe\Refund::create([
'payment_intent' => $order->stripe_payment_intent_id,
'amount' => $refundCents,
'refund_application_fee' => true,
]);
// 2. Реверс трансферов пропорционально
$ratio = $refundCents / $order->total_cents;
foreach ($order->transfers as $transfer) {
$reverseAmount = (int) round($transfer->amount_cents * $ratio);
\Stripe\Transfer::createReversal($transfer->stripe_transfer_id, [
'amount' => $reverseAmount,
'refund_application_fee' => true,
]);
}
}
Типичные ошибки при возвратах
- Забыли отменить
refund_application_fee– платформа теряет комиссию. - Неверно рассчитали пропорцию из-за округления – копеечные расхождения накапливаются.
- Не обработали частичный возврат, когда перевод уже реверсирован частично.
Альтернативы Stripe
| Провайдер | Модель split | Гибкость | Фискализация | Регион |
|---|---|---|---|---|
| Stripe Connect | Charge + Transfer / Direct Charge | Высокая | Требуется отдельная | Global |
| CloudPayments | Receipt с несколькими получателями | Средняя | Встроенная | СНГ |
| YooKassa Deal | Deal API | Средняя | Встроенная | РФ |
| Fondy | Партнёрский договор | Низкая | На стороне провайдера | Украина |
В среднем интеграция с Stripe Connect даёт на 30% больше контроля над транзакциями, чем аналоги CloudPayments, но требует больше времени на настройку. Выбор провайдера зависит от географии и требований к фискализации.
Что делать при расхождениях в мониторинге?
Каждый день запускается reconciliation job — сравнение сумм трансферов в БД с реальными трансферами в Stripe через API. Расхождения уходят в алерт. Это не паранойя — webhook-и иногда теряются, особенно при деплоях в момент транзакции. Настроив мониторинг, вы сократите финансовые потери от таких сбоев на 10–15%.
$stripeTransfers = \Stripe\Transfer::all([
'created' => ['gte' => $yesterday->timestamp, 'lt' => $today->timestamp],
'limit' => 100,
]);
$dbTransfers = Transfer::whereDate('created_at', $yesterday)->get()->keyBy('stripe_id');
foreach ($stripeTransfers->autoPagingIterator() as $transfer) {
if (!isset($dbTransfers[$transfer->id])) {
Log::critical('Untracked transfer', ['stripe_id' => $transfer->id, 'amount' => $transfer->amount]);
}
}
Что входит в работу по реализации split-платежей
- Анализ бизнес-логики и выбор оптимальной модели расщепления.
- Интеграция с платёжным провайдером (Stripe, CloudPayments, YooKassa).
- Настройка правил распределения и хранение в БД.
- Реализация обработки рефандов и реверсов трансферов.
- Настройка webhook-ов и мониторинга.
- Документация API и инструкции для бухгалтерии.
- Обучение команды работе с платёжной системой.
- Поддержка после запуска (1 месяц).
Налоговые и юридические аспекты
Расщепление платежа не освобождает платформу от фискальных обязательств — в большинстве юрисдикций платформа является налоговым агентом. Это означает передачу данных о выплатах в налоговые органы (в РФ — ФНС, в ЕС — DAC7 reporting). Нужно учитывать это при проектировании схемы split ещё на старте — переделывать потом дороже. Обратите внимание на требования DAC7 Directive при работе в Европе.
Свяжитесь с нами для оценки вашего проекта — мы поможем выбрать оптимальное решение и реализуем его в кратчайшие сроки. Наш опыт — 5+ лет в разработке платёжных систем, более 15 успешных проектов с split-платежами. Получите консультацию уже сегодня.







