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製品X

実際のカート:

  • 1 x製品X
  • 1 x製品X

つまり、製品はマージされません。

ブラウザを切り替える代わりに、セッションCookieをクリアするか、製品に別の数量を選択することもできます。

これの最悪の副作用は、アイテムごとに最大注文数量が適用されることです。私の場合、製品には100%の割引がありましたが、一度しか注文できませんでした。この小さなトリックを使用すると、無料で任意の数量で注文できます。

なぜこれが起こり、どうすればそれを防ぐことができますか?

回答:


18

上記のバグの素敵なまとめ、ファビアン!

このバグに遭遇する今後のユーザーには、Magentoからのパッチがすでにあります。

エンタープライズのお客様は、PATCH_SUPEE-6190_EE_1.14.2.0_v1.shこれを修正するためにリクエスト/ダウンロードできます。

更新 2016.02.2016 これは、最新のSUPEE-7405 v 1.1パッチでも対処されました。TwitterのFabianによると(これと以下のツイートを参照)、まだ完全に解決されていない可能性があります。自分でテストしてください。

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
それからスライドします。
マリウス

これは、バンドル製品で問題を引き起こした私の修正よりもうまく機能します。共有してくれてありがとう!
ファビアンシュメングラー16年

1
残念ながら、「related_products」パラメーターは後者の場合にのみ存在するため、製品リストから1回、製品詳細ページから1回製品を追加する場合、これはまだバイパスできます。unset()呼び出しに「related_products」を追加することもできますが、任意のPOSTパラメーターがbuyRequestオプションにも追加されるため、まだ安全ではありません。代わりに、このオプションを完全に無視します。
ファビアンシュメングラー

15

これはバグであることが判明しました Mage_Sales_Model_Quote_Item::compare() Magento CE 1.9.2 / EE 1.14.2で導入されことがました。このメソッドは、アイテムを比較して、同じ製品であり、マージできるかどうかを決定するために使用されます(ログイン中およびカートに製品を追加するとき)。

すべてのカスタムオプションを比較するとき、それはrepresantativeないオプション(スキップする_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()見積品目については常にtrueを返します!

これがメソッドです:

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()とにかくアイテムモデルを書き換えている場合メソッドます。どのような問題を解決しようとしたのかわかりませんが、それはさらに多くを生み出しました...

2016年1月29日更新

これをMagentoに報告し、問題を再現できなかったという応答を受け取ったので、パッチはコミュニティ版になりません(提出APPSEC-1321)。

つまり、問題がある場合は、各更新後にエンタープライズパッチSUPEE-6190を適用するか、代わりにクラスの書き換えを使用する必要があります。


However, $item->getProduct()->hasCustomOptions() always returns true for quote items!見積品目ではなく、カスタムオプションの製品データを確認しています:)
kanevbgbe

1
@kanevbgbe驚いたことに、いいえ。Magentoは、見積品目に関連付けられた製品インスタンスを「準備」し、そのカスタムオプション値を追加します
ファビアンシュメングラー

カートに追加アクションでは、製品インスタンスが完全にロードされるので(見積もりの​​ロードと比較して)、見積もりの​​アルゴリズムの外部から直接setItem()を介して見積もりアイテムインスタンスに設定されるため、このチェックの出力は異なる可能性があります。
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'));

参照リンク:カート位置のマージを無効にしますか?


これは回避策ですが、通常、アイテムのマージを完全に無効にすることは望ましくありません。
ファビアンシュメングラー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.