Перейти к содержимому

CrewsForge — Шаг 5a: Мультипровайдерные выплаты (дополнение)

Статус: проектная записка, реализация отложена до решения-триггера · Дата: 2026-08-21 Вопрос Stark: можем ли мы добавлять платёжных провайдеров, расширяющих список стран выплат командам

1. Постановка: проблема только на выплатной стороне

Заголовок раздела «1. Постановка: проблема только на выплатной стороне»

Приём денег (фаундеры: US/UK/EU/SG/UAE) Stripe закрывает — мультипровайдерность там не нужна. Проблема — выплаты командам в странах вне Stripe-контура. Актуальное состояние Stripe (проверено 2026-08-21):

  • Connect-выплаты (наша текущая модель): платформа US ↔ получатели только в US/UK/EEA/CA/CH. Комплаенс — на лицензии Stripe.
  • Global Payouts (US/UK платформы): выплаты в существенно более широкий список стран (активно расширяется), но комплаенс — на нас, с прямым предупреждением о возможной необходимости MTL.
  • Украина: в Connect-регионы не входит; присутствие в актуальном списке Global Payouts — проверить в дашборде/у sales на момент решения (список меняется ежеквартально).

Любое расширение стран (хоть Stripe Global Payouts, хоть сторонний провайдер) меняет денежный поток с «всё внутри Stripe» на «средства покидают Stripe-баланс и уходят через казначейство платформы» — и лицензионный вопрос открывается заново.

Наша защита — топология K-1: между фаундером и командой нет договора; платформа получает деньги как сторона договора B (собственная выручка/обязательство) и платит команде как сторона договора A (собственный долг подрядчику). Это ordinary course of business, не передача чужих средств. Milestone-гейтинг усложняет картину (удержание до события похоже на эскроу-паттерн — тем важнее терминологическая дисциплина 7.6).

В пакет юристу, пункт 6 расширяется: не «проверить список стран Stripe», а «дать заключение по трём конструкциям выплат: (а) Connect-регионы (текущая), (б) Stripe Global Payouts, (в) сторонний payout-провайдер (Payoneer/Wise) — с оценкой MTL-экспозиции каждой при нашей договорной топологии».

ПровайдерПрофильКомплаенс-модель
Stripe Global PayoutsТот же вендор, Accounts v2, список стран растётКомплаенс на нас (см. §2)
Payoneer (mass payouts)Отраслевой стандарт выплат фрилансерам (модель Upwork/Fiverr), сильное покрытие Восточной Европы, получатели массово уже имеют аккаунтыPayoneer — регулируемый MSB; платформа фондирует свой аккаунт, disbursement делает Payoneer
Wise PlatformШирокое покрытие, прозрачный FX, API выплатWise — регулируемый провайдер; аналогично

Предварительный порядок предпочтения при срабатывании триггера: Payoneer (сетевой эффект у получателей-фрилансеров) → Wise → Global Payouts (в зависимости от заключения юриста — Global Payouts может оказаться и лучшим, и худшим вариантом именно юридически).

Модель готовилась к этому (PayoutAccount.provider); фиксируем контракт порта — на бумаге сейчас, в коде при триггере:

interface PayoutProvider {
initRecipientOnboarding(team, party): Promise<{ externalAccountId, onboardingUrl? }>;
getAccountState(externalAccountId): Promise<PayoutAccountState>; // маппинг в NOT_STARTED/PENDING/RESTRICTED/ACTIVE
executePayout(req: { settlementId, externalAccountId, amountMinor, currency, idempotencyKey }): Promise<{ externalRef }>;
parseStatusEvent(raw): PayoutStatusEvent; // sent | arrived | failed (гранулярность зависит от провайдера)
supportedCountries(): string[]; // для маршрутизации при онбординге
}

Принципы:

  1. Асимметрия жёсткая: мультипровайдерность — только выплатная сторона. Приём (Checkout), рефанды (спор в пользу фаундера — всегда refund исходного charge в Stripe) и сплит-refund-нога провайдеро-независимы и не трогаются. Меняется только транспорт transfer-ноги.
  2. Одна команда — один активный провайдер, выбирается маршрутизацией по стране при онбординге (конфиг-таблица). Смена провайдера — операция администратора с закрытием старого аккаунта.
  3. Машины не меняются. PayoutAccount-состояния и Hold-цикл провайдеро-независимы; guard Y-1 (ACTIVE) работает как есть. Settlement получает снапшот payoutProvider + transferExternalId становится провайдер-специфичным ref (дельта схемы при реализации).
  4. RELEASED честен в меру провайдера: где провайдер отдаёт «arrived» — ждём его; где только «sent» — RELEASED по «sent» с задокументированной деградацией строгости 7.3 для этого провайдера (в UI формулировка «отправлено банком-партнёром»).
ПотеряСледствие
source_transaction-инвариантВыплата идёт не из привязки к charge, а из казначейства платформы: Stripe-баланс → банк платформы → провайдер → команда. Появляется казначейский float (деньги должны быть на счёте платформы к моменту выплаты) и тайминг-зазор ~2 дня
Единый леджерНужен казначейский суб-леджер: сверка (шаг 5.7) получает вторую ногу — «выплачено через провайдера X = Σ соответствующих Settlement.team_amount»; комиссия остаётся на Stripe-балансе и сводится отдельно
Простота RELEASINGОкно «в пути» удлиняется (банк платформы + рельсы провайдера); уведомления 7.3 получают провайдер-специфичные шаблоны
Один вебхук-контур+ endpoint и дедуп-провайдер в WebhookEvent (enum расширяется)

Оценка эпика при реализации: L (порт + первый адаптер + казначейский суб-леджер + сверка + маршрутизация онбординга).

Сейчас не строим. Триггеры реализации (любой из):

  1. Юрист даёт зелёный свет одной из конструкций §2 и подтверждённый спрос: ≥2 качественные команды-кандидаты, которых нельзя обслужить в Connect-регионах;
  2. Стратегическое решение открыть supply-географию до публичной беты.

Мост на бету без второго провайдера: команды с юрлицами в Connect-регионах (US/UK/EEA/CA/CH) — у сильных восточноевропейских команд юрлица в Эстонии/Польше/US типичны; это же снимает вопрос для украинских команд с иностранными entity. Требование юрлица в поддержанной юрисдикции — фильтр онбординга беты, честно коммуницируемый.