EE 1.14.2 / CE 1.9.2: Các mục được trích dẫn không được hợp nhất chính xác khi đăng nhập (các sản phẩm trùng lặp trong giỏ hàng)


16

Tôi đã tìm thấy một lỗi kỳ lạ trong Magento EE 1.14.2 (cũng ảnh hưởng đến CE 1.9.2) với giỏ hàng.

Các bước để tái sản xuất:

  1. Đăng nhập với tư cách là khách hàng A
  2. Thêm sản phẩm X vào giỏ hàng
  3. Chuyển sang một trình duyệt khác
  4. Thêm sản phẩm X vào giỏ hàng
  5. Đăng nhập với tư cách là khách hàng A

Giỏ hàng dự kiến:

  • 2 x Sản phẩm X

Giỏ hàng thực tế:

  • 1 x Sản phẩm X
  • 1 x Sản phẩm X

Tức là các sản phẩm không được hợp nhất.

Thay vì chuyển đổi trình duyệt, bạn cũng có thể xóa cookie phiên hoặc chọn một số lượng khác nhau cho sản phẩm.

Tác dụng phụ tồi tệ nhất của việc này là số lượng đặt hàng tối đa được áp dụng cho mỗi mặt hàng. Trong trường hợp của tôi, đã có giảm giá 100% cho một sản phẩm nhưng bạn chỉ có thể đặt hàng một lần. Với thủ thuật nhỏ này, bạn có thể đặt hàng với số lượng miễn phí.

Tại sao điều này xảy ra và làm thế nào tôi có thể ngăn chặn nó?

Câu trả lời:


18

Đẹp bao bọc các lỗi ở trên, Fabian!

Đối với bất kỳ người dùng nào khác sẽ gặp phải lỗi này, đã có bản vá từ Magento cho lỗi này.

Là khách hàng của Doanh nghiệp, bạn có thể yêu cầu / tải xuống PATCH_SUPEE-6190_EE_1.14.2.0_v1.shđể khắc phục điều này.

Cập nhật 24.02.2016: Điều này cũng đã được giải quyết trong bản vá SUPEE-7405 v 1.1 mới nhất. Theo Fabian trên Twitter (xem tweet này và theo các tweet ) có khả năng nó vẫn chưa được giải quyết hoàn toàn. Hãy tự kiểm tra nó.

Đối với EE 1.14.2.0, giải pháp là:

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']);
                     }
                 }

Lưu ý: Thông thường tôi sẽ không đăng mã EE ở đây, nhưng vì sự cố / tệp giống như trong CE và không ảnh hưởng đến tính năng chỉ có EE, tôi hy vọng nó ổn.


4
Tôi chấp nhận điều này.
philwinkle

5
Chúng tôi sẽ để nó trượt.
đánh dấu

1
Trượt nó là sau đó.
Marius

Điều này hoạt động tốt hơn so với sửa chữa của tôi, gây ra rắc rối với các sản phẩm đi kèm. Cám ơn vì đã chia sẻ!
Fabian Schmengler

1
Thật không may, điều này vẫn có thể được bỏ qua nếu bạn thêm sản phẩm một lần qua danh sách sản phẩm và một lần qua trang chi tiết sản phẩm, bởi vì tham số "Rel_products" chỉ xuất hiện trong trường hợp sau. Bạn cũng có thể thêm "Rel_products" vào các unset()cuộc gọi, nhưng nó vẫn không an toàn vì bất kỳ tham số POST tùy ý nào cũng được thêm vào tùy chọn buyRequest. Thay vào đó, tôi sẽ bỏ qua hoàn toàn tùy chọn này.
Fabian Schmengler

15

Hóa ra đây là một lỗi trong Mage_Sales_Model_Quote_Item::compare()đó đã được giới thiệu trong Magento CE 1.9.2 / EE 1.14.2. Phương pháp được sử dụng để so sánh các mục để quyết định xem chúng có phải là cùng một sản phẩm hay không và có thể được hợp nhất (trong khi đăng nhập và khi thêm sản phẩm vào giỏ hàng).

Khi so sánh tất cả các tùy chọn tùy chỉnh, nên bỏ qua các tùy chọn không phản hồi ( _notRepresentOptions), cụ thể là tùy chọn info_buyRequest .

Trong các phiên bản Magento trước, nó trông như thế này:

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

và làm việc chính xác. Bây giờ nó trông như thế này:

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

và kiểm tra bổ sung cho hasCustomOptions()nguyên nhân lỗi được mô tả. Tại sao? Có vẻ như kiểm tra đã được thêm vào để luôn giữ các sản phẩm có các tùy chọn tùy chỉnh riêng biệt. Tôi không nghĩ nó có ý nghĩa, ít nhất là không phải theo cách nó được thực hiện, nhưng sẽ có một số lý do cho nó mà tôi không nhận thức được.

Tuy nhiên, $item->getProduct()->hasCustomOptions()luôn luôn trả về đúng cho các mục báo giá!

Đây là phương pháp:

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

Nhưng $this->_customOptionscũng chứa các info_buyRequesttùy chọn từ các mục trích dẫn.

Đối với một giải pháp không quan trọng, tôi đã cố gắng loại bỏ info_buyRequesttùy chọn khỏi tất cả các sản phẩm trong một người quan sát trên sales_quote_merge_beforenhưng không thành công.

Lý do nằm ở Mage_Sales_Model_Quote_Item_Abstract::getProduct()chỗ tùy chọn được sao chép lại từ chính mục trích dẫn:

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

    [...]

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

Giải pháp

Tôi đã tạo một bản ghi lại Mage_Sales_Model_Quote_Itemvới ghi đè getProduct()để không bao gồm info_buyRequesttùy chọn tại thời điểm này:

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

Điều này gây ra sự cố với các sản phẩm đi kèm, thay thế bên dưới hoặc bản vá chính thức như được mô tả bởi @ AnnaVölkl là một giải pháp tốt hơn

Thay thế

Bạn cũng có thể loại bỏ vi phạm && !$item->getProduct()->hasCustomOptions()trong compare()phương thức nếu bạn đang viết lại mô hình vật phẩm bằng mọi cách. Tôi không biết vấn đề gì nó đã cố gắng giải quyết, nhưng nó đã tạo ra nhiều hơn ...

Cập nhật ngày 29 tháng 1 năm 2016

Tôi đã báo cáo điều này với Magento và nhận được phản hồi rằng họ không thể tái tạo vấn đề, vì vậy bản vá sẽ không được đưa vào phiên bản cộng đồng (Submission APPSEC-1321).

Điều này có nghĩa, nếu bạn gặp sự cố, bạn cần áp dụng bản vá doanh nghiệp SUPEE-6190 sau mỗi lần cập nhật hoặc sử dụng viết lại lớp thay thế.


However, $item->getProduct()->hasCustomOptions() always returns true for quote items!Nó đang kiểm tra dữ liệu sản phẩm cho các tùy chọn tùy chỉnh chứ không phải mục trích dẫn :)
kanevbgbe

1
@kanevbgbe đáng ngạc nhiên, không. Magento "chuẩn bị" phiên bản sản phẩm được liên kết với một mục trích dẫn và thêm các giá trị tùy chọn tùy chỉnh của nó
Fabian Schmengler

Tôi biết rằng khi thêm vào hành động giỏ hàng, phiên bản sản phẩm được tải đầy đủ (so với tải báo giá), do đó, nó được đặt trực tiếp từ bên ngoài thuật toán của trích dẫn đến máng của mục trích dẫn set sản phẩm (), có thể sau đó kiểm tra này có đầu ra khác .
kanevbgbe

1

Như tôi có thể thấy câu trả lời ở trên đã có sẵn trong phiên bản mới nhất của Magento nhưng chúng tôi vẫn đang gặp vấn đề. Nó không hoạt động vì chúng tôi đã thực hiện rất nhiều tùy chỉnh. Suy nghĩ chia sẻ giải pháp.

Đối với chúng tôi nó rất đơn giản vì chúng tôi chỉ sử dụng các sản phẩm đơn giản. Vì vậy, chúng tôi đã mở rộng chức năng so sánh trích dẫn này:

NS_Module_Model_Sales_Quote_Item mở rộng Mage_Sales_Model_Quote_Item {

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

}

và thêm

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

nhưng. đối với những người đang sử dụng các sản phẩm có thể định cấu hình thì nó có thể không hữu ích cho bạn. Trong trường hợp đó, bạn có thể in cả hai mảng: $ itemOptionValue và $ optionValue và xem sự khác biệt. bỏ đặt tất cả các khóa bổ sung không phổ biến trong cả hai mảng. Điều đó sẽ giải quyết vấn đề.


-1

Bạn chỉ có thể thêm một tùy chọn cho sản phẩm trong sự kiện sales_quote_add_item:

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

Liên kết tham khảo: Vô hiệu hóa sáp nhập các vị trí giỏ hàng?


Đó là một cách giải quyết, nhưng việc vô hiệu hóa hoàn toàn việc hợp nhất vật phẩm thường không được mong muốn.
Fabian Schmengler
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.