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

즉, 제품이 병합되지 않습니다.

브라우저를 전환하는 대신 세션 쿠키를 지우거나 제품에 대해 다른 수량을 선택할 수도 있습니다.

이것의 최악의 부작용은 품목 당 최대 주문 수량이 적용된다는 것입니다. 제 경우에는 제품에 대해 100 % 할인이 있었지만 한 번만 주문할 수있었습니다. 이 작은 트릭을 사용하면 수량에 관계없이 무료로 주문할 수 있습니다.

왜 이런 일이 발생하며 어떻게 방지 할 수 있습니까?

답변:


18

위의 버그를 멋지게 마무리했습니다, Fabian!

이 버그에 직면하게 될 추가 사용자를 위해 이미 Magento의 패치가 있습니다.

엔터프라이즈 고객은 PATCH_SUPEE-6190_EE_1.14.2.0_v1.sh이 문제를 해결하기 위해 요청 / 다운로드 할 수 있습니다 .

2016.02.2016 업데이트 : 최신 SUPEE-7405 v 1.1 패치 에서도이 문제가 해결되었습니다. 트위터의 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
슬라이드 시키겠습니다.
— benmarks

1
그런 다음 밀어 넣습니다.
— Marius

이것은 내 수정보다 낫습니다. 번들 제품에 문제가 발생했습니다. 공유해 주셔서 감사합니다!
— Fabian Schmengler

1
"related_products"매개 변수가 후자의 경우에만 존재하기 때문에 제품 목록을 통해 제품을 한 번 추가하고 제품 세부 사항 페이지를 통해 한 번 추가하면 여전히 우회 할 수 있습니다. "related_products"를 unset()호출에 추가 할 수도 있지만, 임의의 POST 매개 변수가 buyRequest 옵션에도 추가되므로 안전하지 않습니다. 대신이 옵션을 완전히 무시하겠습니다.
— Fabian Schmengler

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는 견적 항목과 관련된 제품 인스턴스를 "준비"하고 사용자 지정 옵션 값을 추가합니다.
— 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'));

참조 링크 : 카트 위치 병합을 비활성화 하시겠습니까?


이는 해결 방법이지만 일반적으로 항목 병합을 완전히 비활성화하는 것은 바람직하지 않습니다.
— Fabian Schmengler
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.