# Étendre le bloc Paiement WooCommerce avec un slot et l’Interactivity API

> Tutoriel pas à pas pour ajouter un emplacement personnalisé au bloc Paiement stable de WooCommerce en s'appuyant sur l'Interactivity API de WordPress 6.5.

- Auteur : WordPress Développement
- Publié le : 2024-01-16
- Mis à jour le : 2026-09-30
- Catégorie : E-commerce
- URL : https://www.wpmoderne.fr/ecommerce/etendre-bloc-paiement-woocommerce-slot-interactivity-api/

## L’essentiel

- Un slot enregistré côté serveur et rempli côté client
- Un store d'interactivité isolé du reste du thème
- Zéro jQuery dans toute la personnalisation

Depuis que le bloc Paiement de WooCommerce est passé en stable, personnaliser le tunnel de commande ne se fait plus en surchargeant un template PHP mais en peuplant des emplacements dédiés, les *slots*, exposés par le bloc lui-même. Ce tutoriel construit un cas concret : une case à cocher facultative « Ajouter un emballage cadeau », affichée juste avant le récapitulatif de commande, dont l'état conditionne l'affichage d'un champ de message.

L'Interactivity API, disponible via le plugin Gutenberg en attendant son intégration prévue à WordPress 6.5, est le complément naturel de cette architecture par blocs : elle permet de gérer l'état d'une interface directement en HTML annoté par des directives, sans écrire de composant React à la main ni charger de bibliothèque supplémentaire. C'est cette approche que nous allons suivre plutôt qu'un enregistrement classique via `@wordpress/element`.

## Étape 1 : déclarer le bloc et son point de montage

La personnalisation prend la forme d'un petit plugin dédié, indépendant du thème, ce qui garantit qu'elle survivra à un futur changement d'habillage graphique. On commence par enregistrer un bloc simple destiné à occuper le slot `woocommerce/checkout-additional-information-block`, l'un des emplacements exposés par défaut dans le flux du paiement :

> L'essentiel à retenir : Un slot enregistré côté serveur et rempli côté client ; Un store d'interactivité isolé du reste du thème ; Zéro jQuery dans toute la personnalisation

```
{
    "apiVersion": 2,
    "name": "boutique/emballage-cadeau",
    "title": "Emballage cadeau",
    "category": "woocommerce",
    "parent": [ "woocommerce/checkout-additional-information-block" ],
    "attributes": {
        "lock": {
            "type": "object",
            "default": { "remove": true, "move": true }
        }
    },
    "supports": { "multiple": false },
    "render": "file:./render.php",
    "viewModule": "file:./view.js"
}
```

La clé `parent` est ce qui rattache le bloc au point de montage : il n'apparaît dans l'éditeur que dans cet emplacement du bloc Paiement. Les attributs `lock` empêchent le marchand de le déplacer ou de le supprimer par mégarde. Attention à la clé qui charge le script de la vue : à la date de ce tutoriel, avec le plugin Gutenberg, elle s'appelle `viewModule` ; elle devrait changer de nom avec l'intégration de l'API dans WordPress 6.5. Vérifiez le nom attendu par la version que vous installez.

## Étape 2 : le balisage annoté par des directives

Le fichier `render.php` produit le HTML du bloc. Les directives de l'Interactivity API sont de simples attributs : `data-wp-interactive` désigne l'espace de noms du store, `data-wp-context` porte l'état local sous forme de JSON, `data-wp-on--change` relie un événement à une action, et `data-wp-bind--hidden` lie un attribut à une valeur calculée :

```
<?php
// render.php
?>
<div
    data-wp-interactive="emballage-cadeau"
    data-wp-context="<?php echo esc_attr( wp_json_encode( array( 'actif' => false, 'message' => '' ) ) ); ?>"
>
    <label>
        <input type="checkbox" data-wp-on--change="actions.basculer">
        Ajouter un emballage cadeau
    </label>
    <p data-wp-bind--hidden="!context.actif">
        <label>
            Message pour la carte (200 caractères au maximum)
            <textarea maxlength="200" data-wp-on--input="actions.saisir"></textarea>
        </label>
    </p>
</div>
```

Le champ de message est masqué tant que la case n'est pas cochée ; aucune ligne de jQuery ni de composant React n'est nécessaire pour cela. Le contexte JSON est échappé avec `esc_attr()` pour ne pas casser l'attribut HTML.

## Étape 3 : le store côté navigateur

Le fichier `view.js` déclare le store. Les actions lisent et modifient le contexte du bloc grâce à `getContext()`, puis transmettent le choix à WooCommerce. Pour cela, le script passe par la fonction `extensionCartUpdate` du paquet `@woocommerce/blocks-checkout`, exposée dans la page par l'objet global `wc.blocksCheckout` :

```
import { store, getContext } from '@wordpress/interactivity';

function transmettre( contexte ) {
    const miseAJour = window.wc?.blocksCheckout?.extensionCartUpdate;
    if ( ! miseAJour ) {
        return;
    }
    miseAJour( {
        namespace: 'emballage-cadeau',
        data: { actif: contexte.actif, message: contexte.message },
    } );
}

store( 'emballage-cadeau', {
    actions: {
        basculer() {
            const contexte = getContext();
            contexte.actif = ! contexte.actif;
            transmettre( contexte );
        },
        saisir( evenement ) {
            const contexte = getContext();
            contexte.message = evenement.target.value.slice( 0, 200 );
            transmettre( contexte );
        },
    },
} );
```

La garde `window.wc?.blocksCheckout?.extensionCartUpdate` évite une erreur si le paquet n'est pas encore chargé. En production, on ajouterait une temporisation pour ne pas envoyer une requête à chaque caractère tapé.

## Étape 4 : enregistrer le choix côté serveur

La Store API de WooCommerce reçoit l'appel et le confie à une fonction de rappel enregistrée par l'extension. Le choix est placé en session, puis copié sur la commande au moment de sa création :

```
add_action( 'woocommerce_blocks_loaded', 'boutique_enregistrer_emballage' );

function boutique_enregistrer_emballage() {
    woocommerce_store_api_register_update_callback( array(
        'namespace' => 'emballage-cadeau',
        'callback'  => function ( $donnees ) {
            $message = isset( $donnees['message'] )
                ? mb_substr( sanitize_textarea_field( wp_unslash( $donnees['message'] ) ), 0, 200 )
                : '';
            WC()->session->set( 'emballage_cadeau', array(
                'actif'   => ! empty( $donnees['actif'] ),
                'message' => $message,
            ) );
        },
    ) );
}

add_action( 'woocommerce_store_api_checkout_update_order_from_request', 'boutique_copier_emballage', 10, 2 );

function boutique_copier_emballage( $commande, $requete ) {
    $cadeau = WC()->session ? WC()->session->get( 'emballage_cadeau' ) : null;

    if ( ! empty( $cadeau['actif'] ) ) {
        $commande->update_meta_data( '_emballage_cadeau', '1' );
        $commande->update_meta_data( '_message_cadeau', $cadeau['message'] );
    }
}
```

La saisie est assainie et bornée côté serveur : le plafond de 200 caractères du champ HTML ne protège de rien, puisqu'une requête peut être forgée. L'enregistrement par `update_meta_data()` fonctionne que la boutique utilise le stockage haute performance des commandes ou non.

> Un emplacement bien choisi vaut mieux qu'un gabarit surchargé : la personnalisation survit aux mises à jour parce qu'elle ne touche à rien qu'elle ne possède pas.

## Ce qu'il faut vérifier avant de livrer

- **L'hydratation dans le bloc Paiement.** Le bloc Paiement est dessiné par React dans le navigateur, alors que l'Interactivity API active les directives sur du HTML déjà présent dans la page. Testez sur votre version : si les directives restent inertes, la voie documentée par WooCommerce est d'enregistrer le bloc avec `registerCheckoutBlock()` et un composant écrit avec `@wordpress/element`, en conservant telle quelle la partie serveur de l'étape 4.
- **La stabilité de l'API.** L'Interactivity API n'est pas encore intégrée à WordPress ; les noms de clés et de directives peuvent évoluer. Fixez la version du plugin Gutenberg en recette.
- **Les extensions de paiement tierces.** Testez avec chaque passerelle active : certaines modifient la validation côté client.
- **Le cas du panier vide ou de la session expirée.** La fonction de rappel doit tolérer l'absence de session sans provoquer d'erreur fatale.

## Conclusion

Étendre le bloc Paiement consiste à déclarer un bloc rattaché à un emplacement, à lui donner un état léger avec des directives et un store isolé, puis à confier la persistance à la Store API de WooCommerce. La personnalisation reste dans un plugin indépendant du thème, sans jQuery. Le point à surveiller est la jeunesse de l'Interactivity API : en attendant sa stabilisation, une recette rigoureuse et une solution de repli documentée valent mieux qu'un pari.
