value('token'); } public static function getWalletFrozen($userID) { return self::where('user_id', $userID)->value('frozen'); } public static function getWalletTotalChaBao($userID) { return self::where('user_id', $userID)->value('token + frozen'); } public static function getWallet($userID) { return self::where('user_id', $userID)->find(); } /** * 仅事务内使用,会附带"for update" * @param $userID * @throws Exception */ public function getWalletTX($userID) { return $this->lock(true)->where('user_id', $userID)->find(); } /** * 更新钱包余额并添加账变记录 * @param int $uid 用户ID * @param string $asset 资产类型 * @param string $amount 金额 正:表示加 负:表示减 * @param int $action 账变类型 * @return void * @throws Exception */ public function changeWalletAccount(int $uid, string $asset, string $amount, int $action, int $from_id = 0) { $available = $this->getWallet($uid); if (empty($available)) (new LedgerWalletModel())->insertGetId(['user_id' => $uid]); // 创建钱包 $frozen = ''; //冻结金额 // 账变资产模型 switch ($asset) { case Asset::USDT: $changeModel = new LedgerUsdtChangeModel(); break; case Asset::TOKEN: $changeModel = new LedgerTokenChangeModel(); break; case Asset::TEAC: $changeModel = new LedgerTeacChangeModel(); break; case Asset::SMH: $changeModel = new LedgerSmhChangeModel(); break; case Asset::FROZEN: //扣掉赠送手续费 $changeModel = new LedgerFrozenChangeModel(); break; default: throw new Exception('币种错误:' . $asset); } // 更新钱包余额 $newAmount = $this->changeWalletOnly($uid, $asset, $amount); // 创建账变记录 $insertRs = $changeModel->insert([ 'user_id' => $uid, 'from_id' => $from_id, 'change_amount' => $amount, 'present_amount' => $newAmount, 'create_time' => time(), 'action' => $action ]); if (empty($insertRs)) { throw new Exception('创建' . $asset . '账变记录失败'); } } /** * 仅更新钱包余额,没有账变 * @param int $uid 用户ID * @param string $asset 资产类型 * @param string $amount 金额 正:表示加 负:表示减 * @return string 变动后的金额 * @throws Exception */ public function changeWalletOnly(int $uid, string $asset, string $amount ): string { $available = $this->getWalletTX($uid); if (empty($available)) { throw new Exception('用户资产信息不存在'); } // 金额为0的判断 $amount = bcadd($amount, 0, 6); if (bccomp($amount, '0', 6) == 0) { throw new Exception('金额变动为0'); } // 余额不足的判断 if ($amount < 0 && $available[$asset] < -$amount) { throw new Exception($asset . '余额不足'); } $newAmount = bcadd($available[$asset], $amount, 6); // 新余额 $walletUpdate = [$asset => $newAmount, 'update_time' => time()]; // 更新余额 $changeRs = $this->save($walletUpdate, ['user_id' => $uid]); if (empty($changeRs)) { throw new Exception('更新' . $asset . '余额失败'); } return $newAmount; } /** * 冻结茶宝 * @param int $uid 用户ID * @param string $amount 报单金额 * @return void * @throws Exception */ public function setChangeFrozen(int $uid, string $amount, int $action, string $icn, int $from_id = 0) { $available = $this->getWallet($uid); $ledgerWalletModel = new LedgerWalletModel(); if (empty($available)) $ledgerWalletModel->insertGetId(['user_id' => $uid]); // 创建钱包 $walletUpdate = []; $result = false; //运费/手续费:扣除 if($icn == '-'){ $totalAmount = bcadd($available['token'], $available['frozen'], 6); //扣除冻结金额 if($available['frozen'] > $amount) $walletUpdate['frozen'] = bcsub($available['frozen'], $amount, 6); if($available['frozen'] <= $amount) { $walletUpdate = ['token'=> bcadd($totalAmount, -$amount, 6), 'frozen' => 0]; //添加账变记录 $subAmount = bcsub($amount, $available['frozen'], 6); $this->changeWalletAccount($uid, Asset::TOKEN, -$subAmount, LedgerTokenChangeModel::Giveaway, $from_id); } //添加冻结 $newAmount = $walletUpdate['frozen']; if($available['frozen'] > 0) $result = true; } //手续费 if($icn == '+' && $available['frozen'] < $amount){ //添加账变记录 if($available->token < $amount) throw new Exception('茶宝不足'); $sunAmount = bcsub($available->frozen, $amount, 6); //扣除的冻结金额 $chabao = bcadd($available['token'], $sunAmount, 6); $newAmount = $amount; //剩余的冻结金额 //添加冻结 $walletUpdate =['token' => $chabao, 'frozen' =>$newAmount]; $this->changeWalletAccount($uid, Asset::TOKEN, $sunAmount, LedgerTokenChangeModel::Super, $from_id); $result = true; } // 创建账变记录 if (count($walletUpdate) > 0) $ledgerWalletModel->where('user_id', $uid)->update($walletUpdate); if($result){ return (new LedgerFrozenChangeModel())->insert([ 'user_id' => $uid, 'from_id' => $from_id, 'change_amount' => $icn.$amount, 'present_amount' => $newAmount, 'create_time' => time(), 'action' => $action ]); } } /** * 发放直推USDT收益 * @param int $uid * @param string $power * @return void * @throws DbException */ public function sendUsdtProfit(int $uid, string $amount) { $ratio = (new Config())->getValue('direct_income');//直推奖励 $user = (new UserModel())->get($uid); if (empty($user) || $user['parent_id'] == 0) { return; } $parent = (new UserModel())->get($user['parent_id']); if (empty($parent)) { return; } $temp = ['拦截提醒', $uid, $amount, $amount * $ratio]; //dump($temp); // 上级算力的账变 $this->changeWalletAccount($user['parent_id'], Asset::USDT, $amount * $ratio, Action::UsdtShareBonus, $uid); } /** * 发放直推收益 * @param int $uid * @param string $power * @return void * @throws DbException */ public function sendDirectProfit(int $uid, string $power) { $user = (new UserModel())->get($uid); if (empty($user) || $user['parent_id'] == 0) { return; } $parent = (new UserModel())->get($user['parent_id']); if (empty($parent)) { return; } // 查询直推奖励比例 $directProfit = (new Config())->getValue('direct_income'); $directProfitFloat = floatval($directProfit); if (is_null($directProfit) || $directProfitFloat <= 0) { return; } $directPower = $power * $directProfitFloat; // 可获得的直推奖励(算力) if($directPower > 0){ $this->changeWalletAccount($user['parent_id'], Asset::POWER, $directPower, Action::PowerDirectAward, $uid); } // 上级算力的账变 } /** * 发放见点奖 * @param int $uid 服务器算力的用户ID * @param string $power 该租赁得到的算力 * @return void * @throws Exception */ public function sendRegBonus(int $uid) { $parentIDs = (new UserPathModel())->getAllParentIDs($uid); if (count($parentIDs) == 0) { return; } $userList = (new UserModel()) ->field('id,team_level_id') ->where('id', 'in', $parentIDs) ->where('team_level_id', '>', 0) ->order('id desc') ->select(); if (empty($userList)) { //没有符合条件的上级 return; } $team_level_config = DB::table('team_level') ->field('level_id, reg_bonus') ->select(); $level_reg_bonus = []; foreach ($team_level_config as $item) { $level_reg_bonus[$item['level_id']] = $item['reg_bonus']; } $now_level = 0; foreach ($userList as $item) { if ($item['team_level_id'] > $now_level && isset($level_reg_bonus[$item['team_level_id']])) { (new LedgerWalletModel())->changeWalletAccount($item['id'], Asset::USDT, $level_reg_bonus[$item['team_level_id']], Action::UsdtRegBonus, $uid); $now_level = $item['team_level_id']; } } } /** * 发放服务器市场推荐相关收益 * @param int $uid * @param string $power * @return void * @throws DbException */ public function sendMarketBonus(int $uid, array $server_info) { //直推奖 $user = (new UserModel())->get($uid); if (empty($user) || $user['parent_id'] == 0) { return; } $parent = (new UserModel())->get($user['parent_id']); if (empty($parent) || $parent['effective_time'] == 0) {//必须参加过算力租赁才能领取该收益 return; } $this->changeWalletAccount($user['parent_id'], Asset::USDT, $server_info['referral_bonus'], Action::ServerReferralBonus, $uid); //间推荐奖,向上级的上级发放佣金 if ($parent['parent_id'] == 0) { return; } $indirect = (new UserModel())->get($parent['parent_id']); if (empty($indirect) || $indirect['effective_time'] == 0) {//必须参加过算力租赁才能领取该收益 return; } $this->changeWalletAccount($parent['parent_id'], Asset::USDT, $server_info['indirect_bonus'], Action::ServerIndirectBonus, $uid); //社长费用 $user_parent_ids = (new UserPathModel())->where('user_id', $uid)->column('parent_id'); $parent_users = (new UserModel()) ->field('id,parent_id') ->where('id', 'in', $user_parent_ids) ->where('effective_time', '>', 0)//必须参加过算力租赁才能领取该收益 ->order('id desc') ->select(); if (empty($parent_users)) { return; } //发放社区长费用 $info = $parent_users[0];//取第一个 $this->changeWalletAccount($info['id'], Asset::USDT, $server_info['community_bonus'], Action::ServerCommunityBonus, $uid); //发放社区长推荐奖 if ($info['parent_id'] > 0) { $community_info = (new UserModel())->get($info['parent_id']); if ($community_info['effective_time'] > 0) { $this->changeWalletAccount($info['id'], Asset::USDT, $server_info['community_referral_bonus'], Action::ServerCommunityReferralBonus, $uid); } } //系统领导人费用 $sys_leader_info_id = 0;//定义待发放收益的系统领导人ID if ($sys_leader_info_id > 0) { $this->changeWalletAccount($sys_leader_info_id, Asset::USDT, $server_info['sys_leader_bonus'], Action::ServerSysLeaderBonus, $uid); } } public function users() { return $this->hasOne(UserModel::class, 'id', 'user_id'); } public function getCreateTimeTextAttr($value, $data) { $value = $value ? $value : (isset($data['create_time']) ? $data['create_time'] : ''); return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value; } public function getUpdateTimeTextAttr($value, $data) { $value = $value ? $value : (isset($data['update_time']) ? $data['update_time'] : ''); return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value; } protected function setCreateTimeAttr($value) { return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value); } protected function setUpdateTimeAttr($value) { return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value); } }