511 lines
17 KiB
PHP
511 lines
17 KiB
PHP
<?php
|
||
|
||
namespace app\service\game;
|
||
|
||
use addons\webman\model\Game;
|
||
use addons\webman\model\GamePlatform;
|
||
use addons\webman\model\Player;
|
||
use addons\webman\model\PlayerGamePlatform;
|
||
use addons\webman\model\PlayerWalletTransfer;
|
||
use app\exception\GameException;
|
||
use Exception;
|
||
use support\Response;
|
||
|
||
class JDBServiceInterface extends GameServiceFactory implements GameServiceInterface
|
||
{
|
||
public $method = 'POST';
|
||
public $successCode = '0000';
|
||
public $loginId;
|
||
public $gameType = [
|
||
'10' => 'Slot',
|
||
'12' => 'Casino',
|
||
'13' => 'Arcade',
|
||
'16' => 'Fishing'
|
||
];
|
||
public $failCode = [
|
||
'0000' => '成功',
|
||
'9999' => '失敗',
|
||
'9001' => '未授權訪問',
|
||
'9002' => '域名為空或域名長度小於 2',
|
||
'9003' => '域名驗證失敗。',
|
||
'9004' => '加密數據為空或加密數據的長度等於 0。',
|
||
'9005' => '斷言(SAML)未通過時間戳驗證。',
|
||
'9006' => '從加密數據中提取 SAML 參數失敗。',
|
||
'9007' => '未知操作。',
|
||
'9008' => '與之前的值相同。',
|
||
'9009' => '超時。',
|
||
'9010' => '讀取超時。',
|
||
'9011' => '重複交易。',
|
||
'9012' => '請稍後再試。',
|
||
'9013' => '系統正在維護。',
|
||
'9014' => '檢測到多帳戶登錄。',
|
||
'9015' => '數據不存在。',
|
||
'9016' => '無效令牌。',
|
||
'9019' => '請求速率限制超過。',
|
||
'9020' => '每次登錄只能獲得一次遊戲票。',
|
||
'9021' => '違反一次性會話策略。',
|
||
'9022' => '遊戲正在維護。',
|
||
'9023' => '不支持的貨幣。',
|
||
'9024' => '贏取倍數必須大於或等於 10 倍。',
|
||
'9025' => '不支持重放遊戲。',
|
||
'9026' => '获胜金额应大于0。',
|
||
'9027' => '不支持演示。',
|
||
'8000' => '輸入參數錯誤,請檢查您的參數是否正確。',
|
||
'8001' => '參數不能為空。',
|
||
'8002' => '參數必須是正整數。',
|
||
'8003' => '參數不能為負數。',
|
||
'8005' => '日期秒格式錯誤',
|
||
'8006' => '時間不符合。',
|
||
'8007' => '參數只能使用數字。',
|
||
'8008' => '找不到參數。',
|
||
'8009' => '時間間隔超過允許範圍。',
|
||
'8010' => '參數長度太長。',
|
||
'8013' => '日期分鐘格式參數錯誤。',
|
||
'8014' => '參數不得超過指定的小數位。',
|
||
'7001' => '找不到指定的父 ID。',
|
||
'7002' => '父級已暫停。',
|
||
'7003' => '父級已鎖定。',
|
||
'7004' => '父級已關閉。',
|
||
'7405' => '您已登出!',
|
||
'7501' => '找不到用戶 ID。',
|
||
'7502' => '用戶已暫停。',
|
||
'7503' => '用戶已鎖定。',
|
||
'7504' => '用戶已關閉。',
|
||
'7505' => '用戶未在玩遊戲。',
|
||
'7506' => '演示帳戶已滿。',
|
||
'7601' => '無效的用戶 ID。請僅使用 a-z、0-9 之間的字符。',
|
||
'7602' => '帳戶已存在。請選擇其他用戶 ID。',
|
||
'7603' => '無效的用戶名。',
|
||
'7604' => '密碼必須至少 6 個字符,包含 1 個字母和 1 個數字。',
|
||
'7605' => '無效的操作代碼。請僅使用數字 2、3、4、5。',
|
||
'6001' => '您的現金餘額不足以取款。',
|
||
'6002' => '用戶餘額為零。',
|
||
'6003' => '取款金額為負。',
|
||
'6004' => '重複轉帳。',
|
||
'6005' => '重複的序列號。',
|
||
'6009' => '存款金額超過上限。',
|
||
'6010' => '餘額超過上限。',
|
||
'6011' => '分配的信用額超過上限。',
|
||
'6012' => '序列號正在進行中。',
|
||
'6901' => '用戶正在玩遊戲,不允許轉移餘額。'
|
||
];
|
||
private $apiDomain;
|
||
private $domain;
|
||
private $iv;
|
||
private $key;
|
||
private $dc;
|
||
private $parent;
|
||
private $lang = [
|
||
'zh-CN' => 'cn',
|
||
'zh-TW' => 'cn',
|
||
'jp' => 'jpn',
|
||
'en' => 'en',
|
||
'th' => 'th',
|
||
'vi' => 'vi',
|
||
'kr_ko' => 'ko',
|
||
'id' => 'id',
|
||
];
|
||
|
||
public $localGameType = [
|
||
'0' => '1',//斯洛
|
||
'32' => '1',//斯洛
|
||
'50' => '1',//斯洛
|
||
'55' => '1',//斯洛
|
||
'57' => '1',//斯洛
|
||
'58' => '1',//斯洛
|
||
'66' => '1',//斯洛
|
||
'80' => '1',//斯洛
|
||
'90' => '1',//斯洛
|
||
'130' => '1',//斯洛
|
||
'7' => '4',//捕鱼
|
||
'31' => '4',//捕鱼
|
||
'70' => '4',//捕鱼
|
||
'59' => '4',//捕鱼
|
||
'67' => '4',//捕鱼
|
||
'91' => '4',//捕鱼
|
||
'8' => '8',//宾果
|
||
'12' => '8',//宾果
|
||
'60' => '8',//宾果
|
||
'9' => '8',//宾果
|
||
'22' => '8',//宾果
|
||
'30' => '8',//宾果
|
||
'56' => '8',//宾果
|
||
'75' => '8',//宾果
|
||
'81' => '8',//宾果
|
||
'92' => '8',//宾果
|
||
'131' => '8',//宾果
|
||
'120' => '8',//宾果
|
||
'18' => '2',//赌场
|
||
'93' => '2',//赌场
|
||
'132' => '2',//赌场
|
||
'41' => '5',//真人视讯
|
||
'101' => '5',//真人视讯
|
||
];
|
||
|
||
/**
|
||
* @param Player|null $player
|
||
* @param $type
|
||
* @throws Exception
|
||
*/
|
||
public function __construct($type, Player $player = null)
|
||
{
|
||
$config = config('game_platform.' . $type);
|
||
$this->iv = $config['iv'];
|
||
$this->apiDomain = $config['api_domain'].'/apiRequest.do';
|
||
$this->domain = $config['domain'];
|
||
$this->key = $config['key'];
|
||
$this->dc = $config['dc'];
|
||
$this->parent = $config['admin_user'];
|
||
$this->platform = GamePlatform::query()->where('name', $type)->first();
|
||
if (!empty($player)) {
|
||
$this->player = $player;
|
||
$this->getLoginId();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 生成请求数据
|
||
* @param $source
|
||
* @return string
|
||
*/
|
||
public function padString($source): string
|
||
{
|
||
$paddingChar = ' ';
|
||
$size = 16;
|
||
$x = strlen($source) % $size;
|
||
$padLength = $size - $x;
|
||
$source .= str_repeat($paddingChar, $padLength);
|
||
return $source;
|
||
}
|
||
|
||
/**
|
||
* 生成请求数据
|
||
* @param $params
|
||
* @return array
|
||
*/
|
||
public function buildParams($params): array
|
||
{
|
||
$data = $this->padString(json_encode($params));
|
||
$encryptData = openssl_encrypt($data, 'AES-128-CBC', $this->key, OPENSSL_NO_PADDING, $this->iv);
|
||
$reqBase64 = base64_encode($encryptData);
|
||
return [
|
||
'dc' => $this->dc,
|
||
'x' => str_replace(array('+','/','=') , array('-','_','') , $reqBase64)
|
||
];
|
||
}
|
||
|
||
/**
|
||
* @throws Exception
|
||
*/
|
||
protected function getLoginId()
|
||
{
|
||
/** @var PlayerGamePlatform $playerGamePlatform */
|
||
$playerGamePlatform = PlayerGamePlatform::query()
|
||
->where('platform_id', $this->platform->id)
|
||
->where('player_id',$this->player->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|\think\Exception
|
||
*/
|
||
public function createPlayer(array $data = [])
|
||
{
|
||
$params = [
|
||
'action' => 12,
|
||
'ts' => round(microtime(true) * 1000),
|
||
'lang' => 'cn',
|
||
'parent' => $this->parent,
|
||
'uid' => $this->player->uuid,
|
||
'name' => $this->player->name ?: $this->player->uuid
|
||
];
|
||
$request = $this->buildParams($params);
|
||
$res = doFormCurl($this->apiDomain, $request);
|
||
if ($res['status'] != $this->successCode) {
|
||
throw new GameException($this->failCode[$res['status']], 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;
|
||
}
|
||
|
||
public function getPlayer()
|
||
{
|
||
// TODO: Implement getPlayer() method.
|
||
}
|
||
|
||
/**
|
||
* 获取游戏摘要MD5 (id+method+sn+APlSecretKey)
|
||
* @return array|mixed|Response
|
||
* @throws GameException|\think\Exception
|
||
*/
|
||
public function getSimpleGameList()
|
||
{
|
||
$params = [
|
||
'action' => 49,
|
||
'ts' => round(microtime(true) * 1000),
|
||
'parent' => $this->parent,
|
||
'lang' => 'en',
|
||
];
|
||
$request = $this->buildParams($params);
|
||
$res = doFormCurl($this->apiDomain, $request);
|
||
if ($res['status'] != $this->successCode) {
|
||
throw new GameException($this->failCode[$res['status']], 0);
|
||
}
|
||
$insertData = [];
|
||
if (!empty($res['data'])) {
|
||
foreach ($res['data'] as $data) {
|
||
foreach($data['list'] as $item){
|
||
$insertData[] = [
|
||
'platform_id' => $this->platform->id,
|
||
'game_code' => $item['mType'],
|
||
'platform_game_type' => $data['gType'],
|
||
'game_type' => $this->localGameType[$data['gType']],
|
||
'name' => $item['name'],
|
||
'game_image' => $item['image'],
|
||
];
|
||
}
|
||
}
|
||
}
|
||
if (!empty($insertData)) {
|
||
Game::query()->upsert($insertData, ['platform_id', 'game_code']);
|
||
}
|
||
return $insertData;
|
||
}
|
||
|
||
/**
|
||
* 获取游戏摘要MD5 (id+method+sn+APlSecretKey)
|
||
* @param array $data
|
||
* @return string
|
||
* @throws GameException|\think\Exception
|
||
*/
|
||
public function login(array $data = []): string
|
||
{
|
||
$params = [
|
||
'action' => 11,
|
||
'ts' => round(microtime(true) * 1000),
|
||
'lang' => $this->lang[$data['lang']] ?? 'en',
|
||
'uid' => $this->loginId,
|
||
'gType' => $data['platformGameType'],
|
||
'mType' => $data['gameCode'],
|
||
'windowMode' => 2,
|
||
'isAPP' => true,
|
||
];
|
||
// if($data['platformGameType'] || $data['gameCode']){
|
||
// $params['gType'] = $data['platformGameType'];
|
||
// $params['mType'] = $data['gameCode'];
|
||
// $params['windowMode'] = 2;
|
||
// $params['isAPP'] = true;
|
||
// }
|
||
$request = $this->buildParams($params);
|
||
$res = doFormCurl($this->apiDomain, $request);
|
||
if ($res['status'] != $this->successCode) {
|
||
throw new GameException($this->failCode[$res['status']], 0);
|
||
}
|
||
return $res['path'] ?? '';
|
||
}
|
||
|
||
/**
|
||
* 玩家钱包转入游戏平台
|
||
* @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()
|
||
{
|
||
//提现之前把用户踢下线
|
||
if($this->checkPlay()){
|
||
$this->userLogout();
|
||
sleep(1);
|
||
}
|
||
$balance = $this->getBalance();
|
||
if($balance == 0){
|
||
// 记录玩家钱包转出转入记录
|
||
$this->createWalletTransfer(PlayerWalletTransfer::TYPE_IN, 0, 0);
|
||
return true;
|
||
}
|
||
return $this->setBalanceTransfer(PlayerWalletTransfer::TYPE_IN, $balance ? -$balance : 0);
|
||
}
|
||
|
||
/**
|
||
* 轉帳進出額度
|
||
* @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)
|
||
{
|
||
$params = [
|
||
'action' => 19,
|
||
'ts' => round(microtime(true) * 1000),
|
||
'parent' => $this->parent,
|
||
'uid' => $this->loginId,
|
||
'serialNo' => createOrderNo(),
|
||
'amount' => $amount ?? 0,
|
||
];
|
||
$request = $this->buildParams($params);
|
||
$res = doFormCurl($this->apiDomain, $request);
|
||
if ($res['status'] != $this->successCode) {
|
||
throw new GameException($this->failCode[$res['status']], 0);
|
||
}
|
||
// 记录玩家钱包转出转入记录
|
||
$this->createWalletTransfer($type, $amount, $reward);
|
||
return $res;
|
||
}
|
||
|
||
/**
|
||
* 獲取玩家餘額信息
|
||
* @return array|mixed|Response
|
||
* @throws GameException|\think\Exception
|
||
*/
|
||
public function getBalance()
|
||
{
|
||
$params = [
|
||
'action' => 15,
|
||
'ts' => round(microtime(true) * 1000),
|
||
'parent' => $this->parent,
|
||
'uid' => $this->loginId,
|
||
];
|
||
|
||
$request = $this->buildParams($params);
|
||
$res = doFormCurl($this->apiDomain, $request);
|
||
if ($res['status'] != $this->successCode) {
|
||
throw new GameException('JDB System Error,Please contact the administrator', 0);
|
||
}
|
||
|
||
return $res['data'][0]['balance'] ?? 0;
|
||
}
|
||
|
||
/**
|
||
* 查询玩家状态
|
||
* @throws GameException|\think\Exception
|
||
*/
|
||
public function checkPlay(): bool
|
||
{
|
||
$params = [
|
||
'action' => 52,
|
||
'ts' => round(microtime(true) * 1000),
|
||
'parent' => $this->parent,
|
||
'uid' => $this->loginId,
|
||
];
|
||
|
||
$request = $this->buildParams($params);
|
||
$res = doFormCurl($this->apiDomain, $request);
|
||
//游戏中
|
||
if($res['status'] == $this->successCode){
|
||
return true;
|
||
}
|
||
//不在游戏中
|
||
if($res['status'] == 7505){
|
||
return false;
|
||
}
|
||
throw new GameException($this->failCode[$res['status']], 0);
|
||
}
|
||
|
||
/**
|
||
* 玩家踢下线
|
||
* @throws GameException|\think\Exception
|
||
*/
|
||
public function userLogout(): bool
|
||
{
|
||
$params = [
|
||
'action' => 17,
|
||
'ts' => round(microtime(true) * 1000),
|
||
'parent' => $this->parent,
|
||
'uid' => $this->loginId,
|
||
];
|
||
|
||
$request = $this->buildParams($params);
|
||
$res = doFormCurl($this->apiDomain, $request);
|
||
if ($res['status'] != $this->successCode) {
|
||
throw new GameException($this->failCode[$res['status']], 0);
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 取得區間內遊戲紀錄
|
||
* @return array
|
||
* @throws Exception
|
||
*/
|
||
public function handleOrderHistories(): array
|
||
{
|
||
$list = [];
|
||
try {
|
||
$data = $this->getGameHistories();
|
||
if (!empty($data)) {
|
||
foreach ($data as $item) {
|
||
if ($item['gType'] == 9 && !empty($item['hasGamble'])) {
|
||
$item['bet'] = $item['gambleBet'];
|
||
}
|
||
$list[] = [
|
||
'uuid' => $item['playerId'],
|
||
'platform_id' => $this->platform->id,
|
||
'game_code' => $item['mtype'],
|
||
'bet' => abs($item['bet']),
|
||
'win' => max($item['win'], 0),
|
||
'order_no' => $item['historyId'],
|
||
'game_type' => $item['gType'],
|
||
'original_data' => json_encode($item,JSON_UNESCAPED_UNICODE),
|
||
'platform_action_at' => date('Y-m-d H:i:s', strtotime($item['lastModifyTime'])),
|
||
'created_at' => date('Y-m-d H:i:s'),
|
||
'updated_at' => date('Y-m-d H:i:s'),
|
||
];
|
||
}
|
||
}
|
||
} catch (Exception $e) {
|
||
return [];
|
||
}
|
||
|
||
return $list;
|
||
}
|
||
|
||
/**
|
||
* 取得區間內遊戲紀錄
|
||
* @return array
|
||
* @throws GameException|\think\Exception
|
||
*/
|
||
public function getGameHistories(): array
|
||
{
|
||
$params = [
|
||
'action' => 29,
|
||
'ts' => round(microtime(true) * 1000),
|
||
'parent' => $this->parent,
|
||
'starttime' => date('d-m-Y H:i:00', strtotime('-5 minutes')),
|
||
'endtime' => date('d-m-Y H:i:00', strtotime('-4 minutes')),
|
||
];
|
||
$request = $this->buildParams($params);
|
||
$res = doFormCurl($this->apiDomain, $request);
|
||
if ($res['status'] != $this->successCode) {
|
||
throw new GameException($this->failCode[$res['status']], 0);
|
||
}
|
||
return $res['data'] ?? [];
|
||
}
|
||
} |