Je dois ajouter deux champs personnalisés à chaque étape d'expédition et de paiement de la page de paiement dans Magento 2 et les données doivent également être enregistrées dans les tableaux nécessaires
comment le faire dans Magento 2
Je dois ajouter deux champs personnalisés à chaque étape d'expédition et de paiement de la page de paiement dans Magento 2 et les données doivent également être enregistrées dans les tableaux nécessaires
comment le faire dans Magento 2
Réponses:
Aujourd'hui, je vais vous expliquer comment ajouter des champs personnalisés à toutes les étapes de la page de paiement et l'enregistrer après la commande et comment utiliser les données publiées après avoir passé la commande
1er champs delivery_date
: - où le client mentionnera à la date de livraison dans l'étape d'expédition
Ordre des 2e champs Commentaires: - sera dans l'étape de paiement et après avoir passé la commande, ces commentaires seront ajoutés à l'historique des commentaires de la commande
Étape 1 : - assurez-vous que la date de livraison est ajoutée dans tous les tableaux de besoins comme le devis sales_order
et sales_order_grid
via le script d'installation ou de mise à niveau
<?php
namespace Sugarcode\Deliverydate\Setup;
use Magento\Framework\Setup\InstallSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
/**
* @codeCoverageIgnore
*/
class InstallSchema implements InstallSchemaInterface
{
/**
* {@inheritdoc}
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function install(SchemaSetupInterface $setup, ModuleContextInterface $context)
{
$installer = $setup;
$installer->startSetup();
$installer->getConnection()->addColumn(
$installer->getTable('quote'),
'delivery_date',
[
'type' => 'datetime',
'nullable' => false,
'comment' => 'Delivery Date',
]
);
$installer->getConnection()->addColumn(
$installer->getTable('sales_order'),
'delivery_date',
[
'type' => 'datetime',
'nullable' => false,
'comment' => 'Delivery Date',
]
);
$installer->getConnection()->addColumn(
$installer->getTable('sales_order_grid'),
'delivery_date',
[
'type' => 'datetime',
'nullable' => false,
'comment' => 'Delivery Date',
]
);
$setup->endSetup();
}
}
Étape 2 : - Ajout de champs personnalisés dans les étapes d'expédition et de paiement, nous pouvons réaliser de deux manières l'une à partir de layout xml
et l'autre est le plugin ci-dessous est la façon d'ajouter les champs via le plugin
Nous créons un di.xml
fichier dans notre module -Sugarcode/Deliverydate/etc/frontend/di.xml
Nous utilisons la zone frontend pour la garder propre, notre plugin ne devrait fonctionner que sur le frontend.
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Checkout\Block\Checkout\LayoutProcessor">
<plugin name="add-delivery-date-field"
type="Sugarcode\Deliverydate\Model\Checkout\LayoutProcessorPlugin" sortOrder="10"/>
</type>
</config>
Sugarcode \ Plugin \ Checkout \ LayoutProcessor.php
<?php
namespace Sugarcode\Plugin\Checkout;
class LayoutProcessor
{
/**
* @var \Magento\Framework\App\Config\ScopeConfigInterface
*/
protected $scopeConfig;
/**
* @var \Magento\Checkout\Model\Session
*/
protected $checkoutSession;
/**
* @var \Magento\Customer\Model\AddressFactory
*/
protected $customerAddressFactory;
/**
* @var \Magento\Framework\Data\Form\FormKey
*/
protected $formKey;
public function __construct(
\Magento\Framework\View\Element\Template\Context $context,
\Magento\CheckoutAgreements\Model\ResourceModel\Agreement\CollectionFactory $agreementCollectionFactory,
\Magento\Checkout\Model\Session $checkoutSession,
\Magento\Customer\Model\AddressFactory $customerAddressFactory
) {
$this->scopeConfig = $context->getScopeConfig();
$this->checkoutSession = $checkoutSession;
$this->customerAddressFactory = $customerAddressFactory;
}
/**
* @param \Magento\Checkout\Block\Checkout\LayoutProcessor $subject
* @param array $jsLayout
* @return array
*/
public function afterProcess(
\Magento\Checkout\Block\Checkout\LayoutProcessor $subject,
array $jsLayout
) {
$jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children']
['shippingAddress']['children']['before-form']['children']['delivery_date'] = [
'component' => 'Magento_Ui/js/form/element/abstract',
'config' => [
'customScope' => 'shippingAddress',
'template' => 'ui/form/field',
'elementTmpl' => 'ui/form/element/date',
'options' => [],
'id' => 'delivery-date'
],
'dataScope' => 'shippingAddress.delivery_date',
'label' => 'Delivery Date',
'provider' => 'checkoutProvider',
'visible' => true,
'validation' => [],
'sortOrder' => 200,
'id' => 'delivery-date'
];
$jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']
['payment']['children']['payments-list']['children']['before-place-order']['children']['comment'] = [
'component' => 'Magento_Ui/js/form/element/textarea',
'config' => [
'customScope' => 'shippingAddress',
'template' => 'ui/form/field',
'options' => [],
'id' => 'comment'
],
'dataScope' => 'ordercomment.comment',
'label' => 'Order Comment',
'notice' => __('Comments'),
'provider' => 'checkoutProvider',
'visible' => true,
'sortOrder' => 250,
'id' => 'comment'
];
return $jsLayout;
}
}
Maintenant, tous les champs sont dans la page de paiement, maintenant comment enregistrer les données
contrairement à M1 dans M2, toutes les pages de paiement sont complètement désactivées JS et API
Nous avons deux étapes: la première est l'expédition et la deuxième étape est le paiement où nous devons enregistrer les deux champs
Vous trouverez ci-dessous comment enregistrer les données après l'enregistrement des adresses de livraison
Étape d'expédition
Pour enregistrer les informations d'expédition dans les utilisations M2
app/code/Magento/Checkout/view/frontend/web/js/model/shipping-save-processor/default.js
pour préparer json
et l'appel api
nous avons donc besoin de remplacer ce js et dans le php
côté sauver se produira
\ Magento \ Checkout \ Model \ ShippingInformationManagement :: SaveAddressInformation () et ShippingInformationManagement implémentés par Magento \ Checkout \ Api \ Data \ ShippingInformationInterface
M2 a un puissant concept appelé extension_attributes
qui est utilisé pour les données dynamiques vers les tables de base permet de l'utiliser
étape 3 : - créer un fichierDeliverydate/etc/extension_attributes.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
<extension_attributes for="Magento\Quote\Api\Data\AddressInterface">
<attribute code="delivery_date" type="string"/>
</extension_attributes>
<extension_attributes for="Magento\Quote\Api\Data\PaymentInterface">
<attribute code="comment" type="string"/>
</extension_attributes>
</config>
pour remplacer js créer un fichier js, Deliverydate/view/frontend/requirejs-config.js
nous devons utiliser des mixns
var config = {
config: {
mixins: {
'Magento_Checkout/js/action/place-order': {
'Sugarcode_Deliverydate/js/order/place-order-mixin': true
},
'Magento_Checkout/js/action/set-payment-information': {
'Sugarcode_Deliverydate/js/order/set-payment-information-mixin': true
},
'Magento_Checkout/js/action/set-shipping-information': {
'Sugarcode_Deliverydate/js/order/set-shipping-information-mixin': true
}
}
};
js / order / set-shipping-information-mixin.js delivery_date
/**
* @author aakimov
*/
/*jshint browser:true jquery:true*/
/*global alert*/
define([
'jquery',
'mage/utils/wrapper',
'Magento_Checkout/js/model/quote'
], function ($, wrapper, quote) {
'use strict';
return function (setShippingInformationAction) {
return wrapper.wrap(setShippingInformationAction, function (originalAction) {
var shippingAddress = quote.shippingAddress();
if (shippingAddress['extension_attributes'] === undefined) {
shippingAddress['extension_attributes'] = {};
}
// you can extract value of extension attribute from any place (in this example I use customAttributes approach)
shippingAddress['extension_attributes']['delivery_date'] = jQuery('[name="delivery_date"]').val();
// pass execution to original action ('Magento_Checkout/js/action/set-shipping-information')
return originalAction();
});
};
});
L'étape suivante consiste à enregistrer ces données de publication de champ personnalisé dans le devis. Faisons un autre plugin en ajoutant un nœud xml dans notreetc/di.xml
<type name="Magento\Checkout\Model\ShippingInformationManagement">
<plugin name="save-in-quote" type="Sugarcode\Deliverydate\Plugin\Checkout\ShippingInformationManagementPlugin" sortOrder="10"/>
</type>
Créez un fichier Sugarcode \ Deliverydate \ Plugin \ Checkout \ ShippingInformationManagementPlugin.php
<?php
namespace Sugarcode\Deliverydate\Plugin\Checkout;
class ShippingInformationManagementPlugin
{
protected $quoteRepository;
public function __construct(
\Magento\Quote\Model\QuoteRepository $quoteRepository
) {
$this->quoteRepository = $quoteRepository;
}
/**
* @param \Magento\Checkout\Model\ShippingInformationManagement $subject
* @param $cartId
* @param \Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation
*/
public function beforeSaveAddressInformation(
\Magento\Checkout\Model\ShippingInformationManagement $subject,
$cartId,
\Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation
) {
$extAttributes = $addressInformation->getShippingAddress()->getExtensionAttributes();
$deliveryDate = $extAttributes->getDeliveryDate();
$quote = $this->quoteRepository->getActive($cartId);
$quote->setDeliveryDate($deliveryDate);
}
}
peu de temps après votre passage aux étapes de paiement, les données seront enregistrées dans le tableau des devis
pour enregistrer les mêmes données après avoir passé la commande, nous devons utiliser fieldset
etc / fieldset.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Object/etc/fieldset.xsd">
<scope id="global">
<fieldset id="sales_convert_quote">
<field name="delivery_date">
<aspect name="to_order"/>
</field>
</fieldset>
</scope>
</config>
Permet maintenant d'enregistrer le champ des étapes de paiement
si nous avons des champs supplémentaires dans l'étape de paiement et que nous devons publier ces données, nous devons remplacer les autres js comme nous l'avons fait pour l'étape d'expédition
comme les informations d'expédition, nous avons des informations de paiement
ww peut atteindre par dérogation est Magento_Checkout/js/action/place-order.js
(mais il aura un problème lorsque l'accord est activé, nous devons donc utiliser les mixins comme mentionné dans re)
Sugarcode_Deliverydate/js/order/place-order-mixin.js
/**
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
define([
'jquery',
'mage/utils/wrapper',
'Sugarcode_Deliverydate/js/order/ordercomment-assigner'
], function ($, wrapper, ordercommentAssigner) {
'use strict';
return function (placeOrderAction) {
/** Override default place order action and add comments to request */
return wrapper.wrap(placeOrderAction, function (originalAction, paymentData, messageContainer) {
ordercommentAssigner(paymentData);
return originalAction(paymentData, messageContainer);
});
};
});
Sugarcode_Deliverydate / js / order / ordercomment-assigner.js
/*jshint browser:true jquery:true*/
/*global alert*/
define([
'jquery'
], function ($) {
'use strict';
/** Override default place order action and add comment to request */
return function (paymentData) {
if (paymentData['extension_attributes'] === undefined) {
paymentData['extension_attributes'] = {};
}
paymentData['extension_attributes']['comment'] = jQuery('[name="ordercomment[comment]"]').val();
};
});
Sugarcode_Deliverydate / js / order / set-payment-information-mixin.js
/*jshint browser:true jquery:true*/
/*global alert*/
define([
'jquery',
'mage/utils/wrapper',
'Sugarcode_Deliverydate/js/order/ordercomment-assigner'
], function ($, wrapper, ordercommentAssigner) {
'use strict';
return function (placeOrderAction) {
/** Override place-order-mixin for set-payment-information action as they differs only by method signature */
return wrapper.wrap(placeOrderAction, function (originalAction, messageContainer, paymentData) {
ordercommentAssigner(paymentData);
return originalAction(messageContainer, paymentData);
});
};
});
et besoin de créer un plugin pour Magento\Checkout\Model\PaymentInformationManagement
donc en etc/di
ajouter ci-dessous le code
<type name="Magento\Checkout\Model\PaymentInformationManagement">
<plugin name="order_comments_save-in-order" type="Sugarcode\Deliverydate\Plugin\Checkout\PaymentInformationManagementPlugin" sortOrder="10"/>
</type>
puis créer un fichier Sugarcode\Deliverydate\Plugin\Checkout\PaymentInformationManagementPlugin.php
/**
* One page checkout processing model
*/
class PaymentInformationManagementPlugin
{
protected $orderRepository;
public function __construct(
\Magento\Sales\Api\OrderRepositoryInterface $orderRepository
) {
$this->orderRepository = $orderRepository;
}
public function aroundSavePaymentInformationAndPlaceOrder(
\Magento\Checkout\Model\PaymentInformationManagement $subject,
\Closure $proceed,
$cartId,
\Magento\Quote\Api\Data\PaymentInterface $paymentMethod,
\Magento\Quote\Api\Data\AddressInterface $billingAddress = null
) {
$result = $proceed($cartId, $paymentMethod, $billingAddress);
if($result){
$orderComment =$paymentMethod->getExtensionAttributes();
if ($orderComment->getComment())
$comment = trim($orderComment->getComment());
else
$comment = '';
$history = $order->addStatusHistoryComment($comment);
$history->save();
$order->setCustomerNote($comment);
}
return $result;
}
}
Remarque: - si le champ de l'étape de paiement doit être enregistré dans le tableau des devis, utilisez le plug-in beofore pour la même fonction et suivez-le comme dans ShippingInformationManagementPlugin
Avant d'effectuer des personnalisations, procédez comme suit.
Étape 1: créer l'implémentation JS du composant d'interface utilisateur de formulaire
Dans votre <your_module_dir>/view/frontend/web/js/view/
répertoire, créez un fichier .js implémentant le formulaire.
/*global define*/
define([
'Magento_Ui/js/form/form'
], function(Component) {
'use strict';
return Component.extend({
initialize: function () {
this._super();
// component initialization logic
return this;
},
/**
* Form submit handler
*
* This method can have any name.
*/
onSubmit: function() {
// trigger form validation
this.source.set('params.invalid', false);
this.source.trigger('customCheckoutForm.data.validate');
// verify that form data is valid
if (!this.source.get('params.invalid')) {
// data is retrieved from data provider by value of the customScope property
var formData = this.source.get('customCheckoutForm');
// do something with form data
console.dir(formData);
}
}
});
});
Étape 2: créer le modèle HTML
Ajoutez le knockout.js
modèle HTML pour le composant de formulaire sous le <your_module_dir>/view/frontend/web/
répertoire du modèle.
Exemple:
<div>
<form id="custom-checkout-form" class="form" data-bind="attr: {'data-hasrequired': $t('* Required Fields')}">
<fieldset class="fieldset">
<legend data-bind="i18n: 'Custom Checkout Form'"></legend>
<!-- ko foreach: getRegion('custom-checkout-form-fields') -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->
</fieldset>
<button type="reset">
<span data-bind="i18n: 'Reset'"></span>
</button>
<button type="button" data-bind="click: onSubmit" class="action">
<span data-bind="i18n: 'Submit'"></span>
</button>
</form>
</div>
Effacer les fichiers après modification
Si vous modifiez votre modèle .html personnalisé après son application sur les pages du magasin, les modifications ne s'appliqueront pas tant que vous n'aurez pas effectué les opérations suivantes:
Supprimez tous les fichiers des répertoires pub/static/frontend
et var/view_preprocessed
. Rechargez les pages.
Étape 3: Déclarez le formulaire dans la mise en page de la page de paiement
Pour ajouter du contenu à l'étape Informations sur la livraison, créez une checkout_index_index.xml
mise à jour de la mise en page dans le <your_module_dir>/view/frontend/layout/
.
Il devrait être similaire au suivant.
<?xml version="1.0"?>
<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="before-form" xsi:type="array">
<item name="children" xsi:type="array">
<!-- Your form declaration here -->
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</argument>
</arguments>
</referenceBlock>
</body>
</page>
Formes statiques:
L'exemple de code suivant montre la configuration du formulaire qui contient quatre champs: saisie de texte, sélection, case à cocher et date. Ce formulaire utilise le fournisseur de données de paiement (checkoutProvider) qui est introduit dans le module Magento_Checkout:
<item name="custom-checkout-form-container" xsi:type="array">
<item name="component" xsi:type="string">%your_module_dir%/js/view/custom-checkout-form</item>
<item name="provider" xsi:type="string">checkoutProvider</item>
<item name="config" xsi:type="array">
<item name="template" xsi:type="string">%your_module_dir%/custom-checkout-form</item>
</item>
<item name="children" xsi:type="array">
<item name="custom-checkout-form-fieldset" xsi:type="array">
<!-- uiComponent is used as a wrapper for form fields (its template will render all children as a list) -->
<item name="component" xsi:type="string">uiComponent</item>
<!-- the following display area is used in template (see below) -->
<item name="displayArea" xsi:type="string">custom-checkout-form-fields</item>
<item name="children" xsi:type="array">
<item name="text_field" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/form/element/abstract</item>
<item name="config" xsi:type="array">
<!-- customScope is used to group elements within a single form (e.g. they can be validated separately) -->
<item name="customScope" xsi:type="string">customCheckoutForm</item>
<item name="template" xsi:type="string">ui/form/field</item>
<item name="elementTmpl" xsi:type="string">ui/form/element/input</item>
</item>
<item name="provider" xsi:type="string">checkoutProvider</item>
<item name="dataScope" xsi:type="string">customCheckoutForm.text_field</item>
<item name="label" xsi:type="string">Text Field</item>
<item name="sortOrder" xsi:type="string">1</item>
<item name="validation" xsi:type="array">
<item name="required-entry" xsi:type="string">true</item>
</item>
</item>
<item name="checkbox_field" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/form/element/boolean</item>
<item name="config" xsi:type="array">
<!--customScope is used to group elements within a single form (e.g. they can be validated separately)-->
<item name="customScope" xsi:type="string">customCheckoutForm</item>
<item name="template" xsi:type="string">ui/form/field</item>
<item name="elementTmpl" xsi:type="string">ui/form/element/checkbox</item>
</item>
<item name="provider" xsi:type="string">checkoutProvider</item>
<item name="dataScope" xsi:type="string">customCheckoutForm.checkbox_field</item>
<item name="label" xsi:type="string">Checkbox Field</item>
<item name="sortOrder" xsi:type="string">3</item>
</item>
<item name="select_field" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/form/element/select</item>
<item name="config" xsi:type="array">
<!--customScope is used to group elements within a single form (e.g. they can be validated separately)-->
<item name="customScope" xsi:type="string">customCheckoutForm</item>
<item name="template" xsi:type="string">ui/form/field</item>
<item name="elementTmpl" xsi:type="string">ui/form/element/select</item>
</item>
<item name="options" xsi:type="array">
<item name="0" xsi:type="array">
<item name="label" xsi:type="string">Please select value</item>
<item name="value" xsi:type="string"></item>
</item>
<item name="1" xsi:type="array">
<item name="label" xsi:type="string">Value 1</item>
<item name="value" xsi:type="string">value_1</item>
</item>
<item name="2" xsi:type="array">
<item name="label" xsi:type="string">Value 2</item>
<item name="value" xsi:type="string">value_2</item>
</item>
</item>
<!-- value element allows to specify default value of the form field -->
<item name="value" xsi:type="string">value_2</item>
<item name="provider" xsi:type="string">checkoutProvider</item>
<item name="dataScope" xsi:type="string">customCheckoutForm.select_field</item>
<item name="label" xsi:type="string">Select Field</item>
<item name="sortOrder" xsi:type="string">2</item>
</item>
<item name="date_field" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/form/element/date</item>
<item name="config" xsi:type="array">
<!--customScope is used to group elements within a single form (e.g. they can be validated separately)-->
<item name="customScope" xsi:type="string">customCheckoutForm</item>
<item name="template" xsi:type="string">ui/form/field</item>
<item name="elementTmpl" xsi:type="string">ui/form/element/date</item>
</item>
<item name="provider" xsi:type="string">checkoutProvider</item>
<item name="dataScope" xsi:type="string">customCheckoutForm.date_field</item>
<item name="label" xsi:type="string">Date Field</item>
<item name="validation" xsi:type="array">
<item name="required-entry" xsi:type="string">true</item>
</item>
</item>
</item>
</item>
</item>
</item>
J'espère que cela t'aides.