EE 1.14.2 / CE 1.9.2: Котирування елементів, неправильно об'єднаних під час входу (копії продуктів у кошику)


16

Я знайшов дивну помилку в Magento EE 1.14.2 (також впливає на CE 1.9.2) з візком.

Кроки до відтворення:

  1. Увійдіть як клієнт A
  2. Додати продукт X у кошик
  3. Переключіться на інший веб-переглядач
  4. Додати продукт X у кошик
  5. Увійдіть як клієнт A

Очікувана кошик:

  • 2 х товар X

Актуальний кошик:

  • 1 х товар X
  • 1 х товар X

Тобто продукти не злиті.

Замість того, щоб перемикати браузер, ви також можете очистити сеансовий файл cookie або вибрати іншу кількість для продукту.

Найгірший побічний ефект цього полягає в тому, що максимальна кількість замовлень застосовується на кожен товар. У моєму випадку на продукт була 100% знижка, але ви могли замовити її лише один раз. За допомогою цієї маленької хитрості ви можете замовити її в будь-якій кількості безкоштовно.

Чому це відбувається і як я можу це запобігти?

Відповіді:


18

Гарне загортання клопа вгорі, Фабіане!

Для будь-яких інших користувачів, які зіткнуться з цією помилкою, для цього вже є патч від Magento.

Як клієнт Enterprise, ви можете подати запит / завантажити, PATCH_SUPEE-6190_EE_1.14.2.0_v1.shщоб виправити це.

Оновлення 24.02.2016: це також було вирішено в останньому патчі SUPEE-7405 v 1.1. За словами Фабіана в Twitter (див. Це та наступні твіти ), є ймовірність, що це все ще не вирішено повністю. Будь ласка, протестуйте і самі.

Що стосується EE 1.14.2.0, рішення:

diff --git a/app/code/core/Mage/Sales/Model/Quote/Item.php b/app/code/core/Mage/Sales/Model/Quote/Item.php
index 3554faa..d759249 100644
--- a/app/code/core/Mage/Sales/Model/Quote/Item.php
+++ b/app/code/core/Mage/Sales/Model/Quote/Item.php
@@ -502,8 +502,8 @@ class Mage_Sales_Model_Quote_Item extends Mage_Sales_Model_Quote_Item_Abstract
                         $itemOptionValue = $_itemOptionValue;
                         $optionValue = $_optionValue;
                         // looks like it does not break bundle selection qty
-                        unset($itemOptionValue['qty'], $itemOptionValue['uenc']);
-                        unset($optionValue['qty'], $optionValue['uenc']);
+                        unset($itemOptionValue['qty'], $itemOptionValue['uenc'], $itemOptionValue['form_key']);
+                        unset($optionValue['qty'], $optionValue['uenc'], $optionValue['form_key']);
                     }
                 }

Примітка: Зазвичай я б не розміщував тут код EE, але оскільки проблема / файли такі ж, як у CE, і не впливають на функцію, що стосується лише EE, я сподіваюся, що це нормально.


4
Я схвалюю це.
philwinkle

5
Ми дозволимо йому ковзати.
орієнтири

1
Пересуньте це тоді.
Маріус

Це працює краще, ніж моє виправлення, що спричинило проблеми з продуктами в комплекті. Дякую, що поділились!
Фабіан Шменглер

1
На жаль, це все-таки можна обійти, якщо додати товар один раз через список товарів та один раз на сторінці деталей продукту, оскільки параметр "related_products" присутній лише в останньому випадку. Ви також можете додавати "related_products" до unset()дзвінків, але це все ще не є безпечним, оскільки будь-який довільний параметр POST також додається до опції buyRequest. Я замість цього повністю ігнорую цю опцію.
Фабіан Шменглер

15

Виявилося, що це помилка Mage_Sales_Model_Quote_Item::compare() тому, що була введена в Magento CE 1.9.2 / EE 1.14.2. Метод використовується для порівняння предметів, щоб визначити, чи є вони одним і тим же продуктом і чи можна об'єднати (під час входу в систему та при додаванні продуктів у кошик).

Порівнюючи всі власні параметри, слід пропустити параметри, які не є репрезентативними ( _notRepresentOptions), а саме опцією info_buyRequest .

У попередніх версіях Magento це виглядало так:

foreach ($this->getOptions() as $option) {
    if (in_array($option->getCode(), $this->_notRepresentOptions)) {
        continue;
    }

і працювали правильно. Тепер це виглядає так:

foreach ($this->getOptions() as $option) {
    if (in_array($option->getCode(), $this->_notRepresentOptions)
        && !$item->getProduct()->hasCustomOptions()
    ) {
        continue;
    }

і додатковий чек на hasCustomOptions() причин описаної помилки. Чому? Схоже, чек додано, щоб завжди тримати продукти окремими опціями. Я не думаю, що це має сенс, принаймні, не в тому, як це реалізується, але для цього будуть деякі причини, про які я не знаю.

Однак, $item->getProduct()->hasCustomOptions() завжди повертає істину для предметів цитат!

Це метод:

public function hasCustomOptions()
{
    if (count($this->_customOptions)) {
        return true;
    } else {
        return false;
    }
}

Але $this->_customOptions також містить info_buyRequestваріант із пункту цитати.

Для ненав'язливого рішення я спробував видалити info_buyRequest варіант із усіх продуктів у спостерігача sales_quote_merge_before, не маючи успіху.

Причина полягає в тому, Mage_Sales_Model_Quote_Item_Abstract::getProduct()де параметр знову копіюється з самого пункту цитування:

public function getProduct()
{
    $product = $this->_getData('product');

    [...]

    if (is_array($this->_optionsByCode)) {
        $product->setCustomOptions($this->_optionsByCode);
    }
    return $product;
}

Рішення

Я створив перезапис для Mage_Sales_Model_Quote_Itemз заміною для того, getProduct()щоб не включати info_buyRequestпараметр у цьому пункті:

public function getProduct() { $product = parent::getProduct(); $options = $product->getCustomOptions(); if (isset($options['info_buyRequest'])) { unset($options['info_buyRequest']); $product->setCustomOptions($options); } return $product; }

Це спричинило проблеми з продуктами в комплекті, альтернативою нижче або офіційним виправленням, як описано @ AnnaVölkl, є кращим рішенням

Альтернатива

Ви також можете видалити порушників && !$item->getProduct()->hasCustomOptions()уcompare() методі, якщо ви все одно перепишете модель товару. Я не знаю, яку проблему вона намагалася вирішити, але це створило більше ...

Оновити 29 січня 2016 року

Я повідомив про це Magento і отримав відповідь, що вони не можуть відтворити проблему, тому патч не ввійде у видання для громади (Submission APPSEC-1321).

Це означає, що якщо у вас є проблеми, вам потрібно застосувати корпоративний патч SUPEE-6190 після кожного оновлення або використовувати замість цього перезапис класу.


However, $item->getProduct()->hasCustomOptions() always returns true for quote items!Це перевірка даних про товар на користувальницькі опції, а не пункт цитати :)
kanevbgbe

1
@kanevbgbe дивно, ні. Magento "готує" екземпляр продукту, пов’язаний із котируванням, і додає значення спеціальних параметрів
Fabian Schmengler

Я знаю, що при додаванні до кошика екземпляр продукту завантажується повністю (порівняно з завантаженням цитат), тому він встановлюється поза алгоритмами цитати безпосередньо до екземпляра елемента цитати через setProduct (), можливо, тоді ця перевірка має інший вихід .
kanevbgbe

1

Як я бачу, вищезазначена відповідь уже доступна в останній версії Magento, але ми все ще отримували проблему. Це не спрацювало, тому що ми зробили багато налаштувань. Думав поділитися рішенням.

Для нас це було дуже просто, оскільки ми використовуємо лише прості продукти. Отже, ми розширили функцію порівняння об'єднань цитат на цю:

NS_Module_Model_Sales_Quote_Item розширює Mage_Sales_Model_Quote_Item {

public function compare($item) {
    if ($this->getProductId() == $item->getProductId()) {
        return true;
    }
    return parent::compare($item);
}

}

і додав

<models>
   <sales>
      <rewrite>
         <quote_item>NS_Module_Model_Sales_Quote_Item</quote_item>
      </rewrite>
   </sales>
</models>

але. для тих, хто також використовує налаштовані продукти, то це може бути не корисним для вас. У цьому випадку ви можете надрукувати обидва масиви: $ itemOptionValue та $ optionValue і побачити різницю. скиньте всі додаткові клавіші, які не є звичними для обох масивів. Це повинно вирішити проблему.


-1

Ви можете просто додати опцію до продукту у події sales_quote_add_item:

$data['microtime'] = microtime(true);
$product->addCustomOption('do_not_merge', serialize($data));
$item->addOption($product->getCustomOption('do_not_merge'));

Посилання на посилання: Вимкнути об'єднання позицій кошика?


Це вирішення, але повністю вимикати об'єднання елементів зазвичай не бажано.
Фабіан Шменглер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.