add_action('woocommerce_payment_complete', 'proceseaza_split_stripe_connect');
function proceseaza_split_stripe_connect($order_id) {
$order = wc_get_order($order_id);
$vendor_totals = [];
foreach ($order->get_items() as $item) {
$product = $item->get_product();
$vendor_id = get_post_field('post_author', $product->get_id());
$stripe_account = get_user_meta($vendor_id, '_stripe_connect_account_id', true);
if (!$stripe_account) continue;
$vendor_totals[$stripe_account] = ($vendor_totals[$stripe_account] ?? 0) + $item->get_total();
}
foreach ($vendor_totals as $account_id => $amount) {
$payout_cents = (int) round(($amount * 0.88) * 100); // 12% comision platformă
\Stripe\Transfer::create([
'amount' => $payout_cents,
'currency' => 'ron',
'destination' => $account_id,
'source_transaction' => $order->get_transaction_id(),
'metadata' => ['order_id' => $order_id],
]);
}
}Anul trecut am rescris fluxul de plăți pentru un marketplace pe WooCommerce cu 45 de producători locali și în jur de 1.800 de comenzi lunare. Dacă lași plugin-urile generice de multi-vendor să gestioneze banii din cutie, fără să înțelegi ce se întâmplă în Stripe, ajungi rapid să plătești comisioane și refund-uri din buzunarul tău.
Marea problemă cu WooCommerce într-un scenariu marketplace apare în momentul în care un client cumpără de la trei vendori diferiți în aceeași comandă.
Destination Charges vs Separate Charges and Transfers
Stripe Connect îți oferă practic două opțiuni mari când vrei să împarți banii. Prima opțiune este Destination Charges: clientul plătește, platforma oprește un comision (application_fee_amount), iar restul sumei pleacă automat direct în contul conectat al vendorului. Sună ideal, dar are o limitare masivă: nu poți specifica mai multe destinații pe un singur PaymentIntent.
Dacă ai coșuri mixte cu produse de la producători diferiți, Destination Charges pică din start. Singura arhitectură viabilă rămâne Separate Charges and Transfers.
Fluxul funcționează așa: platforma încasează suma integrală a comenzii pe contul principal. Imediat ce plata a fost confirmată, scriptul tău parsează linia de comandă WooCommerce, grupează sumele pe fiecare vendor, calculează comisionul platformei (noi am mers pe 12% fix) și inițiază un apel separat de Stripe\Transfer::create pentru fiecare cont conectat.
Capcana de care ne-am lovit: refund-urile parțiale
Trade-off-ul major la Separate Charges este că platforma ta devine merchant of record legal și financiar. Dacă un vendor livrează marfă stricată și clientul cere banii înapoi pe un singur produs, Stripe nu ia banii înapoi magic din contul vendorului.
Am pățit-o chiar în prima lună: am procesat un refund din panoul WooCommerce, platforma a returnat 150 de lei cumpărătorului, dar transferul către vendor rămăsese intact. Vendorul primise deja banii, noi rămăsesem cu gaura. Soluția este să agăți un hook pe woocommerce_order_partially_refunded care să execute explicit un TransferReversal prin Stripe API pe transferul inițial, altfel contabilul o să te caute cu furca.
De asemenea, folosește conturi Express sau Custom, nu Standard. Cu Standard, vendorul controlează prea mult din experiență și nu poți automatiza retragerile sau debita soldul negativ atât de ușor dacă apar dispute.
Unde legăm logica în WooCommerce
Nu te baza pe statusul completed al comenzii pentru a împărți banii, fiindcă mulți vendori uită să schimbe statusul fizic al livrării. Noi legăm logica de split direct pe hook-ul woocommerce_payment_complete. În felul ăsta, transferul se calculează imediat ce banii sunt garantați, iar fiecare transfer_id returnat de Stripe este salvat în meta-ul fiecărui order item pentru trasabilitate completă.