123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545 |
- <?php
- /**
- * 用户基础信息
- * @author benzhan
- */
- class Account extends Model {
- protected $tableName = 'account';
- protected $dbKey = 'dw_eos';
- const PRE_KEY_TOKEN = 'globals:token:';
- const PRE_KEY_RANDOM = 'globals:random_1:';
- const EOS_REWARD_RATE = 0.002;
- const REWARD_GT = 50000;
- public static $vip_return_map = [
- 1 => 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');
- }
- }
|