Magento 2 - la remise dépend de la méthode de paiement ne fonctionne pas

13

Je vais dans Magento 2 Admin> Marketing> Promotions> Règles de prix du panier et crée une nouvelle règle: Paiement par virement bancaire:

Informations sur la règle de tabulation:

  • Nom de la règle: Paiement par virement bancaire
  • Statut: Actif
  • Sites Web: site Web principal
  • Groupes de clients: tout sélectionner
  • Coupon: Aucun coupon
  • Utilisations par client: 0
  • De: vide
  • À: vide
  • Priorité: 0
  • Public dans le flux RSS: Non

Onglet Conditions:

  • Si TOUTES ces conditions sont VRAIES:
    • La méthode de paiement est le paiement par virement bancaire

Onglet Actions:

  • Appliquer: pourcentage de remise sur le prix du produit
  • Montant du rabais: 2
  • La remise de quantité maximale est appliquée à: 0
  • Étape de remise (acheter X): 0
  • Appliquer au montant d'expédition: Non
  • Ignorer les règles suivantes: Non
  • Livraison gratuite: Non
  • Appliquer la règle uniquement aux articles du panier répondant aux conditions suivantes (laisser vide pour tous les articles): rien

Ensuite, j'active la méthode de paiement par virement bancaire, accédez à la page de paiement, cliquez sur Paiement par virement bancaire, mais le prix en pourcentage de la remise n'apparaît pas dans le résumé de la commande.

entrez la description de l'image ici

Veuillez me donner un conseil. Comment faire une remise sur le mode de paiement sur Magento 2. Pour Magento 1, ça marche bien.

Merci beaucoup

Nguyễn Hồng Quang
la source
Vous pouvez poster votre règle ici?
Khoa TruongDinh
J'ai posté ma règle. Pouvez-vous vérifier pour moi s'il vous plaît?
Nguyễn Hồng Quang
Essayez d'ajouter la date activée de la règle?
Khoa TruongDinh
J'essaie d'ajouter la date de début de la règle, mais rien ne se passe toujours dans le récapitulatif de la commande lorsque je clique sur l'option de paiement par virement bancaire
Nguyễn Hồng Quang
1
Merci. J'ai posté le problème ici: github.com/magento/magento2/issues/5937
Nguyễn Hồng Quang

Réponses:

11

Cette règle ne fonctionne pas, car Magento 2 n'enregistre pas le mode de paiement à proposer lorsque vous en sélectionnez un. Et il ne recharge pas non plus les totaux lors de la sélection d'un mode de paiement. Et malheureusement, vous devez écrire un module personnalisé pour résoudre le problème.

Le nouveau module n'a besoin que de 4 fichiers pour être créé:

  1. app / code / Namespace / ModuleName / etc / frontend / routes.xml

    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
        <router id="standard">
            <route id="namespace_modulename" frontName="namespace_modulename">
                <module name="Namespace_ModuleName"/>
            </route>
        </router>
    </config>

    Cela définira un nouveau contrôleur pour notre module.

  2. app / code / Espace de noms / ModuleName / Controller / Checkout / ApplyPaymentMethod.php

    <?php
    
    namespace Namespace\ModuleName\Controller\Checkout;
    
    class ApplyPaymentMethod extends \Magento\Framework\App\Action\Action
    {
        /**
         * @var \Magento\Framework\Controller\Result\ForwardFactory
         */
        protected $resultForwardFactory;
    
        /**
         * @var \Magento\Framework\View\LayoutFactory
         */
        protected $layoutFactory;
    
        /**
         * @var \Magento\Checkout\Model\Cart
         */
        protected $cart;
    
        /**
         * @param \Magento\Framework\App\Action\Context $context
         * @param \Magento\Framework\View\LayoutFactory $layoutFactory
         * @param \Magento\Framework\Controller\Result\ForwardFactory $resultForwardFactory
         */
        public function __construct(
            \Magento\Framework\App\Action\Context $context,
            \Magento\Framework\Controller\Result\ForwardFactory $resultForwardFactory,
            \Magento\Framework\View\LayoutFactory $layoutFactory,
            \Magento\Checkout\Model\Cart $cart
        ) {
            $this->resultForwardFactory = $resultForwardFactory;
            $this->layoutFactory = $layoutFactory;
            $this->cart = $cart;
    
            parent::__construct($context);
        }
    
        /**
         * @return \Magento\Framework\Controller\ResultInterface
         */
        public function execute()
        {
            $pMethod = $this->getRequest()->getParam('payment_method');
    
            $quote = $this->cart->getQuote();
    
            $quote->getPayment()->setMethod($pMethod['method']);
    
            $quote->setTotalsCollectedFlag(false);
            $quote->collectTotals();
            $quote->save();
        }
    }

    Ce fichier crée une action du contrôleur pour enregistrer le mode de paiement sélectionné pour le devis

  3. app / code / Namespace / ModuleName / view / frontend / requirejs-config.js

    var config = {
        map: {
            '*': {
                'Magento_Checkout/js/action/select-payment-method':
                    'Namespace_ModuleName/js/action/select-payment-method'
            }
        }
    };

    Ce fichier permet de remplacer le Magento_Checkout/js/action/select-payment-methodfichier

  4. app / code / Espace de noms / ModuleName / view / frontend / web / js / action / select-payment-method.js

    define(
        [
            'Magento_Checkout/js/model/quote',
            'Magento_Checkout/js/model/full-screen-loader',
            'jquery',
            'Magento_Checkout/js/action/get-totals',
        ],
        function (quote, fullScreenLoader, jQuery, getTotalsAction) {
            'use strict';
            return function (paymentMethod) {
                quote.paymentMethod(paymentMethod);
    
                fullScreenLoader.startLoader();
    
                jQuery.ajax('/namespace_modulename/checkout/applyPaymentMethod', {
                    data: {payment_method: paymentMethod},
                    complete: function () {
                        getTotalsAction([]);
                        fullScreenLoader.stopLoader();
                    }
                });
    
            }
        }
    );

    Envoie une demande ajax pour enregistrer le mode de paiement et recharger les totaux du panier.

PS Certaines parties du code proviennent de l' extension des frais de paiement pour Magento 2.

MagestyApps
la source
1
Merci beaucoup MagestyApps, j'ai créé un nouveau module, suivez vos instructions. Cependant, à la fin, j'ai eu ce problème jquery.js 192.168.41.59/phoenix_checkout/checkout/applyPaymentMethod 404 (Not Found). Avez-vous eu ce bug avant?
Nguyễn Hồng Quang
1
Ça marche vraiment bien. Merci beaucoup à MagestyApps. Cette solution est parfaite.
Nguyễn Hồng Quang du
Ça marche, tu m'as fait gagner du temps. Merci :)
Sameer Bhayani
Des trucs géniaux, merci. La règle de prix du panier pour les méthodes de paiement a été supprimée btw ( github.com/magento/magento2/commit/… ). J'ai ajouté la ligne "'payment_method' => __ ('Payment Method')", encore une fois, maintenant je peux créer des règles de prix de panier pour les méthodes de paiement.
DaFunkyAlex
Cela a beaucoup aidé. Merci. +1 :)
Shoaib Munir
3

Sur Magento 2.2, je n'ai pas pu faire fonctionner la réponse de MagestyApps. J'avais besoin d'ajouter des fichiers supplémentaires. Car:

  • La règle de prix du panier pour la méthode de paiement a été supprimée de l'administrateur (comme l'a souligné DaFunkyAlex);
  • Dans Magento 2.2, la remise n'était pas appliquée sur le devis, car la méthode \Magento\AdvancedSalesRule\Model\Rule\Condition\FilterTextGenerator\Address\PaymentMethod::generateFilterText(en fait, elle revient à \Magento\AdvancedSalesRule\Model\Rule\Condition\FilterTextGenerator\Address::generateFilterText), s'attendait à ce que les données payment_methodsoient définies sur les adresses de devis;
  • Même changer le contrôleur de la réponse de MagestyApps pour définir les payment_methoddonnées sur les adresses de devis, n'a pas fonctionné lorsque le devis est devenu une commande, car il ne persiste pas payment_method;

Le module suivant a fonctionné pour moi (grâce à la réponse de MagestyApps, il était basé sur cela):

registration.php

<?php

\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Vendor_SalesRulesPaymentMethod',
    __DIR__
);

etc / module.xml

<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Vendor_SalesRulesPaymentMethod" setup_version="1.0.0">
        <sequence>
            <module name="Magento_AdvancedSalesRule"/>
            <module name="Magento_Checkout"/>
            <module name="Magento_SalesRules"/>
            <module name="Magento_Quote"/>
        </sequence>
    </module>
</config>

etc / di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="Magento\AdvancedSalesRule\Model\Rule\Condition\FilterTextGenerator\Address\PaymentMethod"
                type="Vendor\SalesRulesPaymentMethod\Model\Rule\Condition\FilterTextGenerator\Address\PaymentMethod"/>
    <type name="Magento\SalesRule\Model\Rule\Condition\Address">
        <plugin name="addPaymentMethodOptionBack" type="Vendor\SalesRulesPaymentMethod\Plugin\AddPaymentMethodOptionBack" />
    </type>
</config>

etc / frontend / routes.xml

<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="standard">
        <route id="salesrulespaymentmethod" frontName="salesrulespaymentmethod">
            <module name="Vendor_SalesRulesPaymentMethod"/>
        </route>
    </router>
</config>

Controller / Checkout / ApplyPaymentMethod.php

<?php

namespace Vendor\SalesRulesPaymentMethod\Controller\Checkout;

use Magento\Checkout\Model\Cart;
use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Magento\Framework\App\ResponseInterface;
use Magento\Framework\Controller\Result\ForwardFactory;
use Magento\Framework\Controller\ResultInterface;
use Magento\Framework\View\LayoutFactory;
use Magento\Quote\Model\Quote;

class ApplyPaymentMethod extends Action
{
    /**
     * @var ForwardFactory
     */
    protected $resultForwardFactory;

    /**
     * @var LayoutFactory
     */
    protected $layoutFactory;

    /**
     * @var Cart
     */
    protected $cart;

    /**
     * @param Context $context
     * @param LayoutFactory $layoutFactory
     * @param ForwardFactory $resultForwardFactory
     */
    public function __construct(
        Context $context,
        ForwardFactory $resultForwardFactory,
        LayoutFactory $layoutFactory,
        Cart $cart
    ) {
        $this->resultForwardFactory = $resultForwardFactory;
        $this->layoutFactory = $layoutFactory;
        $this->cart = $cart;

        parent::__construct($context);
    }

    /**
     * @return ResponseInterface|ResultInterface|void
     * @throws \Exception
     */
    public function execute()
    {
        $pMethod = $this->getRequest()->getParam('payment_method');

        /** @var Quote $quote */
        $quote = $this->cart->getQuote();

        $quote->getPayment()->setMethod($pMethod['method']);

        $quote->setTotalsCollectedFlag(false);
        $quote->collectTotals();

        $quote->save();
    }
}

Modèle / Règle / Condition / FilterTextGenerator / Adresse / PaymentMethod.php

<?php

namespace Vendor\SalesRulesPaymentMethod\Model\Rule\Condition\FilterTextGenerator\Address;

use Magento\AdvancedSalesRule\Model\Rule\Condition\FilterTextGenerator\Address\PaymentMethod as BasePaymentMethod;

class PaymentMethod extends BasePaymentMethod
{
    /**
     * @param \Magento\Framework\DataObject $quoteAddress
     * @return string[]
     */
    public function generateFilterText(\Magento\Framework\DataObject $quoteAddress)
    {
        $filterText = [];
        if ($quoteAddress instanceof \Magento\Quote\Model\Quote\Address) {
            $value = $quoteAddress->getQuote()->getPayment()->getMethod();
            if (is_scalar($value)) {
                $filterText[] = $this->getFilterTextPrefix() . $this->attribute . ':' . $value;
            }
        }

        return $filterText;
    }
}

Plugin / AddPaymentMethodOptionBack.php

<?php

namespace Vendor\SalesRulesPaymentMethod\Plugin;

use Magento\SalesRule\Model\Rule\Condition\Address;

class AddPaymentMethodOptionBack
{
    /**
     * @param Address $subject
     * @param $result
     * @return Address
     */
    public function afterLoadAttributeOptions(Address $subject, $result)
    {
        $attributeOption = $subject->getAttributeOption();
        $attributeOption['payment_method'] = __('Payment Method');

        $subject->setAttributeOption($attributeOption);

        return $subject;
    }
}

voir / frontend / requirejs-config.js

var config = {
    map: {
        '*': {
            'Magento_Checkout/js/action/select-payment-method':
                'Vendor_SalesRulesPaymentMethod/js/action/select-payment-method'
        }
    }
};

voir / frontend / web / js / action / select-payment-method.js

define(
    [
        'Magento_Checkout/js/model/quote',
        'Magento_Checkout/js/model/full-screen-loader',
        'jquery',
        'Magento_Checkout/js/action/get-totals',
    ],
    function (quote, fullScreenLoader, jQuery, getTotalsAction) {
        'use strict';
        return function (paymentMethod) {
            quote.paymentMethod(paymentMethod);

            fullScreenLoader.startLoader();

            jQuery.ajax('/salesrulespaymentmethod/checkout/applyPaymentMethod', {
                data: {payment_method: paymentMethod},
                complete: function () {
                    getTotalsAction([]);
                    fullScreenLoader.stopLoader();
                }
            });

        }
    }
);
missoxd
la source
Je reçois quand vous essayez de compiler: Fatal error: Class 'Magento\AdvancedSalesRule\Model\Rule\Condition\Address\PaymentMethod' not found in Vendor/SalesRulesPaymentMethod/Model/Rule/Condition/FilterTextGenerator/Address/PaymentMethod.php on line 7. J'ai même essayé de changer AdvancedSalesRule en SalesRule car je peux voir qu'il n'y a pas de modèle AdvancedSalesRule dans Magento 2.2.2
Alexandros
pour magento 2.1.9, devrions-nous omettre les pièces AdvancedSalesRule?
Doni Wibowo
Obtention d'une erreur lors de la compilation: Erreur fatale: Classe 'Magento \ AdvancedSalesRule \ Model \ Rule \ Condition \ Address \ PaymentMethod' introuvable dans Vendor / SalesRulesPaymentMethod / Model / Rule / Condition / FilterTextGenerator / Address / PaymentMethod.php on line 7
Magecode
AdvancedSalesRule n'est pas disponible dans Magento 2.1.5
Magecode
2

Nous venons de vérifier la même règle et avons constaté que cela ne fonctionne pas. Dans les mêmes conditions, aucune information sur la méthode choisie sélectionnée n'est envoyée et elle n'est enregistrée nulle part tant que la commande n'est pas passée et que la règle peut ne pas fonctionner.

entrez la description de l'image ici

L'adresse n'a pas de mode de paiement jusqu'à la validation et obtient le mode de paiement du devis de paiement qui n'existe pas car aucune information n'a été envoyée ( $model->getQuote()->getPayment()->getMethod()retours null).

entrez la description de l'image ici

Nous supposons que c'est un bug de Magento. Lorsque vous choisissez un mode de paiement, les informations doivent être envoyées à l'avance.

MageWorx
la source
2
La réponse de MagestyApps est acceptée. Merci.
Nguyễn Hồng Quang
1

La solution avec le module personnalisé fonctionne.

Je pensais juste qu'il serait utile pour les débutants de Magento de savoir que vous devez également ajouter ces fichiers pour pouvoir ajouter et activer ce module:

(copier à partir d'un module différent et modifier les fichiers en fonction du nom et de l'espace de noms de votre module)

app/code/Namespace/ModuleName/composer.js
app/code/Namespace/ModuleName/registration.php
app/code/Namespace/ModuleName/etc/module.xml

alors vous seriez en mesure d'exécuter bin/magento setup:upgrade

Антон Скроботов
la source
0

J'ai créé les fichiers et remplacé les espaces de noms et le nom de module, mais je pense que mes fichiers ne seront pas exécutés.

Peut-être une erreur sur mes fichiers ??

registration.php

<?php

use Magento\Framework\Component\ComponentRegistrar;
ComponentRegistrar::register(
ComponentRegistrar::MODULE,
'Jacor_Checkoutpayment',
__DIR__
);

composer.json

{
"name": "jacor/checkoutpayment",
"autoload": {
    "psr-4": {
        "Jacor\\Checkoutpayment\\": ""
    },
    "files": [
        "registration.php"
    ]
}

}

module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Jacor_Checkoutpayment" setup_version="1.0.0" />
</config>
Tobi
la source
0

en fait, remplacer les fichiers core de magento n'est pas une bonne idée. Au lieu de remplacer, Magento_Checkout/js/action/select-payment-methodmieux créer un mixin pour cela. Et vous pouvez le désactiver sans créer de nouveau contrôleur. Voir ci-dessous (en plus de la réponse @magestyapps)

  1. app / code / Namespace / ModuleName / view / frontend / requirejs-config.js

        var config = {
            config: {
                mixins: {
                    'Magento_Checkout/js/action/select-payment-method': {
                        'Namespace_ModuleName/js/checkout/action/select-payment-method-mixin': true
                    },
                }
            }
        };
  2. app / code / namespace / ModuleName / view / frontend / js / checkout / action / select-payment-method-mixin.js

        define([
        'jquery',
        'mage/utils/wrapper',
        'mage/storage',
        'Magento_Checkout/js/action/get-totals',
        'Magento_Checkout/js/model/full-screen-loader',
        'Magento_Checkout/js/model/quote',
        'Magento_Checkout/js/model/url-builder',
        'Magento_Customer/js/model/customer',
    ], function ($, wrapper, storage, getTotalsAction, fullScreenLoader, quote, urlBuilder, customer) {
        'use strict';
        return function (selectPaymentMethod) {
            return wrapper.wrap(selectPaymentMethod, function (originalAction, paymentMethod) {
                var serviceUrl, payload;
    
                originalAction(paymentMethod);
    
                payload = {
                    method: paymentMethod
                };
                if (customer.isLoggedIn()) {
                    serviceUrl = urlBuilder.createUrl('/carts/mine/selected-payment-method', {});
                } else {
                    serviceUrl = urlBuilder.createUrl('/guest-carts/:cartId/selected-payment-method', {
                        cartId: quote.getQuoteId()
                    });
                }
                fullScreenLoader.startLoader();
                storage.put(
                    serviceUrl,
                    JSON.stringify(payload)
                ).success(function () {
                    getTotalsAction([]);
                    fullScreenLoader.stopLoader();
                });
            });
        };
    });
Styopchik
la source