255], ]; } /** * {@inheritdoc} */ public function attributeLabels() { return [ 'id' => 'ID', 'mall_id' => 'Mall ID', 'user_id' => 'User ID', 'bargain_order_id' => '砍价订单ID', 'price' => '砍价的金额', 'token' => 'Token', 'status' => '状态[-1:删除;0:禁用;1启用]', 'created_at' => 'Created At', 'updated_at' => 'Updated At', ]; } // 关联模型 public function getUser() { return $this->hasOne(User::class, ['id' => 'user_id']); } public function getOrder() { return $this->hasOne(BargainOrder::class, ['id' => 'bargain_order_id']); } public static function userJoinBargain($params) { $stock_locks = []; $t = Yii::$app->db->beginTransaction(); try { $lock_key = RedisKeyEnum::LOCK_BARGAIN_ORDER . $params['bargain_order_id']; $identification = uniqid(); if (!LockHelper::lock($lock_key, $identification, 30, 60)) throw new \Exception('当前访问人数过多'); $stock_locks[$lock_key] = $identification; $user_join_order_list = self::findAll(['mall_id' => $params['mall_id'], 'bargain_order_id' => $params['bargain_order_id'], 'status' => StatusEnum::ENABLED]); foreach ($user_join_order_list as $val) { if ($val['user_id'] == $params['user_id']) throw new \Exception('您已参与过本次砍价'); } $bargain_order = BargainOrder::findOne(['mall_id' => $params['mall_id'], 'id' => $params['bargain_order_id']]); if (empty($bargain_order)) throw new \Exception('砍价活动已关闭'); if ($bargain_order->order_status == BargainEnum::ORDER_SUCCESS) throw new \Exception('砍价已完成'); if ($bargain_order->order_status == BargainEnum::ORDER_FAILURE) throw new \Exception('砍价失败'); $active = BargainActive::findOne(['mall_id' => $params['mall_id'], 'id' => $bargain_order->bargain_active_id]); if (($bargain_order->created_at + $active['time'] * 3600) <= time()) throw new \Exception('砍价已结束'); $bargain_goods_data = json_decode($bargain_order->bargain_goods_data,true); if ($active->stock <= 0 && $bargain_goods_data['type'] == 1) throw new \Exception('商品已售罄,暂时无法砍价哦~'); if ($bargain_order->user_id != $params['user_id'] || ($bargain_order->user_id == $params['user_id'] && $active->is_creator_exempt == 0)) { //判断用户等级能否参与砍价 self::checkUserBargain($params, $active); //判断用户能否参与砍价 self::checkUserBargainTime($params, $active, $bargain_order); } // 已砍价金额 $total_price = array_sum(array_column($user_join_order_list, 'price')); // 参与砍价人数 $total_people = count($user_join_order_list); // 剩余可砍价金额 $reset_price = floatval($bargain_order->price) - floatval($bargain_order->min_price) - $total_price; $reset_price = $reset_price <= 0 ? 0 : $reset_price; if ($reset_price <= 0){ //todo //推送一条信息给发布砍价的用户 throw new \Exception('已砍至最低价'); } $price = self::intToFloat(self::getPrice($reset_price, $total_people, $bargain_order->bargain_goods_data)); $model = new self(); $model->user_id = $params['user_id']; $model->mall_id = $params['mall_id']; $model->price = $price; $model->token = \Yii::$app->security->generateRandomString(); $model->bargain_order_id = $params['bargain_order_id']; $res = $model->save(); if ($res == false) throw new \Exception(self::getStaticError()); $active->participant += 1; if ($price == $reset_price) $active->min_price_goods += 1; $res = $active->save(); if ($res == false) throw new \Exception(BargainActive::getStaticError()); $bargain_order->reduce_price+=$price; if($bargain_order->reduce_price==$bargain_order->min_price) $bargain_order->order_status = BargainEnum::ORDER_SUCCESS; $res = $bargain_order->save(); if ($res == false) throw new \Exception($bargain_order->getErrorMessage()); $t->commit(); LockHelper::batchUlock($stock_locks); $info = [ 'nickname' => $model->user->nickname ?? '', 'price' => $model->price, 'user_id' => $model->user_id, ]; $start = substr($bargain_order->user->mobile,0,3); $end = substr($bargain_order->user->mobile,-4,4); $mobile = $start.'****'.$end; $bargain = [ 'nickname' => $bargain_order->user->nickname ?? '', 'mobile' => $mobile, 'avatar_url' => $bargain_order->user->avatar_url ?? '', 'user_id' => $bargain_order->user_id, ]; return ['info' => $info, 'bargain' => $bargain]; } catch (\Exception $e) { LockHelper::batchUlock($stock_locks); $t->rollback(); self::$static_error = $e->getMessage(); return false; } } /** * @desc:砍价算法 * @Author: hua * @Date: 2022/1/3 * @Time: 15:46 * @Copyright: copyright (c) 2021 广东七件事集团 * @param $reset_price * @param $people * @param $bargain_goods_data * @return float|int */ private static function getPrice($reset_price, $people, $bargain_goods_data) { $data = json_decode($bargain_goods_data); if (isset($data->bargain_people)) { $dataPeople = intval($data->bargain_people); if ($dataPeople != 0) { if ($people == $dataPeople - 1) { return $reset_price * 100; } if ($people >= $dataPeople) return 0; } } if ($people < intval($data->bargain_human)) { $min = $data->bargain_first_min_price > $data->bargain_first_max_price ? $data->bargain_first_max_price : $data->bargain_first_min_price; $max = $data->bargain_first_min_price > $data->bargain_first_max_price ? $data->bargain_first_min_price : $data->bargain_first_max_price; } else { $min = min($data->bargain_second_min_price, $data->bargain_second_max_price); $max = max($data->bargain_second_min_price, $data->bargain_second_max_price); } $money = mt_rand($min * 100, $max * 100); if ($money > $reset_price * 100) $money = (round($reset_price, 2)) * 100; return intval($money); } // int转float private static function intToFloat($int) { // 去除原来计算保留两个小数点 return bcdiv($int, 100, 2); } /** * 指定位置插入字符串 * @param $str string 原字符串 * @param $i integer 插入位置 * @param $substr string 插入字符串 * @return string 处理后的字符串 */ private static function insertToStr($str, $i, $substr) { //指定插入位置前的字符串 $startStr = substr($str, 0, $i); //指定插入位置后的字符串 $lastStr = substr($str, -2); //将插入位置前,要插入的,插入位置后三个字符串拼接起来 $str = $startStr . $substr . $lastStr; //返回结果 return $str; } public function sendMessage($mall_id,$open_id,$total_price,$min_price,$temp_id){ $notice_wechat = \Yii::$app->services->setting->mall->get(5, 'notice_wechat'); if(!empty($notice_wechat['is_miniapp_priority'])){ $mini_program = \Yii::$app->services->setting->mall->get($mall_id, 'mini_program'); if (!empty($mini_program)) { \Yii::$app->params['wechatMiniProgramConfig'] = [ 'app_id' => $mini_program['app_id'], 'secret' => $mini_program['secret'], 'key' => $mini_program['pay_secret'] ?? '', 'cert_path' => $mini_program['cert_pem_path'] ?? '', 'key_path' => $mini_program['key_pem_path'] ?? '', 'notify_url' => ''//回调地址 ]; } $app = \Yii::$app->wechat->miniProgram; }else{ $wechat = \Yii::$app->services->setting->mall->get($mall_id, 'wechat'); if ($wechat) { \Yii::$app->params['wechatConfig'] = [ 'app_id' => $wechat['app_id'] ?? '', 'secret' => $wechat['secret'] ?? '', 'token' => $wechat['token'] ?? '', 'aes_key' => $wechat['aes_key'] ?? '', ]; } $app = \Yii::$app->wechat->app; } $send_data = [ 'first' => '你发布的商品已经砍价成功', 'keyword1' => '砍掉'.$total_price."元", 'keyword2' => date("Y-m-d H:i:s"), 'keyword3' => $min_price, 'remark' => '已砍至最低价,快来买我吧!!' ]; $pageUrl = '/plugins2/bargain/joinBargain?id=' . '1'; $h5_url = 'https://h5.qijianshirjcs.com' . "/h5/#" . $pageUrl; $app->template_message->send([ 'touser' => $open_id, 'template_id' => $temp_id, 'url' => $h5_url, 'data' => $send_data, ]); } public static function checkUserBargain($params, $active) { $bargain_limit_user_level = empty($active->bargain_limit_user_level) ? [] : $active->bargain_limit_user_level; if (empty($bargain_limit_user_level)) { return true; } $user = User::find() ->where(['id' => $params['user_id'], 'status' => StatusEnum::ENABLED]) ->select('id,level') ->asArray() ->one(); if (empty($user)) { throw new \Exception('用户信息不存在'); } $mall_level_info = UserLevel::find() ->where([ 'mall_id' => $params['mall_id'], 'status' => StatusEnum::ENABLED ]) ->andWhere(['in', 'id', $bargain_limit_user_level]) ->select('id,level') ->asArray() ->all(); $join_level = $mall_level_info ? array_column($mall_level_info, 'level') : []; if (in_array(0, $bargain_limit_user_level)) { $join_level[] = 0; } if (!in_array($user['level'], $join_level)) { throw new \Exception('很抱歉!您暂时无法帮砍~'); } } public static function checkUserBargainTime($params, $active, $bargain_order) { //统计用户参与该活动的次数 $model = (new \yii\db\Query()) ->from('qimall_addons_bargain_order o') ->innerJoin('qimall_addons_bargain_user_order u', 'o.id = u.bargain_order_id') ->where([ 'o.bargain_active_id' => $active->id, 'u.user_id' => $params['user_id'], 'o.status' => StatusEnum::ENABLED, 'u.status' => StatusEnum::ENABLED ]); if ($active['is_creator_exempt']) { $model->andWhere(['<>', 'o.user_id', $params['user_id']]); } $records = $model->select('o.user_id,u.bargain_order_id,u.user_id as bargain_user_id') ->all(); $count = count($records); if (!empty($active->bargain_time)) { if ($count >= $active->bargain_time) { throw new \Exception('您的帮砍次数不足,去看看其它活动吧~'); } } if ($count > 0 && empty($active->is_repeat_bargain)) { //不允许帮同个用户但不同砍价订单重复帮砍 foreach ($records as $record) { if ($record['user_id'] == $bargain_order->user->id) { throw new \Exception('您已经帮ta砍过一次啦,不可以重复帮砍哦~'); } } } } }