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.