关于$cart_id与$increment_id的一些问题与思考

bug问题 · Axin · 于 5年前 发布 · 2394 次阅读

前言:

之前出了appserver端,出现几万redis key的情况,根据作者的1.7.0.0版本已经修复。

问题

经过我测试,发现会出现刷购物车会刷到别人购物的情况。同样,在支付里面也出现了取到别人的订单的情况。

详细

看代码,发现在$cart_id 与 $increment_id都是存储在appserver端session里面的。(代码如下)

  • $increment_id 示例:
	/**
     * 将生成的订单号写入session
     * @param string $increment_id order订单号
     */
    protected function actionSetSessionIncrementId($increment_id)
    {
        Yii::$service->session->set(self::CURRENT_ORDER_INCREMENT_ID, $increment_id);
    }

    /**
     * 从session中取出来订单号.
     */
    protected function actionGetSessionIncrementId()
    {
        return Yii::$service->session->get(self::CURRENT_ORDER_INCREMENT_ID);
    }

同样的在Cart Service 里面也可以找到Cart_id的存储。 不太理解作者为什么要放session里面的思路。

解决

相应的代码我改了三个方法 如下: Cart 子服务 Quote 里面 (我这里是用的作者cart redis 扩展 )

	/**
     * @return int 得到cart_id
     * Cart的session的超时时间由session组件决定。
     * 在执行$this->CreateCart $this->mergeCartAfterUserLogin,都会执行 $this->setCartId,执行 Yii::$service->session->set(self::SESSION_CART_ID,'xxxx'); 给其赋值。
     * 当新用户没有任何购物车操作,则返回为空值。
     */
    public function getCartId()
    {
        if (!$this->_cart_id) {
            $customerId     = Yii::$app->user->getId();
            $cartInfo       = $this->getCartByCustomerId($customerId);
            $this->_cart_id = $cartInfo['cart_id'];
        }
        return $this->_cart_id;
    }
	
	/**
     * 初始化创建cart信息,
     * 在用户的第一个产品加入购物车时,会在库中创建购物车.
     */
    protected function actionCreateCart()
    {
        $customerCart             = new $this->_cartModelName;
        $customerCart->store      = Yii::$service->store->currentStore;
        $customerCart->created_at = time();
        $customerCart->updated_at = time();
        if (!Yii::$app->user->isGuest) {
            $identity                        = Yii::$app->user->identity;
            $id                              = $identity['id'];
            $customerCart->customer_id       = $id;
            $customerCart->customer_is_guest = 2;
        } else {
            $customerCart->customer_is_guest = 1;
        }
        $customerCart->remote_ip = \common\helpers\CFunc::get_real_ip();
        $customerCart->app_name  = Yii::$service->helper->getAppName();

        $customerCart->save();
        $cart_id = $customerCart['cart_id'];
        $this->setCartId($cart_id);
        $this->setCart($this->_cartModel->findOne($cart_id));
        return $customerCart;
    }
	
	/**
     * 通过用户的customer_id,在cart表中找到对应的购物车
     * 找不到用户购物车时,创建用户购物车
     * @property $customer_id | int
     * @return $this->_cartModel Object。
     */
    public function getCartByCustomerId($customer_id)
    {
        if ($customer_id) {
            $one = $this->_cartModel->findOne(['customer_id' => $customer_id]);
            if ($one['cart_id']) {
                return $one;
            } else {
                return $this->createCart();
            }
        }
    }

想知道下你们会不会出现,探讨下。

本文由 Axin 创作,采用 知识共享署名 3.0 中国大陆许可协议 进行许可。 可自由转载、引用,但需署名作者且注明文章出处。

共收到 4 条回复 fecshop 问题提问
Fecmall#15年前 0 个赞

Yii::$service->session->get() 执行的是 https://github.com/fecshop/yii2_fecshop/blob/master/services/session/SessionRedis.php

最终的存储并不是放到php session里面

public function set($key, $val, $timeout)
    {
        $key = $this->getSessionKey($key);
        $val = $val . $this->valSeparator . time();
        return (bool) Yii::$app->redis->executeCommand('SET', [$key, $val, 'EX', $timeout]);
    }
    public function get($originKey, $reflush)
    {
        $key = $this->getSessionKey($originKey);
        $data = Yii::$app->redis->executeCommand('GET', [$key]);
        $arr = explode($this->valSeparator, $data);
        if (count($arr) < 2) {
            return '';
        }
        $val = $arr[0];
        $timeout = $arr[1];
        if (Yii::$service->session->isUpdateTimeOut($timeout) && $val) {
            $this->set($originKey, $val, $timeout);
        }
        return $val === false || $val === null ? '' : $val;
    }
    public function remove($key)
    {
        $key = $this->getSessionKey($key);
        Yii::$app->redis->executeCommand('DEL', [$key]);
        // @see https://github.com/yiisoft/yii2-redis/issues/82
        return true;
    }

执行的是 Yii::$app->redis->executeCommand

Fecmall#25年前 0 个赞

你能找一下具体,是什么原因导致你出现的这个问题吗?

Axin#35年前 0 个赞

恩,我知道最终存储不会放在php session, 是在redis里面的。 我这边具体原因,应该是前端APP,对$fecshop_uuid没处理好,退出没有清掉。

这边只是想知道下,为什么要把cart_id和订单编号id放session中。

Fecmall#45年前 0 个赞

以为支持游客购物车和游客下单,因此cart_id和 订单放到了session services里面。

你出现这个问题的原因,找到了吗?

添加回复 (需要登录)
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册
Your Site Analytics