Necesito agregar dos campos personalizados en cada paso de envío y pago de la página de pago en Magento 2 y también los datos deben guardarse en las tablas necesarias
cómo hacerlo en Magento 2
Hoy voy a explicar cómo agregar campos personalizados a todos los pasos de la página de pago y guardarlos después de realizar el pedido y también cómo usar los datos publicados después de realizar el pedido
1er campo delivery_date
: - donde el cliente mencionará en la fecha de entrega en el paso de envío
Comentarios del orden de los 2dos campos : - estará en el paso de Pago y después de realizar el pedido, estos comentarios se agregarán al historial de comentarios del pedido
Paso 1 : asegúrese de agregar delivery_date en todas las tablas de necesidades, como presupuesto, sales_order
y a sales_order_grid
través de la secuencia de comandos de instalación o actualización
<?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();
}
}
Paso 2 : - Agregando campos personalizados en los pasos de envío y pago, podemos lograr de dos maneras, uno desde layout xml
y otro es el complemento a continuación, es la forma de agregar los campos a través del complemento
Creamos un di.xml
archivo en nuestro módulo -Sugarcode/Deliverydate/etc/frontend/di.xml
Usamos el área de la interfaz para mantenerlo limpio, nuestro complemento solo debe ejecutarse en la interfaz.
<?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;
}
}
Ahora todos los campos están en la página de pago, ahora cómo guardar los datos
a diferencia de M1 en M2, todas las páginas de pago están completamente desactivadas JS y API
Tenemos dos pasos, el primero es el envío y el segundo paso es el pago donde necesitamos guardar ambos campos
A continuación se muestra cómo guardar los datos después de guardar las direcciones de envío.
Paso de envío
Para guardar la información de envío en M2 utiliza
app/code/Magento/Checkout/view/frontend/web/js/model/shipping-save-processor/default.js
para preparar json
y la llamada, api
por lo que debemos anular este js y en el php
lado guardado sucederá
\ Magento \ Checkout \ Model \ ShippingInformationManagement :: SaveAddressInformation () y ShippingInformationManagement implementado por Magento \ Checkout \ Api \ Data \ ShippingInformationInterface
M2 tiene un concepto poderoso llamado extension_attributes
que se usa para datos dinámicos en tablas centrales, hagamos uso de eso
paso 3 : crea un archivoDeliverydate/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>
para anular js crear un archivo js Deliverydate/view/frontend/requirejs-config.js
necesitamos usar mezclas
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();
});
};
});
El siguiente paso es guardar los datos de publicación de este campo personalizado en la cotización. Hagamos otro complemento agregando un nodo xml en nuestroetc/di.xml
<type name="Magento\Checkout\Model\ShippingInformationManagement">
<plugin name="save-in-quote" type="Sugarcode\Deliverydate\Plugin\Checkout\ShippingInformationManagementPlugin" sortOrder="10"/>
</type>
Cree un archivo 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);
}
}
poco después, cuando pase a los pasos de pago, los datos se guardarán en la tabla de cotizaciones
para guardar los mismos datos después de realizar el pedido, necesitamos usar el conjunto de campos
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>
Ahora vamos a guardar el campo de pasos de pago
si tenemos campos adicionales en el paso de pago y necesitamos publicar esos datos, entonces necesitamos anular los otros js como lo hicimos para el paso de envío
como la información de envío tenemos información de pago
ww puede lograr mediante anulación es Magento_Checkout/js/action/place-order.js
(pero tendrá un problema cuando se habilite el acuerdo, por lo que debemos usar mixins como se menciona en 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);
});
};
});
y necesita crear un complemento para Magento\Checkout\Model\PaymentInformationManagement
así que etc/di
agregue el siguiente código
<type name="Magento\Checkout\Model\PaymentInformationManagement">
<plugin name="order_comments_save-in-order" type="Sugarcode\Deliverydate\Plugin\Checkout\PaymentInformationManagementPlugin" sortOrder="10"/>
</type>
y luego crea un archivo 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;
}
}
Nota: si el campo en el paso de pago necesita guardarse en la tabla de cotizaciones, use antes el complemento para la misma función y siga como se hizo en ShippingInformationManagementPlugin
Antes de hacer personalizaciones, haga lo siguiente.
Paso 1: cree la implementación JS del componente de interfaz de usuario de formulario
En su
<your_module_dir>/view/frontend/web/js/view/
directorio, cree un archivo .js implementando el formulario.Paso 2: crea la plantilla HTML
Agregue la
knockout.js
plantilla HTML para el componente de formulario en el<your_module_dir>/view/frontend/web/
directorio de plantillas.Ejemplo:
Borrar archivos después de la modificación
Si modifica su plantilla .html personalizada después de que se aplicó en las páginas de la tienda, los cambios no se aplicarán hasta que haga lo siguiente:
Elimine todos los archivos en los directorios
pub/static/frontend
yvar/view_preprocessed
. Recargar las páginas.Paso 3: declara el formulario en el diseño de la página de pago
Para agregar contenido al paso Información de envío, cree una
checkout_index_index.xml
actualización de diseño en<your_module_dir>/view/frontend/layout/
.Debería ser similar a lo siguiente.
Formas estáticas:
El siguiente ejemplo de código muestra la configuración del formulario que contiene cuatro campos: entrada de texto, selección, casilla de verificación y fecha. Este formulario utiliza el proveedor de datos de pago (checkoutProvider) que se introduce en el módulo Magento_Checkout:
Espero que esto ayude.
fuente