'Casino', 'Fishing' => 'Fishing', 'Bingo' => 'Bingo', 'Slot' => 'Slot', ]; public $localGameType = [ 'ECasino' => '2', 'Fishing' => '4', 'Bingo' => '8', 'Slot' => '1', ]; public $failCode = [ 'S200' => '重復請求', 'F0001' => '無效的簽名', 'F0002' => '無效的SN', 'F0003' => '無效的參數', 'F0004' => '無效的貨幣', 'F0005' => '玩家已存在', 'F0006' => '玩家不存在', 'F0007' => '會員不存在', 'F0008' => '執行失敗', 'F0009' => '無效的方法', 'F0010' => '無效的用戶狀態', 'F0011' => '玩家狀態無需更新', 'F0012' => '超出數據範圍', 'F0013' => '無匹配數據', 'F0014' => '登入位置被禁止', 'F0015' => '分數不足夠', 'F0016' => '不支持禮碼', 'F0017' => '交易流水號不得重複', 'F0018' => '系統繁忙', 'F0019' => '日期時間各式錯誤', 'F0020' => '超出時間限制範圍(開始時間與結束時間之間不能大於120分鐘)', 'F0021' => '執行取消', 'M0001' => '系統維護', 'M0002' => '系統錯誤', ]; private $lang = [ 'zh-CN' => 'zh_ch', 'en' => 'en_us', 'zh_tc' => 'zh_tc', 'th_th' => 'th_th', 'Ma_my' => 'Ma_my', 'vi_nam' => 'vi_nam', 'Fi_fi' => 'Fi_fi', 'Kr_ko' => 'Kr_ko', 'Hi_hi' => 'Hi_hi', 'My_mar' => 'My_mar', 'Br_po' => 'Br_po', 'cam_dia' => 'cam_dia', // 柬埔寨语 ]; /** * @param Player|null $player * @param $type * @throws Exception */ public function __construct($type, Player $player = null) { $config = config('game_platform.' . $type); $this->appId = $config['app_id']; $this->apiDomain = $config['api_domain']; $this->domain = $config['domain']; $this->appSecret = $config['app_secret']; $this->platform = GamePlatform::query()->where('name', $type)->first(); if (!empty($player)) { $this->player = $player; $this->getLoginId(); } } /** * 生成请求url * @param $method * @return string */ public function createUrl($signature): string { return $this->apiDomain."?AppID=".$this->appId."&Signature=".$signature; } public function createSign($params): string { ksort($params); $signature = urlencode(base64_encode(hash_hmac("sha1", urldecode(http_build_query($params,'', '&')), $this->appSecret, TRUE))); return $signature; } /** * 更新游戏列表 * @return array|mixed|Response * @throws GameException|\think\Exception */ public function getSimpleGameList() { $params = [ 'Method' => 'ListGames', 'Timestamp' => time(), ]; $signature = $this->createSign($params); $result = doCurl($this->createUrl($signature), $params); if (isset($result['ListGames'])) { foreach ($result['ListGames'] as $game) { Game::query()->updateOrCreate( [ 'platform_id' => $this->platform->id, 'game_code' => $game['GameCode'], ], [ 'platform_game_type' => $game['GameType'], 'game_type' => $this->localGameType[$game['GameType']], 'name' => $game['GameName'], ] ); } }else{ throw new GameException($result['Message'], 0); } return $result; } /** * 获取游戏列表 * @return array|mixed|Response * @throws GameException|\think\Exception */ public function getGamesList() { $params = [ 'Method' => 'ListGames', 'Timestamp' => time(), ]; $signature = $this->createSign($params); $result = doCurl($this->createUrl($signature), $params); if (isset($result['ListGames'])) { return $result; }else{ throw new GameException($result['Message'], 0); } } /** * 获取游戏列表 * @return array|mixed|Response * @throws GameException|\think\Exception */ public function playFreeGame() { $params = [ 'Method' => 'PLAY', 'Username' => $this->player->name, 'Timestamp' => time(), ]; $signature = $this->createSign($params); $result = doCurl($this->createUrl($signature), $params); if (isset($result['Token'])) { return $forwardUrl = $this->domain."?token=".$result['Token']."&game=1jeqx59c7ztqg&mobile=false"; }else{ throw new GameException($result['Message'], 0); } } /** * 玩游戏 * @return array|mixed|Response * @throws GameException|\think\Exception */ public function playGame() { $params = [ 'Method' => 'PLAY', 'Username' => $this->player->name, 'RequestID' => createOrderNo(), 'Amount' => $amount, 'Timestamp' => time(), ]; $signature = $this->createSign($params); $result = doCurl($this->createUrl($signature), $params); if (isset($result['Token'])) { return $forwardUrl = $this->domain."?token=".$result['Token']."&game=1jeqx59c7ztqg&mobile=false"; }else{ throw new GameException($result['Message'], 0); } } /** * @throws Exception */ protected function getLoginId() { /** @var PlayerGamePlatform $playerGamePlatform */ $playerGamePlatform = $this->player->playerGamePlatform->where('platform_id', $this->platform->id)->first(); if (!empty($playerGamePlatform)) { return $this->loginId = $playerGamePlatform->player_code; } return $this->createPlayer([ 'uuid' => $this->player->uuid, 'name' => $this->player->name, ]); } /** * 创建玩家 * @param array $data * @return array|mixed|Response * @throws GameException|Exception */ public function createPlayer(array $data = []) { $params = [ 'Method' => 'CU', 'Username' => $data['uuid'], 'Timestamp' => time(), ]; $signature = $this->createSign($params); $res = doCurl($this->createUrl($signature), $params); if (empty($res['Status']) || $res['Status'] != 'OK') { Log::error($res['Message'], ['res' => $res]); throw new GameException($res['Message'], 0); } $playerGamePlatform = new PlayerGamePlatform(); $playerGamePlatform->player_id = $this->player->id; $playerGamePlatform->platform_id = $this->platform->id; $playerGamePlatform->player_name = $data['name']; $playerGamePlatform->player_code = $data['uuid']; $playerGamePlatform->save(); $this->loginId = $playerGamePlatform->player_code; return $res; } /** * 获取玩家 * @return array|mixed|Response * @throws GameException|Exception */ public function getPlayer() { $params = [ 'ID' => createOrderNo(), 'Method' => 'GetPlayer', 'SN' => $this->appId, 'LoginId' => $this->loginId, ]; $params['Signature'] = $this->createSign($params); $data = doCurl($this->createUrl('getPlayer'), $params); if ($data['code'] != $this->successCode) { throw new GameException($this->failCode[$data['code']], 0); } return $data; } /** * 玩家进入游戏 * @param array $data * @return string * @throws GameException|\think\Exception */ public function login(array $data = []): string { $params = [ 'Method' => 'PLAY', 'Username' => $this->loginId, 'RequestID' => createOrderNo(), 'Amount' => 0, 'Timestamp' => time(), ]; $signature = $this->createSign($params); $res = doCurl($this->createUrl($signature), $params); if (empty($res['Token'])) { Log::error($res['Message'], ['res' => $res]); throw new GameException($res['Message'], 0); } if (!empty($data['gameCode'])) { $link = $this->domain.'?token='.$res['Token'].'&game='.$data['gameCode'].'&mobile=1&lang=en'; }else{ $link = $this->domain . ($res['data']['loginUrl'] ?? '') . '&' . $parametersValue; } return $link; } /** * 设置用户状态 * @return array|mixed|Response * @throws GameException|\think\Exception */ public function setPlayerStatus($status) { $params = [ 'Method' => 'SS', 'Username' => $this->loginId, 'Status' => $status, 'Timestamp' => time(), ]; $signature = $this->createSign($params); $res = doCurl($this->createUrl($signature), $params); if ($res['Status'] != 'OK') { throw new GameException($this->failCode[$res['Status']], 0); } return $res; } /** * 获取玩家游戏平台余额 * @return array|mixed|Response * @throws GameException|\think\Exception */ public function getBalance() { $params = [ 'Method' => 'GC', 'Username' => $this->loginId, 'Timestamp' => time(), ]; $signature = $this->createSign($params); $res = doCurl($this->createUrl($signature), $params); if (empty($res['Credit']) && !empty($res['Message'])) { throw new GameException($res['Message'], 0); } return $res; } /** * 玩家钱包转入游戏平台 * @return array|mixed|null * @throws GameException|\think\Exception */ public function balanceTransferOut() { return $this->setBalanceTransfer(PlayerWalletTransfer::TYPE_OUT, $this->player->wallet->money); } /** * 游戏平台转入玩家钱包 * @return array|mixed|null * @throws GameException|\think\Exception */ public function balanceTransferIn() { $params = [ 'Method' => 'WAC', 'Username' => $this->loginId, 'Timestamp' => time(), 'RequestID' => createOrderNo(), ]; $signature = $this->createSign($params); $res = doCurl($this->createUrl($signature), $params); if (empty($res['RequestID']) || $res['RequestID'] != $params['RequestID'] || $res['Amount'] == 0) { throw new GameException($res['Message'], 0); } // 记录玩家钱包转出转入记录 $this->createWalletTransfer(PlayerWalletTransfer::TYPE_IN, $res['Amount'], 0, $res['RequestID'] ?? ''); return $res; } /** * 轉帳進出額度 * 簽名密鑰方式 MD5 (Id+Method+SN+LoginId+APISecretKey) * @param $type * @param float $amount * @param float $reward * @return array|mixed|null * @throws GameException|\think\Exception */ protected function setBalanceTransfer($type, float $amount = 0, float $reward = 0) { if ($amount == 0 && $reward == 0) { throw new GameException('转出/入金额错误', 0); } $params = [ 'Method' => 'TC', 'Username' => $this->loginId, 'Timestamp' => time(), 'RequestID' => createOrderNo(), 'Amount' => $amount, ]; $signature = $this->createSign($params); $res = doCurl($this->createUrl($signature), $params); if (empty($res['RequestID']) || $res['RequestID'] != $params['RequestID']) { // Log::error($res['Message'], ['res' => $res]); throw new GameException($res['Message'], 0); } // 记录玩家钱包转出转入记录 $this->createWalletTransfer($type, $amount, $reward, $res['RequestID'] ?? ''); return $res; } /** * 依據時間獲取遊戲紀錄 * MD5 (Id+Method+SN+StartTime+EndTime+APISecretKey) * @param int $pageIndex * @param string $startTime * @param string $endTime * @return array|mixed|null * @throws GameException|\think\Exception */ public function getGameRecordByTime(string $startTime = '', string $endTime = '') { $params = [ 'Method' => 'TSM', 'StartDate' => $startTime, 'EndDate' => $endTime, 'NextId' => '', 'Delay' => 0, 'Timestamp' => time(), ]; $signature = $this->createSign($params); $res = doCurl($this->createUrl($signature), $params); // if (empty($res['data'])) { // throw new GameException($res['Message'], 0); // } return $res; } }