'Casino', 'Fishing' => 'Fishing', 'Bingo' => 'Bingo', 'Slot' => 'Slot', ]; public $localGameType = [ 'slot' => '2', 'multiplayer' => '1', 'fishing' => '7', 'bet' => '5', ]; public $failCode = [ '0' => '应用不存在', '1000' => '参数错误', '1101' => '玩家账号', '1102' => '密码', '1103' => '玩家id', '1204' => '金额', '1205' => '开始时间', '1206' => '结束时间', '2001' => '渠道不存在', '2100' => '用户错误', '2102' => '用户已注册', '2103' => '玩家不存在', '2104' => '玩家已被停用', '2205' => '钱包余额不足', '2206' => '结束时间必须大于起始时间', '2207' => '查询时间不能超过1小时', '3000' => '系统错误', '3201' => '钱包转出失败', '3202' => '钱包转入失败', '3902' => 'JWT清除失败', ]; public function __construct($player = null) { $config = ConfigModel::where('group', 'mini_games')->column('value', 'name'); $this->appId = $config['app_id']; $this->appSecret = $config['app_secret']; $this->domain = $config['domain']; if (!empty($player)) { $this->player = $player; $this->account = $player['xyx_account']; $this->password = $player['xyx_password']; if (empty($this->account) || empty($this->password)) { $this->createPlayer($player); } } } /** * 生成请求 * @param $url * @param array $params * @return array|mixed * @throws \Exception */ public function doXyxCurl($url, array $params = []) { $headers = [ 'appId' => $this->appId, 'timestamp' => time(), 'nonceStr' => Str::random(6), ]; $data = array_merge($params,$headers); ksort($data); $signature = hash('sha256', urldecode(http_build_query($data)) . $this->appSecret); $headers['signature'] = $signature; $client = new Client([ 'timeout' => 7, 'verify' => true, ]); try { $response = $client->post($url, [ 'json' => $params, // 相当于 asJson(),会自动设置 Content-Type: application/json 'headers' => $headers, ]); if ($response->getStatusCode() !== 200) { throw new \Exception(lang('system_busy')); // ThinkPHP 使用 lang() 代替 trans() } $contents = $response->getBody()->getContents(); $data = json_decode($contents, true); if (empty($data)) { throw new \Exception(lang('system_busy')); } return $data; } catch (GuzzleException $e) { // 请求失败(如超时、证书错误等) throw new \Exception(lang('system_busy')); } } /** * 获取token */ public function getToken($gameId) { $params = [ 'account' => $this->account, 'password' => $this->password, 'game_id' => $gameId, ]; $res = $this->doXyxCurl($this->domain . 'agent/api/get-access-token', $params); if ($res['code'] != 200) { throw new \Exception($this->failCode[$res['code']]); } return $res['data']['access_token']; } /** * 创建玩家 */ public function createPlayer($player) { $params = [ 'account' => 'jk' . $player['jk_user_id'], 'password' => Str::random(12), ]; $res = $this->doXyxCurl($this->domain . 'agent/api/create-player', $params); if ($res['code'] != 200) { throw new \Exception($this->failCode[$res['code']]); } $player->xyx_account = $params['account']; $player->xyx_password = $params['password']; $player->save(); $this->account = $params['account']; $this->password = $params['password']; return $res; } /** * 玩家进入游戏 * @param array $data * @return string */ public function login(array $data = []): string { $token = $this->getToken($data['gameCode']); $out = UserScoreLog::where('user_id', $this->player->id) ->where('type', 2) ->whereNotNull('created_by') ->order('id', 'desc') ->find(); if ($out) { $this->balanceTransferIn($out->game_type); } $this->balanceTransferOut($data['gameCode']); $headers = [ 'appId' => $this->appId, 'timestamp' => time(), 'nonceStr' => Str::random(6), ]; ksort($headers); $signature = hash('sha256', urldecode(http_build_query($headers)) . $this->appSecret); $headers['signature'] = $signature; $headers['Authorization'] = 'Bearer ' . $token; $client = new Client([ 'timeout' => 7, 'allow_redirects' => false, ]); try { $response = $client->request('GET', $this->domain . 'agent/enter-game', [ 'headers' => $headers, ]); if ($response->getStatusCode() == 302) { return $response->getHeader('Location')[0] ?? ''; } } catch (RequestException $e) { if ($e->hasResponse() && $e->getResponse()->getStatusCode() == 302) { return $e->getResponse()->getHeader('Location')[0] ?? ''; } } return false; } /** * 获取玩家游戏平台余额 */ public function getBalance() { $params = [ 'account' => $this->account, ]; $res = $this->doXyxCurl($this->domain . 'agent/api/get-player-info', $params); if ($res['code'] != 200) { throw new \Exception($this->failCode[$res['code']]); } return $res['data']['point']; } /** * 玩家钱包转入游戏平台 */ public function balanceTransferOut($gameType) { $score = $this->player->userScore()->where('game_type', $gameType)->value('score'); if ($score == 0) { return true; } return $this->setBalanceTransfer(2, $gameType, $score); } /** * 游戏平台转入玩家钱包 */ public function balanceTransferIn($gameType) { $balance = $this->getBalance(); if ($balance == 0) { $userScore = $this->player->userScore()->where('game_type', $gameType)->find(); $userScoreLog = new UserScoreLog(); $userScoreLog->save([ 'user_id' => $this->player->id, 'game_type' => $gameType, 'before' => $userScore->score, 'after' => $userScore->score, 'score' => 0, 'memo' => '转入', 'type' => 1, 'created_by'=> 0, ]); return true; } return $this->setBalanceTransfer(1, $gameType, $balance); } /** * 轉帳進出額度 * @param $type * @param float $amount * @return array|mixed|null * @throws \Exception */ protected function setBalanceTransfer($type,$gameType, float $amount = 0) { $yCode = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']; $tradeno = $yCode[intval(date('Y')) - 2011] . strtoupper(dechex(date('m'))) . date('d') . substr(microtime(), 2, 5) . sprintf('%02d', rand(0, 99)); $params = [ 'account' => $this->account, 'point' => $amount, 'tradeno' => $tradeno ]; if ($type == 2) { $res = $this->doXyxCurl($this->domain . 'agent/api/transfer-in', $params); } else { $res = $this->doXyxCurl($this->domain . 'agent/api/transfer-out', $params); } if ($res['code'] != 200) { throw new \Exception($this->failCode[$res['code']]); } $userScore = $this->player->userScore()->where('game_type', $gameType)->find(); $userScore->created_by = 0; if ($type == 2) { $userScore->score = 0; $userScore->memo = '转出'; } else { $userScore->score += $amount; $userScore->memo = '转入'; } $userScore->save(); return $res; } public function getReportRecord(string $startTime = '', string $endTime = '') { $params = [ 'start_date' => $startTime, 'end_date' => $endTime, ]; $res = $this->doXyxCurl($this->domain . 'agent/api/draw-records-by-date', $params); if ($res['code'] != 200) { throw new \Exception($this->failCode[$res['code']]); } return $res['data']; } }