Personnalisation du checkout Magento 2 : Guide pas à pas (2026)
Le checkout de Magento 2 est construit sur une application monopage Knockout.js — puissante mais notoirement complexe à personnaliser. Ce guide couvre toutes les approches principales : surcharges de layout XML, extensions de composants Knockout, ajout/suppression de champs, étapes personnalisées, modifications de l’expédition et du paiement, et bonnes pratiques pour rester compatible avec les mises à jour. Vous pouvez aussi consulter mon service de développement Magento 2 si vous avez besoin d’une implémentation complète du checkout.
En résumé : Le checkout Magento 2 est composé de composants UI (Knockout.js), de handles de layout (XML) et de fournisseurs PHP (sources de données). Vous pouvez le personnaliser via
layout/checkout_index_index.xml, l’extend/overridedes composants Knockout, et les plugins sur les classes PHP.
Table des matières
- Comprendre l’architecture du checkout
- Outils : Layout XML, Knockout et fournisseurs PHP
- Ajouter un champ personnalisé à l’adresse de livraison
- Supprimer un champ du checkout
- Surcharger un composant Knockout.js
- Ajouter une étape de checkout personnalisée
- Personnaliser les méthodes d’expédition
- Personnaliser les méthodes de paiement
- Ajouter des règles de validation
- Modifier le récapitulatif de commande (barre latérale)
- Compatibilité avec les extensions tierces
- Bonnes pratiques et sécurité de mise à jour
- FAQ
Comprendre l’architecture du checkout
Le checkout de Magento 2 est une application Knockout.js monopage avec ces étapes principales :
| Étape | Composant | Objectif |
|---|---|---|
| Expédition | Magento_Checkout/js/view/shipping | Formulaire d’adresse de livraison + sélection du mode d’expédition |
| Facturation | Magento_Checkout/js/view/billing | Formulaire d’adresse de facturation |
| Paiement | Magento_Checkout/js/view/payment | Liste des méthodes de paiement |
| Récapitulatif | Magento_Checkout/js/view/summary | Barre latérale de révision de la commande |
Chaque étape est un composant UI composé d’un template .html, d’un view-model .js et d’une classe PHP provider qui fournit les données backend. Si vous débutez dans la construction de modules Magento 2
, commencez par là — la personnalisation du checkout s’appuie sur la même structure de module.
Outils : Layout XML, Knockout et fournisseurs PHP
Layout XML
Le fichier checkout_index_index.xml contrôle quels composants sont rendus :
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceBlock name="checkout.root">
<arguments>
<argument name="jsLayout" xsi:type="array">
<!-- components go here -->
</argument>
</arguments>
</referenceBlock>
</body>
</page>
Extension de composant Knockout
Utilisez extend pour ajouter à un composant existant :
define(['Magento_Checkout/js/view/shipping'], function (Component) {
'use strict';
return Component.extend({
// your custom logic
});
});
Fournisseurs PHP
La logique backend vit dans Magento\Checkout\Block\Checkout\LayoutProcessor ou des Processors personnalisés qui implémentent LayoutProcessorInterface.
Ajouter un champ personnalisé à l’adresse de livraison
Étape 1 — Créer le layout XML
<!-- Vendor/Module/view/frontend/layout/checkout_index_index.xml -->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceBlock name="checkout.root">
<arguments>
<argument name="jsLayout" xsi:type="array">
<item name="components" xsi:type="array">
<item name="checkout" xsi:type="array">
<item name="children" xsi:type="array">
<item name="steps" xsi:type="array">
<item name="children" xsi:type="array">
<item name="shipping-step" xsi:type="array">
<item name="children" xsi:type="array">
<item name="shippingAddress" xsi:type="array">
<item name="children" xsi:type="array">
<item name="shipping-address-fieldset" xsi:type="array">
<item name="children" xsi:type="array">
<item name="custom_field" xsi:type="array">
<item name="config" xsi:type="array">
<item name="component" xsi:type="string">uiComponent</item>
<item name="template" xsi:type="string">ui/form/field</item>
<item name="elementTmpl" xsi:type="string">ui/form/elements/input</item>
<item name="label" xsi:type="string">Custom Field</item>
<item name="dataScope" xsi:type="string">custom_field</item>
<item name="provider" xsi:type="string">checkoutProvider</item>
<item name="sortOrder" xsi:type="string">150</item>
<item name="validation" xsi:type="array">
<item name="required-entry" xsi:type="boolean">true</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</argument>
</arguments>
</referenceBlock>
</body>
</page>
Étape 2 — Sauvegarder le champ via LayoutProcessor
namespace Vendor\Module\Block\Checkout;
use Magento\Checkout\Block\Checkout\LayoutProcessorInterface;
class CustomFieldProcessor implements LayoutProcessorInterface
{
public function process($jsLayout)
{
// Field was already added via XML; persist it to the quote
return $jsLayout;
}
}
Étape 3 — Plugin sur ShippingInformationManagement
namespace Vendor\Module\Plugin;
use Magento\Checkout\Model\ShippingInformationManagement;
use Magento\Checkout\Model\Session;
use Magento\Quote\Api\Data\AddressExtensionFactory;
class SaveCustomField
{
private $checkoutSession;
private $addressExtensionFactory;
public function __construct(
Session $checkoutSession,
AddressExtensionFactory $addressExtensionFactory
) {
$this->checkoutSession = $checkoutSession;
$this->addressExtensionFactory = $addressExtensionFactory;
}
public function beforeSaveAddressInformation(
ShippingInformationManagement $subject,
$cartId,
\Magento\Checkout\Api\Data\ShippingInformationInterface $shippingInfo
) {
$extAttributes = $shippingInfo->getShippingAddress()->getExtensionAttributes();
if ($extAttributes === null) {
$extAttributes = $this->addressExtensionFactory->create();
}
$customField = $shippingInfo->getShippingAddress()->getCustomAttribute('custom_field');
$extAttributes->setCustomField($customField ? $customField->getValue() : '');
return [$cartId, $shippingInfo];
}
}
Supprimer un champ du checkout
Utilisez LayoutProcessor pour retirer des champs :
namespace Vendor\Module\Block\Checkout;
use Magento\Checkout\Block\Checkout\LayoutProcessorInterface;
class RemoveFieldProcessor implements LayoutProcessorInterface
{
public function process($jsLayout)
{
$fieldset = &$jsLayout['components']['checkout']['children']['steps']
['children']['shipping-step']['children']['shippingAddress']
['children']['shipping-address-fieldset']['children'];
unset($fieldset['company']); // remove company field
unset($fieldset['telephone']); // remove telephone field
return $jsLayout;
}
}
Surcharger un composant Knockout.js
Pour remplacer le composant d’expédition par le vôtre :
// Vendor/Module/view/frontend/web/js/view/custom-shipping.js
define([
'Magento_Checkout/js/view/shipping',
'Magento_Checkout/js/model/quote',
'Magento_Customer/js/model/customer'
], function (Component, quote, customer) {
'use strict';
return Component.extend({
defaults: {
template: 'Vendor_Module/custom-shipping'
},
// Add a custom observable
initialize: function () {
this._super();
this.customMessage = ko.observable('');
return this;
},
// Override the shipping method selection
setShippingInformation: function () {
// custom logic before calling parent
return this._super();
}
});
});
Enregistrez-le dans checkout_index_index.xml :
<item name="shipping" xsi:type="array">
<item name="config" xsi:type="array">
<item name="component" xsi:type="string">Vendor_Module/js/view/custom-shipping</item>
</item>
</item>
Ajouter une étape de checkout personnalisée
Étape 1 — Créer le composant d’étape
// Vendor/Module/view/frontend/web/js/view/custom-step.js
define([
'uiComponent',
'Magento_Checkout/js/model/step-navigator',
'jquery',
'ko'
], function (Component, stepNavigator, $, ko) {
'use strict';
var uniqueId = 'custom-step';
return Component.extend({
defaults: {
template: 'Vendor_Module/custom-step'
},
isVisible: ko.observable(false),
stepCode: uniqueId,
stepTitle: 'Custom Step',
initialize: function () {
this._super();
stepNavigator.registerStep(
this.stepCode,
null,
this.stepTitle,
this.isVisible,
_.bind(this.navigate, this),
25 // sort order
);
return this;
},
navigate: function () {
this.isVisible(true);
},
navigateToNextStep: function () {
this.isVisible(false);
stepNavigator.next();
}
});
});
Étape 2 — Enregistrer dans le layout XML
<item name="custom-step" xsi:type="array">
<item name="config" xsi:type="array">
<item name="component" xsi:type="string">Vendor_Module/js/view/custom-step</item>
</item>
</item>
Personnaliser les méthodes d’expédition
Masquer une méthode d’expédition
namespace Vendor\Module\Plugin;
use Magento\Quote\Api\Data\ShippingMethodInterface;
use Magento\Quote\Model\Cart\ShippingMethodConverter;
class HideShippingMethod
{
public function afterModelToDataObject(
ShippingMethodConverter $subject,
ShippingMethodInterface $result
) {
$code = $result->getCarrierCode() . '_' . $result->getMethodCode();
if (in_array($code, ['flatrate_flatrate'])) {
return null;
}
return $result;
}
}
Ajouter une méthode d’expédition personnalisée
Créez une classe Carrier étendant \Magento\Shipping\Model\Carrier\AbstractCarrier et implémentez collectRates(), puis enregistrez-la via config.xml.
Personnaliser les méthodes de paiement
Ajouter une méthode de paiement personnalisée
- Créez un Model implémentant
Magento\Payment\Model\MethodInterface - Définissez
config.xmlavec la configuration de la méthode - Créez des templates frontend pour le formulaire de checkout
- Enregistrez un composant Knockout pour le rendu du paiement
Besoin d’une intégration de passerelle personnalisée ? Consultez mon service de modules personnalisés pour les processeurs de paiement locaux (Konnect, Flouci, Paymee) et les flux de checkout complets.
<!-- config.xml -->
<default>
<payment>
<custom_payment>
<model>Vendor\Module\Model\Payment\CustomPayment</model>
<title>Custom Payment</title>
<active>1</active>
<sort_order>10</sort_order>
<order_status>pending</order_status>
<allowspecific>0</allowspecific>
</custom_payment>
</payment>
</default>
Ajouter des règles de validation
Ajoutez des règles de validation Knockout personnalisées :
define(['jquery', 'jquery/validate'], function ($) {
'use strict';
$.validator.addMethod('custom-rule', function (value) {
return value && value.length >= 3;
}, $.mage.__('Value must be at least 3 characters'));
});
Puis référencez dans votre layout XML :
<item name="validation" xsi:type="array">
<item name="custom-rule" xsi:type="boolean">true</item>
</item>
Modifier le récapitulatif de commande (barre latérale)
Surchargez le composant Knockout summary :
define([
'Magento_Checkout/js/view/summary/abstract-total',
'Magento_Checkout/js/model/quote'
], function (Component, quote) {
'use strict';
return Component.extend({
getCustomBlockHtml: function () {
return '<p class="custom-note">' +
$t('Your custom message here') + '</p>';
}
});
});
Compatibilité avec les extensions tierces
| Problème | Solution |
|---|---|
| Conflits de champs | Utilisez sortOrder pour contrôler la position des champs |
| Ordre des étapes perturbé | Enregistrez l’étape avec le bon poids de tri |
| Erreurs JS dues aux surcharges | Utilisez extend plutôt que replace quand c’est possible |
| Données fournisseur non persistantes | Créez un plugin sur ShippingInformationManagement::saveAddressInformation |
| Collisions CSS | Limitez les styles avec des sélecteurs de classe spécifiques au checkout |
Bonnes pratiques et sécurité de mise à jour
- Préférez
extendau remplacement complet du composant — votre code reste fonctionnel après les mises à jour de version. - Utilisez
LayoutProcessorInterfacepour les modifications de champs plutôt que de surcharger les templates. - Stockez les données personnalisées dans les tables
quote_extensionvia les attributs d’extension — évite les modifications des tables principales. - Testez sur plusieurs navigateurs et appareils — le JS du checkout varie en comportement.
- Évitez de modifier directement les fichiers
Magento_Checkout/js/model/**— étendez-les. - Videz toujours le contenu statique après des modifications JS :
php bin/magento setup:static-content:deploy -f. - Exécutez une compilation complète (
php bin/magento setup:upgrade && php bin/magento setup:di:compile) après avoir ajouté de nouvelles classes PHP — consultez le guide sur setup:upgrade vs di:compile pour les détails. - Pour un réglage plus approfondi des performances, consultez mon service d’optimisation des performances couvrant l’audit FPC, Varnish et les Core Web Vitals.
FAQ
Pourquoi utiliser LayoutProcessor plutôt que XML pour les modifications de champs ?
LayoutProcessor est plus flexible pour la logique conditionnelle (par exemple, afficher un champ uniquement pour certaines méthodes d’expédition) et évite le XML profondément imbriqué pour les modifications dynamiques.
Comment tester mes modifications du checkout en mode développeur ?
php bin/magento deploy:mode:set developer
php bin/magento cache:flush
npm run watch # if theme uses Grunt
Mon champ personnalisé ne se sauvegarde pas. Que dois-je vérifier ?
- Vérifiez que
dataScopecorrespond au code d’attribut - Le plugin sur
ShippingInformationManagement::saveAddressInformationest enregistré - Les attributs d’extension sont correctement déclarés dans
extension_attributes.xml - Vérifiez la console du navigateur pour les erreurs JS
Puis-je ajouter une étape après le paiement ?
Oui — enregistrez votre étape avec un ordre de tri supérieur à celui de l’étape de paiement (valeur par défaut : 30) et implémentez la logique de navigation en conséquence.
Conclusion
La personnalisation du checkout Magento 2 nécessite une bonne compréhension de son architecture de composants Knockout.js, de son système de layout XML et de ses fournisseurs PHP. En utilisant extend plutôt que le remplacement, LayoutProcessor pour les modifications de champs et des plugins pour la persistence des données, vous pouvez construire des personnalisations de checkout robustes et compatibles avec les mises à jour.
Prochaines étapes :
- Construire une méthode d’expédition personnalisée avec des tarifs dynamiques
- Implémenter un checkout en une étape avec des modules tiers
- Créer une étape de message cadeau ou de commentaire de commande
- Ajouter une validation d’adresse via l’API Google Maps