vendredi 25 septembre 2026

À propos

Contact

E-commerce

Créer une passerelle de paiement WooCommerce personnalisée avec WC_Payment_Gateway

Étapes concrètes pour écrire un plugin de passerelle de paiement WooCommerce à partir de la classe abstraite WC_Payment_Gateway, du formulaire au traitement de la commande.

Par Clément Hadrot • 2 décembre 2020 • 5 min de lecture • Aucun commentaire
Créer une passerelle de paiement WooCommerce personnalisée avec WC_Payment_Gateway

Un client vendait des prestations sur devis et voulait accepter un mode de règlement particulier, un virement instantané via un prestataire bancaire régional non couvert par les extensions habituelles. Plutôt que d’attendre un plugin tiers hypothétique, la solution la plus robuste a été d’écrire une passerelle de paiement sur mesure. WooCommerce rend cet exercice tout à fait accessible dès lors qu’on comprend la classe abstraite WC_Payment_Gateway.

Ce n’est pas réservé aux grandes intégrations bancaires : de nombreux besoins spécifiques (paiement sur facture, acompte, règlement en espèces à la livraison avec confirmation manuelle) se traitent très bien avec une passerelle personnalisée légère, sans dépendre d’un service tiers.

La structure minimale d’un plugin de passerelle

Une passerelle de paiement WooCommerce est un plugin classique qui s’accroche au filtre woocommerce_payment_gateways pour s’enregistrer, puis définit une classe étendant WC_Payment_Gateway :

add_filter( 'woocommerce_payment_gateways', function ( $gateways ) {
    $gateways[] = 'WC_Gateway_Virement_Express';
    return $gateways;
} );

add_action( 'plugins_loaded', function () {
    class WC_Gateway_Virement_Express extends WC_Payment_Gateway {
        public function __construct() {
            $this->id                 = 'virement_express';
            $this->icon               = '';
            $this->has_fields         = false;
            $this->method_title       = 'Virement Express';
            $this->method_description = 'Paiement par virement bancaire instantané.';

            $this->init_form_fields();
            $this->init_settings();

            $this->title       = $this->get_option( 'title' );
            $this->description = $this->get_option( 'description' );
            $this->enabled      = $this->get_option( 'enabled' );

            add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, [ $this, 'process_admin_options' ] );
        }
    }
} );

Déclarer les champs de configuration

La méthode init_form_fields() définit ce qui apparaît dans WooCommerce > Réglages > Paiements pour cette passerelle : activation, titre affiché au client, description, et tout champ spécifique au prestataire (identifiant marchand, clé API, mode test) :

public function init_form_fields() {
    $this->form_fields = [
        'enabled' => [
            'title'   => 'Activer',
            'type'    => 'checkbox',
            'label'   => 'Activer le virement express',
            'default' => 'no',
        ],
        'title' => [
            'title'       => 'Titre',
            'type'        => 'text',
            'default'     => 'Virement bancaire instantané',
        ],
        'description' => [
            'title'   => 'Description',
            'type'    => 'textarea',
            'default' => 'Réglez votre commande par virement instantané, confirmation sous quelques minutes.',
        ],
    ];
}
L'essentiel à retenir : WC_Payment_Gateway impose un ensemble de méthodes précises à implémenter ; Le champ de configuration et le traitement de commande sont deux responsabilités distinctes ; Les statuts de commande doivent refléter l'état réel du paiement, jamais un raccourci

Traiter le paiement au moment de la commande

Le cœur de la passerelle est la méthode process_payment( $order_id ), appelée quand le client valide sa commande. C’est elle qui décide du statut de la commande et de la redirection :

public function process_payment( $order_id ) {
    $order = wc_get_order( $order_id );

    // Marque la commande en attente de confirmation du virement
    $order->update_status( 'on-hold', 'En attente de réception du virement express.' );

    // Réduit le stock immédiatement, comportement à adapter selon le besoin métier
    wc_reduce_stock_levels( $order_id );

    // Vide le panier
    WC()->cart->empty_cart();

    return [
        'result'   => 'success',
        'redirect' => $this->get_return_url( $order ),
    ];
}

Le choix du statut de commande n’est jamais anodin. on-hold convient à un paiement dont la confirmation est différée ; processing convient à un paiement confirmé immédiatement mais nécessitant une préparation ; completed ne devrait être utilisé que lorsque la commande est réellement finalisée (livraison ou service rendu), jamais comme raccourci pour « paiement reçu ».

Confirmer le paiement de façon asynchrone

Pour un prestataire qui notifie le paiement via un webhook, il faut exposer un point d’entrée dédié. WooCommerce fournit pour cela l’action générique woocommerce_api_{id-de-la-passerelle}, déclenchée sur une URL du type https://exemple.fr/wc-api/virement_express/ :

add_action( 'woocommerce_api_virement_express', function () {
    $order_id = isset( $_GET['order_id'] ) ? absint( $_GET['order_id'] ) : 0;
    $order    = wc_get_order( $order_id );

    if ( $order && $this->verifier_signature_webhook() ) {
        $order->payment_complete();
    }

    status_header( 200 );
    exit;
} );

La vérification de la signature du webhook n’est pas optionnelle : sans elle, n’importe qui connaissant l’URL pourrait déclencher une confirmation de paiement frauduleuse. Chaque prestataire fournit son propre mécanisme de signature (HMAC, certificat, jeton partagé) qu’il faut valider avant tout appel à payment_complete().

Tester avant la mise en production

Il est indispensable de couvrir les scénarios d’échec autant que le scénario nominal : paiement refusé, webhook reçu en double, commande déjà payée qui reçoit une seconde notification. La méthode $order->has_status() permet d’éviter de traiter deux fois la même confirmation :

  • Toujours vérifier $order->has_status( 'processing' ) avant d’appeler payment_complete() une seconde fois ;
  • Journaliser chaque appel de webhook via wc_get_logger() pour pouvoir diagnostiquer un litige de paiement plusieurs semaines après ;
  • Prévoir un mode bac à sable clairement signalé dans l’interface d’administration, jamais activé par défaut en production.

Une passerelle de paiement mal testée coûte toujours plus cher après la mise en ligne qu’avant : un webhook manqué se traduit directement par une commande payée mais jamais préparée.

En résumé

Écrire une passerelle de paiement WooCommerce sur mesure n’exige pas d’expertise cryptographique poussée pour la majorité des cas, mais demande de la rigueur sur trois points : des statuts de commande fidèles à la réalité du paiement, une confirmation asynchrone sécurisée par une vérification de signature, et des tests couvrant les cas d’échec autant que le chemin nominal. C’est un investissement qui se rentabilise vite dès qu’un prestataire de paiement sort des sentiers battus des extensions toutes faites.

Partager :

À propos de l'auteur

Clément Hadrot

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi