// +---------------------------------------------------------------------- declare (strict_types = 1); namespace addon\wxchat\controller\api; use addon\wxchat\model\WxchatLotteryPrize; use addon\wxchat\model\WxchatLotteryRecord; use think\facade\Db; use think\facade\Request; use ywxapp\controller\FrontendBase; use ywxapp\service\WalletService; /** * Lottery 类 * * @author ywxapp */ class Lottery extends FrontendBase { protected $noNeedLogin = []; protected $noNeedVerify = ['*']; // 每次抽奖消耗金币 protected $cost = 10; // 每日免费次数 protected $freeDaily = 1; protected function initialize() { if ($this->auth->isLogin) { $this->uid = $this->auth->model->uid; } } private $uid = 0; /** * 抽奖配置(奖品列表 + 我的金币 + 剩余免费次数) */ public function config() { $uid = $this->uid; $prizes = WxchatLotteryPrize::where('status', 1) ->order('sort', 'asc') ->field('id,name,type,value,probability') ->select(); $freeUsed = WxchatLotteryRecord::where('uid', $uid) ->where('is_free', 1) ->where('create_at', '>=', strtotime('today')) ->count(); $this->success([ 'coins' => WalletService::getCoins($uid), 'cost' => $this->cost, 'free_daily' => $this->freeDaily, 'free_left' => max(0, $this->freeDaily - $freeUsed), 'prizes' => $prizes, ]); } /** * 抽奖(金币或免费) */ public function draw() { $uid = $this->uid; // 是否使用免费次数 $freeUsed = WxchatLotteryRecord::where('uid', $uid) ->where('is_free', 1) ->where('create_at', '>=', strtotime('today')) ->count(); $useFree = Request::post('use_free', 0) && $freeUsed < $this->freeDaily; if (! $useFree) { try { WalletService::decCoins($uid, $this->cost, '抽奖消耗'); } catch (\Throwable $e) { $this->error($e->getMessage()); } } $prize = $this->pickPrize(); $record = new WxchatLotteryRecord(); $record->uid = $uid; $record->prize_id = $prize ? $prize->id : 0; $record->prize_name = $prize ? $prize->name : '谢谢参与'; $record->prize_type = $prize ? $prize->type : 3; $record->prize_value = $prize ? $prize->value : 0; $record->is_free = $useFree ? 1 : 0; $record->save(); // 金币奖品发放 if ($prize && $prize->type == 1 && $prize->value > 0) { WalletService::incCoins($uid, (int) $prize->value, "抽奖中奖:{$prize->name}"); } $this->success([ 'prize' => $record->prize_name, 'prize_type' => $record->prize_type, 'prize_value'=> $record->prize_value, 'coins_left' => WalletService::getCoins($uid), ], '抽奖完成'); } /** * 按概率加权抽取奖品(无命中返回 null) */ private function pickPrize() { $prizes = WxchatLotteryPrize::where('status', 1) ->where('stock', '<>', 0) ->order('sort', 'asc') ->select(); if ($prizes->isEmpty()) { return null; } $rand = mt_rand(1, 10000) / 10000; // 0-1 $acc = 0.0; foreach ($prizes as $p) { $acc += (float) $p->probability; if ($rand <= $acc) { // 扣库存 if ($p->stock > 0) { Db::name('wxchat_lottery_prizes')->where('id', $p->id)->dec('stock')->update(['update_at' => time()]); } return $p; } } return null; } }