首页 » Ecstore » Ecstore订单促销策略错误读取其他商品促销的BUG

Ecstore订单促销策略错误读取其他商品促销的BUG

6027 0

最近发现一个Ecstore大bug关于订单促销这一块的,能直接影响到最后的结算金额,使结算价格远远低于应付金额。在和官方技术人员沟通中,发现最新版的ecstore仍然没有修复此bug,因此有必要将此bug公布一下。

活动名称:第2件商品半价,多款商品可同时享受。
场景重现:
1. 建立1条订单策略,优先权50,不排他。指定包含购买商品A数量x2的时候,订单-100元。
2. 建立另1条订单策略,优先权50,不排他。指定包含购买商品B数量x2的时候,订单-60元。
3. 建立商品A,单价为200元,商品B单价为120,确保商品单价要大于减免价格。

结果发现买商品A两件时,结算价格变成了200×2-100-60了,执行了商品A的100元的优惠基础上同时又执行了商品B的的促销优惠。同一时间上,生效的第2件半价的订单促销策略不止这两条,查看其他产品结算价格都正常。起初怀疑是后台设置问题,但是在仔细比对其他产品的第2件商品半价促销设置后,并没有发现有什么设置上的问题,于是开始怀疑本身的代码有bug。

订单促销走的是/b2c/lib/cart/postfilter/promotion.php到/b2c/lib/sales/,代码封装得很深,最后定位到产生的问题的文件/b2c/lib/sales/basic/operator/contain.php这个文件的validate函数。

原代码为:

public function validate($operator,$value,$validate) {
        if( !$value  || !$validate ) return false;
        //商品包含某个字
        switch($operator) {
            case '()':
                if(is_array($value)) return in_array($validate,$value);
                $flag = strpos($validate,$value);
                if( $flag===false ) 
			return false;
                else 
			return true;
                break;
            case '!()':
                if(is_array($value)) return !in_array($validate,$value);
                $flag = strpos($validate,$value);
                if( $flag===false ) return false;
                else return true;
                break;
        }
        return false;
    }

这里函数参数operator是包含的符号'()’,value是策略里的goods_id(多个的情况下是数组),validate是购物车里的goods_id(只可能是单个)。可以看到如果策略里包含多个商品,则会用in_array判断购物车商品是否在策略生效的商品清单中,这个没问题。问题点在于下面这条strpos,如果购物车内的goods_id是123,策略里生效的goods_id是1234的话,那么strpos(‘123′,’1234’)是成立的。另外查了一下后台所有策略的可选项,发现在设置商品名称匹配的时候也用到了包含,所以,这里针对性的略做修改,如下:

 case '()':
    if(is_array($value)) return in_array($validate,$value);
				
	//by tiandi 2016.5.9 尝试修复goods_id=123的商品会载入goods_id=1234订单促销的错误,不清楚这里原先为什么要用strpos,可能并不局限用于促销策略模块,
	//所以可能会造成其他问题。如果value字符串里都是数字(goods_id),则不使用strpos,而直接判断是否和validate相同
	//start 
	if(is_numeric($value)&&($validate != $value)) 
		return false;
	//end
				
        $flag = strpos($validate,$value);
        if( $flag===false ) 
		return false;
        else 
		return true;
        break;

这样在比对goods_id的时候就不会再出现读取错误的情况了。Ecstore的框架写得还真是有够复杂,查明上述问题,几乎涉及到10个左右的文件。

PS:已经将该问题提交给官方技术了。

文章评分2次,平均分5.0

本文原始地址:https://www.tiandiyoyo.com/2016/05/read-a-wrong-order-rule-on-ecstore/
本站所有文章,除了特别注明外,均为本站原创,转载请注明出处来自www.tiandiyoyo.com

您可能还会对以下文章感兴趣:

评论前先开启评论开关: