Реализация 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-платежами. Получите консультацию уже сегодня.







