Files
dafuweng/app/service/game/JDBServiceInterface.php
2026-03-02 13:44:38 +08:00

511 lines
17 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?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'] ?? [];
}
}