Deux statuts de commande supplémentaires suffisent à modéliser l’attente d’un versement différé sur une place de marché B2B agricole : un pour la commission calculée mais non reversée, un pour la confirmation de livraison qui déclenche enfin le paiement au producteur. Le délai réel de rétention dépend d’un accord contractuel précis — souvent cette confirmation de livraison par l’acheteur professionnel — mais le code doit modéliser cette attente sans jamais perdre la trace d’un versement en cours, y compris en cas d’incident technique entre-temps.
Ce cas construit une extension pour une coopérative qui monte une place de marché entre producteurs agricoles et acheteurs professionnels : chaque vente génère une commission pour la coopérative, et le solde n’est reversé au producteur qu’après confirmation de la livraison. Cet article ne traite pas la logistique de livraison elle-même, uniquement le calcul et le suivi du versement.
Modéliser la commande comme une répartition, pas un simple montant
Sur une place de marché, une commande WooCommerce classique ne suffit pas à elle seule : il faut associer à chaque ligne de commande le producteur concerné et le taux de commission applicable, potentiellement différent d’un producteur à l’autre selon son ancienneté dans la coopérative.
add_action( 'woocommerce_new_order_item', function ( $item_id, $item, $order_id ) {
$producteur_id = $item->get_product()->get_meta( '_producteur_id' );
$taux_commission = get_user_meta( $producteur_id, 'taux_commission', true ) ?: 0.08;
wc_add_order_item_meta( $item_id, '_producteur_id', $producteur_id );
wc_add_order_item_meta( $item_id, '_taux_commission', $taux_commission );
wc_add_order_item_meta( $item_id, '_montant_commission', $item->get_total() * $taux_commission );
}, 10, 3 );
Introduire un statut de versement distinct du statut de commande

Le statut de la commande (payée, en préparation, expédiée) ne doit pas être confondu avec le statut du versement au producteur, qui suit son propre cycle : en attente de livraison confirmée, prêt à verser, versé. Deux statuts personnalisés suffisent à couvrir ce besoin, enregistrés comme une métadonnée dédiée sur chaque ligne de commande plutôt que déduits indirectement du statut global.
function definir_statuts_versement() {
return [
'en_attente_livraison' => 'En attente de confirmation de livraison',
'pret_a_verser' => 'Prêt à verser au producteur',
];
}
add_action( 'woocommerce_order_status_completed', function ( $order_id ) {
$commande = wc_get_order( $order_id );
foreach ( $commande->get_items() as $item_id => $item ) {
wc_update_order_item_meta( $item_id, '_statut_versement', 'pret_a_verser' );
}
} );
Générer le relevé individuel de chaque producteur
Un producteur n’a aucun intérêt à consulter un total global de la marketplace : il a besoin d’un relevé qui ne concerne que ses propres ventes, avec le détail de la commission retenue et la date prévisionnelle de versement. Une route REST dédiée, accessible uniquement au producteur concerné, expose ce relevé sans exposer les données des autres adhérents.
register_rest_route( 'marketplace/v1', '/mon-releve', [
'methods' => 'GET',
'permission_callback' => fn() => is_user_logged_in(),
'callback' => function () {
$producteur_id = get_current_user_id();
global $wpdb;
$lignes = $wpdb->get_results( $wpdb->prepare(
"SELECT order_item_id, meta_value AS montant_commission
FROM {$wpdb->prefix}woocommerce_order_itemmeta
WHERE meta_key = '_montant_commission'
AND order_item_id IN (
SELECT order_item_id FROM {$wpdb->prefix}woocommerce_order_itemmeta
WHERE meta_key = '_producteur_id' AND meta_value = %d
)",
$producteur_id
) );
return $lignes;
},
] );
Automatiser le versement une fois le seuil franchi
Une tâche planifiée quotidienne parcourt les lignes de commande au statut pret_a_verser et déclenche le virement réel via l’API de paiement du prestataire utilisé pour les versements aux producteurs, avant de marquer la ligne comme définitivement versée. Ce point d’intégration reste le seul appel à un service tiers dans cette architecture, le calcul et le suivi restant entièrement internes.
add_action( 'traiter_versements_quotidiens', function () {
$lignes_pretes = recuperer_lignes_par_statut( 'pret_a_verser' );
foreach ( $lignes_pretes as $ligne ) {
$resultat = declencher_virement_producteur( $ligne->producteur_id, $ligne->montant_net );
if ( $resultat['succes'] ) {
marquer_ligne_versee( $ligne->id );
}
}
} );
Notre verdict
Une place de marché B2B entre producteurs et acheteurs professionnels n’a pas besoin d’un système de paiement fractionné complexe si l’essentiel repose sur un principe simple : chaque ligne de commande porte son propre statut de versement, indépendant du statut global de la commande, et une tâche planifiée applique ce cycle sans intervention manuelle. Le point de vigilance reste la traçabilité : un producteur doit toujours pouvoir retrouver, ligne par ligne, pourquoi un versement est encore en attente plutôt que déjà réalisé.