0.0001, 2 => 0.0002, 3 => 0.0003, 4 => 0.0004, 5 => 0.0005, 6 => 0.0007, 7 => 0.0009, 8 => 0.0011, 9 => 0.0013, 10 => 0.0015, ]; public static $vip_need_map = [ 1 => 1000, 2 => 5000, 3 => 10000, 4 => 50000, 5 => 100000, 6 => 500000, 7 => 1000000, 8 => 5000000, 9 => 10000000, 10 => 50000000, ]; public static $vip_airdrop_map = [ 1 => 66, 2 => 266, 3 => 566, 4 => 2666, 5 => 5666, 6 => 26666, 7 => 56666, 8 => 266666, 9 => 566666, 10 => 2666666, ]; public function getBalance($player, $field = 'balance') { $where = compact('player'); $_field = $field; return (int) $this->objTable->getOne($where, compact('_field')); } /** * 修改用户余额 * @param $player * @param $amount * @param string $type 类型:pledge:抵押, win:获得奖励, return:归还,deposit:充值, withdraw:提现 * @param $memo * @param $others { transaction_state, transaction_id, block_num, wait_amount} * @return array * @throws Exception */ public function changeBalance($player, $amount, $type, $memo, $others = null) { $objBalaceLog = new TableHelper('balance_log', 'dw_eos'); $objLock = new Lock('changeBalance', 30); $objLock->lockWait($player); $this->objTable->autoCommit(false); try { // 检查修改后,余额是否小于0 $account = $this->objTable->getRow(['player' => $player]); $account_balance = intval($account['balance']) + $amount; $beforeBalance = (int)$account['balance']; if ($account_balance < 0) { // 需要告警 $backtrace = debug_backtrace(); $msg = "changeBalance, player:{$player}, memo:{$memo}, account_balance < 0, backtrace:" . json_encode($backtrace); alermErrorMsg($msg); $objLock->unlock($player); throw new Exception('system error: account_balance < 0', CODE_UNKNOW_ERROT); } // 检查交易id是否存在 $transaction_id = $others['transaction_id']; if ($transaction_id) { $count = $objBalaceLog->getCount(['transaction_id' => $transaction_id]); if ($count) { // 需要告警 $backtrace = debug_backtrace(); $msg = "changeBalance, player:{$player}, memo:{$memo}, transaction_id has exist, backtrace:" . json_encode($backtrace); alermErrorMsg($msg); $objLock->unlock($player); throw new Exception('system error, transaction_id has exist.!', CODE_NORMAL_ERROR); } } $newData = [ 'balance' => $account['balance'], ]; // 待上链的余额 $wait_amount = arrayPop($others, 'wait_amount'); if ($wait_amount) { $newData['wait_amount'] = $account['wait_amount'] + $wait_amount; } // 处理抵押 if ($others['roomAmount']) { $roomAmount = $others['roomAmount']; $newData['game_bet'] = $account['game_bet'] - $roomAmount; if ($newData['game_bet'] < 0) { // 需要告警 $msg = "changeBalance, player:{$player}, memo:{$memo}, game_bet < 0;"; alermErrorMsg($msg); $objLock->unlock($player); throw new Exception('system error: game_bet < 0', CODE_UNKNOW_ERROT); } // 赢钱的抵押一起归还,输钱的只加奖金 if ($others['act'] != 'lose') { $newData['balance'] += $roomAmount; // 插入归还记录 $balance_log = [ 'appid' => 'box', 'player' => $player, 'change_amount' => $roomAmount, 'type' => 'return', 'before_amount' => $beforeBalance, 'after_amount' => $newData['balance'], 'eos_balance' => $account['eos_balance'], 'memo' => $memo, 'create_time' => date('Y-m-d H:i:s'), ]; $beforeBalance += $roomAmount; if (!$objBalaceLog->addObject($balance_log)) { $objLock->unlock($player); throw new Exception('system error: add balance log, try again!', CODE_NORMAL_ERROR); } } unset($others['roomAmount'], $others['act']); } // 本次操作金额 $newData['balance'] += $amount; if ($account) { // 不能修改update_time,update_time只能用于同步 $ret = $this->objTable->updateObject($newData, ['player' => $player, 'balance' => $account['balance']]); } else { $newData['player'] = $player; $newData['create_time'] = date('Y-m-d H:i:s'); $newData['update_time'] = date('Y-m-d H:i:s'); $ret = $this->objTable->addObject($newData); } if (!$ret) { // 需要告警 $backtrace = debug_backtrace(); $msg = "changeBalance, player:{$player}, memo:{$memo}, balance change fail, backtrace:" . json_encode($backtrace); alermErrorMsg($msg); $objLock->unlock($player); throw new Exception('system error: change account balance, try again!', CODE_UNKNOW_ERROT); } // 防止关闭游戏重复插入记录 if (0 != $amount) { //插入balance_log $balance_log = [ 'appid' => 'box', 'player' => $player, 'change_amount' => $amount, 'type' => $type, 'before_amount' => $beforeBalance, 'after_amount' => $newData['balance'], 'eos_balance' => $account['eos_balance'], 'memo' => $memo, 'create_time' => date('Y-m-d H:i:s'), ]; if ($others) { $balance_log += $others; } if (!$objBalaceLog->addObject($balance_log)) { $objLock->unlock($player); throw new Exception('system error: add balance log, try again!', CODE_NORMAL_ERROR); } } $this->objTable->commit(); $result = true; $msg = 'success'; } catch (Exception $e) { $this->objTable->rollback(); // 发出告警 alermErrorMsg($e->getMessage()); $result = false; $msg = $e->getMessage(); } $objLock->unlock($player); return compact('result', 'msg'); } /** * 增加下注额 * @param $player * @param $bet_amount */ public function addBetAmount($player, $bet_amount) { if ($bet_amount >= 0) { // 增加下注总额度 $account = $this->objTable->getRow(['player' => $player]); $vip_level = $this->updateBetAmount($player, $account['total_bet_amount'] + $bet_amount); // 增加vip返现 $map = self::$vip_return_map; if ($vip_level && $map[$vip_level]) { $return_amount = intval($bet_amount * $map[$vip_level]); if ($return_amount > 0) { $bet_eos = sprintf("%.4f EOS", round($bet_amount / 10000, 4)); $wait_amount = $return_amount; $memo = "vip{$vip_level} return for {$bet_eos}"; $this->changeBalance($player, $return_amount, 'vip_return', $memo, compact('wait_amount')); } } } } /** * 更新下注额 * @param $player * @param $total_bet_amount */ public function updateBetAmount($player, $total_bet_amount) { $vip_level = self::getVipLevel($total_bet_amount); $newData = compact('total_bet_amount', 'vip_level'); $this->objTable->updateObject($newData, compact('player')); if ($vip_level > 0) { // 尝试添加vip空投 $this->addVipAirdrop($player, $vip_level); } return $vip_level; } public function addVipAirdrop($player, $vip_level) { $map = self::$vip_airdrop_map; // 如果没有空投则空投 $objVipAirdropLog = new TableHelper('vip_airdrop_log', 'dw_eos'); $data = compact('player', 'vip_level'); $data['gt_amount'] = $map[$vip_level] * 10000; $data['create_time'] = date('Y-m-d H:i:s'); $data['update_time'] = $data['create_time']; $objVipAirdropLog->addObjectsIfNoExist([$data]); } /** * 根据下注额获取vip等级 * @param $bet_amount * * @return int */ public static function getVipLevel($bet_amount) { $bet_amount = intval($bet_amount / 10000); for ($i = 10; $i > 0; $i--) { if ($bet_amount >= self::$vip_need_map[$i]) { return $i; } } return 0; } public static function getTokenKey($token) { return self::PRE_KEY_TOKEN . $token; } /** * 检查token是否存在 * @param $player * * @return bool */ public static function checkToken() { $objRedis = dwRedis::init('dw_dice'); if ($_REQUEST['token'] && $_REQUEST['account']) { $token = $_REQUEST['token']; $account = $_REQUEST['account']; } else { $token = $_COOKIE['token']; $account = $_COOKIE['account']; } if ($token) { $tokenKey = self::getTokenKey($token); $value = $objRedis->get($tokenKey); if ($value) { if ($value == $account) { return true; } } else { self::clearCookie(); } } return false; } /** * 生成账号 */ public static function genToken($account) { $token = uuid16(); $tokenKey = self::getTokenKey($token); $objRedis = dwRedis::init(); // $objRedis->set($tokenKey, $account); $objRedis->setex($tokenKey, 86400, $account); return $token; } /** * 设置用户的Cookie * @param $account * * @return array */ public static function setCookie($account) { $token = Account::genToken($account); $expire = time() + 86400 * 7; $path = '/'; $domain = ''; if (ENV != ENV_DEV) { $domain = 'eosget.io'; } // 生成token setcookie('token', $token, $expire, $path, $domain); setcookie('account', $account, $expire, $path, $domain); return compact('account', 'token'); } public static function clearCookie() { $expire = time() - 86400; $path = '/'; // 删除正式环境的cookie setcookie('token', null, $expire, $path, 'eosget.io'); setcookie('account', null, $expire, $path, 'eosget.io'); if (ENV == ENV_DEV) { // 删除cookie setcookie('token', null, $expire, $path); setcookie('account', null, $expire, $path); } } public static function getRandomKey($account) { return self::PRE_KEY_RANDOM . $account; } /** * 获取随机数 * @param $player * @return string */ public static function getRandom($account) { $objRedis = dwRedis::init(); $randomKey = self::getRandomKey($account); $random = $objRedis->get($randomKey); if (!$random) { $random = uuid16(); } $objRedis->setex($randomKey, 900, $random); return $random; } public static function verifyMsg($pubkey, $account, $data, $sign) { $json = Eos::getAccount($account); $user = json_decode($json, true); // $user = EosRpcApi::getAccount($account); $active = $user['permissions'][0]['required_auth']['keys'][0]['key']; $owner = $user['permissions'][1]['required_auth']['keys'][0]['key']; if ($pubkey != $active && $pubkey != $owner) { return false; } $cmd = "node {$GLOBALS['verifyPath']} '$data' '$pubkey' '$sign'"; // 返回true表示验证通过 $ret = Eos::execCmd($cmd); return trim($ret) == 'true'; } /** * 增加推荐佣金 * @param $bet_player * @param $referee_player */ public static function addRefereeReward($bet_player, $referee_player, $bet_data) { $objLock = new Lock('addRefereeReward'); $objLock->lock($bet_player); //判断是否为第一次奖励 $objRefereeReward = new TableHelper('referee_reward_log', 'dw_eos'); $row = $objRefereeReward->getRow(['player' => $bet_player, 'referee_player' => $referee_player]); //奖励 $objAccountReward = new TableHelper('account_reward_info', 'dw_eos'); $objRefereeReward->autoCommit(false); try { $log_data = [ 'appid' => 'k3', 'player' => $bet_player, 'referee_player' => $referee_player, 'reward_eos' => floor(self::EOS_REWARD_RATE * $bet_data['bet_amount']), 'commission_rate' => self::EOS_REWARD_RATE, 'create_time' => date('Y-m-d H:i:s'), ]; $log_data += $bet_data; if (!$row) { //增加初次gt奖励 $log_data['reward_gt'] = self::REWARD_GT; } if (!$objRefereeReward->addObject($log_data)) { throw new Exception('system error: add balance log, try again!', CODE_NORMAL_ERROR); } //增加奖励总数 $user = $objAccountReward->getRow(['player' => $referee_player]); $user_data = []; if ($user) { $user_data['eos_balance'] = $user['eos_balance'] + $log_data['reward_eos']; if ($log_data['reward_gt']) { $user_data['gt'] = intval($user['gt']) + intval($log_data['reward_gt']); } $ret = $objAccountReward->updateObject($user_data, ['player' => $referee_player]); } else { $user_data['eos_balance'] = $log_data['reward_eos']; if ($log_data['reward_gt']) { $user_data['gt'] = $log_data['reward_gt']; } $user_data['player'] = $referee_player; $ret = $objAccountReward->addObject($user_data); } if (!$ret) { throw new Exception('system error: add balance log, try again!', CODE_NORMAL_ERROR); } $objRefereeReward->commit(); } catch (Exception $e) { $objRefereeReward->rollback(); $objLock->unlock($bet_player); alermErrorMsg($e->getMessage()); return [false, $e->getMessage()]; } $objLock->unlock($bet_player); return [true, '']; } /** * 绑定推荐账户 * @param $bet_player * @param $referee_player * @param $objReferee * @param $objAccount * @return array */ public static function bindReferee($bet_player, $referee_player, $objReferee = null, $objAccount = null) { if ($bet_player == $referee_player) { return [false, '推荐人不能为自己']; } //用户只能有一个推荐人 !$objReferee && $objReferee = new TableHelper('referee_relation', 'dw_eos'); $row = $objReferee->getRow(['player' => $bet_player]); if (!$row) { !$objAccount && $objAccount = new Account(); $account = $objAccount->objTable->getRow(['player' => $bet_player], ['_field' => 'total_bet_amount']); if ($account['total_bet_amount'] > 0) { return [false, '只有用户第一次下注才能绑定邀请推广']; } else { // 可以发奖励 $objReferee->addObject(['player' => $bet_player, 'referee_player' => $referee_player, 'create_time' => date('Y-m-d H:i:s')]); return [true, '']; } } else { if ($row['referee_player'] != $referee_player) { //一个用户只能有一个上线 return [false, '一个用户只能有一个邀请人,此用户的邀请人为:'. $row['referee_player']]; } else { return [true, '']; } } } /** * 玩家vip等级 * @author solu * @param $players * @return array */ public function getVipLevels($players) { if (!$players) { return []; } $items = $this->objTable->getAll(['player' => $players], ['_field' => 'player, vip_level']); return arrayFormatKey($items, 'player', 'vip_level'); } }