public function actionExchange() { $params = $this->getParams(); if (empty($params['memberId']) || empty($params['goodsId']) || empty($params['channelId']) || empty($params['receiveMode']) || empty($params['phone']) || empty($params['captcha']) || !isset($params['count']) || empty($params['address'])) { throw new BadRequestHttpException(Yii::t('common', 'parameters_missing')); } if ($params['count'] < 0) { throw new BadRequestHttpException(Yii::t('common', 'data_error')); } $this->attachBehavior('CaptchaBehavior', new CaptchaBehavior()); $this->checkCaptcha($params['phone'], $params['captcha']); $member = Member::findByPk(new \MongoId($params['memberId'])); if (empty($member) || $member->isDisabled) { throw new BadRequestHttpException(Yii::t('member', 'invalid_member_id')); } $goods = Goods::findByPk(new \MongoId($params['goodsId'])); if (empty($goods)) { throw new BadRequestHttpException(Yii::t('product', 'invalid_goods_id')); } if ((string) $goods->accountId !== (string) $member->accountId) { throw new BadRequestHttpException(Yii::t('product', 'different_account')); } if ($goods->status === Goods::STATUS_OFF) { throw new InvalidParameterException(Yii::t('product', 'goods_not_on_shelves')); } if (!is_array($goods->receiveModes) || !in_array($params['receiveMode'], $goods->receiveModes)) { throw new InvalidParameterException(Yii::t('product', 'receive_mode_invalid')); } $usedScore = $goods->score * $params['count']; $params['usedScore'] = $usedScore; $params['expectedScore'] = $usedScore; if ($member->score < $usedScore) { throw new InvalidParameterException(Yii::t('product', 'member_score_not_enough')); } //if $goods->total is '', means no limit if ($goods->total === 0) { throw new InvalidParameterException(Yii::t('product', 'goods_sold_out')); } if (!empty($goods->total) && $params['count'] > $goods->total) { throw new InvalidParameterException(Yii::t('product', 'goods_not_enough')); } $goodsCondition = ['_id' => $goods->_id]; $goodsModifier = ['$inc' => ['usedCount' => $params['count']]]; $goodsRollbackModifier = ['$inc' => ['usedCount' => 0 - $params['count']]]; if ($goods->total !== '') { $goodsCondition['total'] = ['$gte' => $params['count']]; $goodsModifier['$inc']['total'] = 0 - $params['count']; $goodsRollbackModifier['$inc']['total'] = $params['count']; } $goodsUpdatedCount = Goods::updateAll($goodsModifier, $goodsCondition); if ($goodsUpdatedCount === 1) { $memberUpdatedCount = Member::updateAll(['$inc' => ['score' => 0 - $usedScore]], ['_id' => $member->_id, 'score' => ['$gte' => $usedScore]]); if ($memberUpdatedCount === 1) { $exchanges = [['goods' => $goods, 'count' => $params['count']]]; if ($this->_saveLog($member, $exchanges, $params)) { return ['message' => 'OK', 'data' => null]; } else { Goods::updateAll($goodsRollbackModifier, ['_id' => $goods->_id]); Member::updateAll(['$inc' => ['score' => $usedScore]], ['_id' => $member->_id]); LogUtil::error(['message info' => 'save exchange log error', 'params' => $params, 'goods' => $goods->toArray(), 'member' => $member->toArray()], 'product'); } } else { Goods::updateAll($goodsRollbackModifier, ['_id' => $goods->_id]); throw new InvalidParameterException(Yii::t('product', 'member_score_not_enough')); } } else { throw new InvalidParameterException(Yii::t('product', 'goods_sold_out')); } }