'全部', self::Popular => '热销支付', self::Payment => '转让支付', self::Receive => '转让收款', self::Recharge => '充值', self::Withdraw => '提现', self::Share => '分享', self::Return => '退回', ]; public static function getWalletChaBao($userID) { return self::where('user_id', $userID)->value('token'); } public function getWallet($userID) { return $this->where('user_id', $userID)->find(); } /** * 仅事务内使用,会附带"for update" * @param $userID * @throws Exception */ public function getWalletTX($userID) { return $this->lock(true)->where('user_id', $userID)->find(); } public static function getStatusList() { return [self::Popular => __('热销支付'), self::Payment => __('转让支付'), self::Receive => __('转让收款'), self::Recharge => __('充值'), self::Withdraw => __('提现'), self::Share => __('分享'), self::Return => __('退回')]; } /** * 更新钱包余额并添加账变记录 * @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, ]); } // 账变资产模型 switch ($asset) { case Asset::POWER: $changeModel = new LedgerPowerChangeModel(); break; case Asset::USDT: $changeModel = new LedgerUsdtChangeModel(); break; case Asset::TOKEN: $changeModel = new LedgerTokenChangeModel(); break; case Asset::DECLARATION: $changeModel = new LedgerDeclarationChangeModel(); break; case Asset::SMH: $changeModel = new LedgerSmhChangeModel(); break; case Asset::QUBIC: $changeModel = new LedgerQubicChangeModel(); 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; } /** * 发放直推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 $usdt 报单金额 * @return void * @throws Exception */ public function sendGenerateProfit(int $uid, string $usdt) { //上上级ID $parentID = (new UserPathModel())->getParentID($uid, 2); if(empty($parentID)){ return; } // 查询代数收益比例 $directProfit = (new ParametersModel)->getValue('generateProfitRate'); $rateArr = explode(',', $directProfit); if (empty($rateArr) || count($rateArr) != 2) { throw new Exception('获取代数收益比例失败'); } $genRate2 = explode(':', $rateArr[0]); // 上上级人数和比例 $genRate3 = explode(':', $rateArr[1]); // 上上上级人数和比例 // 上上级的发放 $amount = bcmul($genRate2[1], $usdt, 6); if ($amount > 0) { $parent1 = (new UserModel())->getById($parentID); if (!empty($parent1) && $parent1['direct_num'] >= $genRate2[0]) { // 有效直推人数达标 (new LedgerWalletModel())->changeWalletAccount($parentID, Asset::USDT, $amount, Action::UsdtGenerateProfit, $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); } }