Magento2.1 – How to Change Product Price with Plugin

checkoutmagento-2.1magento2priceproduct

UPDATE

After a lot of debugging I found out that the plugin is loaded on the product detail page but not in the checkout.
It seems that the checkout gets the values from somewhere before so that is why the price is correct initially. But if Javascript is triggered it goes through the module loading process again and there the plugin is not loaded. Thus the original magento database price is loaded.

The problem seems to be in var/generation/Magento/Catalog/Model/Product/Interceptor.php
in function getPrice.
There they fetch $pluginInfo and this contains an array with my plugin. But only on the product detail page. In the checkout this array is always null and therefor it only calls parent::getPrice().

I wonder why my plugin is not loaded in the checkout?

Here is how I setup the plugin:

registration.php

<?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    '<vendor>_<plugin>',
    __DIR__
);

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">
    <type name="Magento\Catalog\Model\Product" shared="false">
        <plugin
                name="<vendor>_<plugin>_productplugin"
                type="\<vendor>\<plugin>\Plugin\Product\ProductPlugin"
                disabled="false"
                sortOrder="999" />
    </type>
</config>

app/code/<vendor>/<plugin>/Plugin/Product/ProductPlugin.php

<?php

namespace <vendor>\<plugin>\Plugin\Product;

class ProductPlugin
{
    public function afterGetPrice($product, $proceed) : float
    {
        return 111.55;
    }

}

OLD INFO

I already build a mage2-module with a plugin for Magento\Catalog\Model\Product and created an afterGetPrice() method. This works fine for:

  • product detail page
  • checkout/cart product listing on the left

But the problem is that the widget/sidebar summary component at the checkout on the right side of the e.g. Luma theme shows the right prices for a short moment, than an ajax request to the Magento REST-API changes all prices to the normal Magento product prices so the plugin does not work here.

Before everything is ok and can be checkt via console:

window.checkoutConfig;

quoteData and totalsData have got the proper prices. Later they will be updated by the response of totals-information.

I think these endpoints could be used for this action depending on the situation:

POST   /V1/carts/:cartId/totals-information
POST   /V1/guest-carts/:cartId/totals-information
POST   /V1/carts/mine/totals-information

<preference for="Magento\Checkout\Api\Data\TotalsInformationInterface" type="Magento\Checkout\Model\TotalsInformation" />
<preference for="Magento\Checkout\Api\GuestTotalsInformationManagementInterface" type="Magento\Checkout\Model\GuestTotalsInformationManagement" />
<preference for="Magento\Checkout\Api\TotalsInformationManagementInterface" type="Magento\Checkout\Model\TotalsInformationManagement" />

In my own theme no such reloading takes place but in step 2 of the onepage checkout the prices are also wrong.

How can I achieve to overwrite the prices in the frontend with my own
prices and in case of no data with the original price, like the
afterGetPrice() function does?

Here you can see the process in screenshots:

  1. first it loads the page with the correct price (sorry it's german language)
    enter image description here

  2. then it reloads the summary box
    enter image description here

  3. after the refresh the price is the magento price without the afterGetPrice() method being runenter image description here

Best Answer

The problem is that I placed the di.xml into the frontend subfolder, thinking that this defines the area the plugin applies to. But reading the docu ( http://devdocs.magento.com/guides/v2.1/architecture/archi_perspectives/components/modules/mod_and_areas.html )

Magento area types

Magento is organized into these main areas:

Magento Admin (adminhtml): entry point for this area is index.php or pub/index.php. The Admin panel area includes the code needed for store management. The /app/design/adminhtml directory contains all the code for components you’ll see while working in the Admin panel.

Storefront (frontend): entry point for this area is index.php or pub/index.php. The storefront (or frontend) contains template and layout files that define the appearance of your storefront.

Basic (base): used as a fallback for files absent in adminhtml and frontend areas.

again it seems that frontend refers only to display purposes but not saving or anything.