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'));
     }
 }