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

473 lines
15 KiB
PHP
Raw 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 DateTime;
use DateTimeZone;
use Exception;
use support\Log;
use support\Response;
use WebmanTech\LaravelHttpClient\Facades\Http;
class PragmaticServiceInterface extends GameServiceFactory implements GameServiceInterface
{
public $method = 'POST';
private $apiDomain;
private $domain;
private $appId;
private $appSecret;
private $secureLogin;
private $providerId;
public $loginId;
public $gameType = [
'2' => 'Casino',
'5' => 'Fishing',
'8' => 'Bingo',
'1' => 'Slot',
];
public $localGameType = [
'2' => '2',//赌场
'5' => '4',//捕鱼
'8' => '8',//宾果
'vs' => '1',//斯洛
'lg' => '5',//真人游戏
];
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' => '系統錯誤',
];
/**
* @param Player|null $player
* @param $type
* @throws Exception
*/
public function __construct($type, Player $player = null)
{
$config = config('game_platform.' . $type);
$this->apiDomain = $config['api_domain'];
$this->domain = $config['domain'];
$this->appId = $config['name'];
$this->secureLogin = $config['secure_login'];
$this->providerId = $config['provider_id'];
$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($method): string
{
return $this->apiDomain.$method;
}
public function createSign($params): string
{
ksort($params);
return md5(http_build_query($params, '', '&') . $this->appSecret);
}
/**
* 更新游戏列表
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getSimpleGameList()
{
$params = [
'secureLogin' => $this->secureLogin,
];
$signature = $this->createSign($params);
$params['hash'] = $signature;
$result = doFormCurl($this->createUrl('/IntegrationService/v3/http/CasinoGameAPI/getCasinoGames/'), $params);
if ($result['error'] == 0 && !empty($result['gameList'])) {
foreach ($result['gameList'] as $game) {
if ($game['gameTypeID'] != 'vs') {
continue;
}
Game::query()->updateOrCreate(
[
'platform_id' => $this->platform->id,
'game_code' => $game['gameID'],
],
[
'platform_game_type' => $game['gameTypeID'],
'game_type' => $this->localGameType[$game['gameTypeID']],
'name' => $game['gameName'],
// 'game_image' => $this->apiDomain.'/gs2c/common/lobby/v1/apps/slots-lobby-assets/'.$game['gameID'].'/'.$game['gameID'].'_325x234_NB.png'
]
);
}
}else{
throw new GameException($result['description'], 0);
}
return $result;
}
/**
* 获取游戏列表
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getGamesList()
{
$params = [
'secureLogin' => $this->secureLogin,
];
$signature = $this->createSign($params);
$params['hash'] = $signature;
$result = doFormCurl($this->createUrl('/IntegrationService/v3/http/CasinoGameAPI/getCasinoGames/'), $params);
if ($result['error'] == 0 && !empty($result['gameList'])) {
return $result;
}else{
throw new GameException($result['description'], 0);
}
}
/**
* 获取玩家ID
* @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|Exception
*/
public function createPlayer(array $data = [])
{
$params = [
'secureLogin' => $this->secureLogin,
'externalPlayerId' => $data['uuid'],
'currency' => 'MYR',
];
$signature = $this->createSign($params);
$params['hash'] = $signature;
$result = doFormCurl($this->createUrl('/IntegrationService/v3/http/CasinoGameAPI/player/account/create/'), $params);
if ($result['error'] != 0 || empty($result['playerId'])) {
Log::error($result['description'], ['res' => $result]);
throw new GameException($result['description'], 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 $result;
}
/**
* 获取玩家
* @return false
* @throws Exception
*/
public function getPlayer(): bool
{
return false;
}
/**
* 玩家进入游戏
* @param array $data
* @return string
* @throws GameException|\think\Exception
*/
public function login(array $data = []): string
{
$params = [
'secureLogin' => $this->secureLogin,
'externalPlayerId' => $this->loginId,
'gameId' => $data['gameCode'],
'language' => 'en',
];
$signature = $this->createSign($params);
$params['hash'] = $signature;
$result = doFormCurl($this->createUrl('/IntegrationService/v3/http/CasinoGameAPI/game/start/'), $params);
if ($result['error'] == 0 && !empty($result['gameURL'])) {
$link = $result['gameURL'];
}else{
throw new GameException($result['description'], 0);
}
return $link;
}
/**
* 获取玩家游戏平台余额
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getBalance()
{
$params = [
'secureLogin' => $this->secureLogin,
'externalPlayerId' => $this->loginId,
];
$signature = $this->createSign($params);
$params['hash'] = $signature;
$result = doFormCurl($this->createUrl('/IntegrationService/v3/http/CasinoGameAPI/balance/current/'), $params);
if ($result['error'] != 0) {
throw new GameException('Pragmatic System Error,Please contact the administrator', 0);
}
return $result['balance'];
}
/**
* 玩家钱包转入游戏平台
* @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()
{
$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 = [
'secureLogin' => $this->secureLogin,
'externalPlayerId' => $this->loginId,
'externalTransactionId' => createOrderNo(),
'amount' => $amount,
];
$signature = $this->createSign($params);
$params['hash'] = $signature;
$result = doFormCurl($this->createUrl('/IntegrationService/v3/http/CasinoGameAPI/balance/transfer/'), $params);
if ($result['error'] != 0) {
throw new GameException($result['description'], 0);
}
// 记录玩家钱包转出转入记录
$this->createWalletTransfer($type, $amount, $reward, $result['transactionId'] ?? '');
return $result;
}
/**
* 转账记录
* @param $startTime
* @return array|mixed|null
* @throws GameException
* @throws \think\Exception
*/
protected function transferTransactions($startTime)
{
$params = [
'secureLogin' => $this->secureLogin,
//'timepoint' => $startTime ?? round(microtime(true) * 1000),
];
$signature = $this->createSign($params);
$params['hash'] = $signature;
$result = doFormCurl($this->createUrl('/IntegrationService/v3/http/CasinoGameAPI/balance/transfer/transactions/'), $params);
if ($result['error'] != 0) {
throw new GameException($result['description'], 0);
}
return $result;
}
/**
* 踢出游戏
* @return array|mixed|Response
* @throws GameException|Exception
*/
public function terminateSession()
{
$params = [
'secureLogin' => $this->secureLogin,
'externalPlayerId' => $this->loginId,
];
$signature = $this->createSign($params);
$params['hash'] = $signature;
$result = doFormCurl($this->createUrl('/IntegrationService/v3/http/CasinoGameAPI/game/session/terminate'), $params);
if ($result['error'] == 0) {
throw new GameException($result['description'], 0);
}
return $result;
}
/**
* 重播链接
* @return array|mixed|Response
* @throws GameException|Exception
*/
public function replayLink($roundId)
{
$params = [
'secureLogin' => $this->secureLogin,
'externalPlayerId' => $this->loginId,
'roundId' => $roundId,
];
$signature = $this->createSign($params);
$params['hash'] = $signature;
$result = doFormCurl($this->createUrl('/IntegrationService/v3/http/ReplayAPI/getSharedLink'), $params);
if ($result['error'] == 0) {
throw new GameException($result['description'], 0);
}
return $result;
}
/**
* 查询游戏纪录
* @return array
*/
public function getGameRecordList(): array
{
$params = [
'login' => $this->secureLogin,
'password' => $this->appSecret,
'timepoint' => round(microtime(true) * 1000) - 90000,
];
$query = http_build_query($params, '', '&');
$url = $this->createUrl('/IntegrationService/v3/DataFeeds/gamerounds/finished/?' . $query);
$response = Http::timeout(10)->get($url);
$result = $response->body();
return $this->parseCustomCsv($result);
}
/**
* CSV转数组
* @param $input
* @return array
*/
public function parseCustomCsv($input): array
{
$lines = explode("\n", trim($input)); // 分割为行数组
// 解析timepoint
$timepoint = (int) substr($lines[0], strpos($lines[0], '=') + 1);
array_shift($lines); // 移除timepoint行
// 处理CSV部分
$header = str_getcsv(array_shift($lines)); // 获取标题行
$result = [
'timepoint' => $timepoint,
'data' => []
];
foreach ($lines as $line) {
$row = str_getcsv($line);
if (count($row) !== count($header)) continue; // 跳过列数不匹配的行
// 组合关联数组并转换数据类型
$entry = array_combine($header, array_map(function($value) {
if ($value === 'null') return null; // 转换null字符串
if (is_numeric($value)) { // 转换数字类型
return (strpos($value, '.') !== false) ? (float)$value : (int)$value;
}
return $value;
}, $row));
$result['data'][] = $entry;
}
return $result;
}
/**
* 查询玩家游戏记录
* @return array
*/
public function handleOrderHistories(): array
{
try {
$list = [];
$data = $this->getGameRecordList();
if (!empty($data['data'])) {
foreach ($data['data'] as $item) {
$list[] = [
'uuid' => $item['extPlayerID'],
'platform_id' => $this->platform->id,
'game_code' => $item['gameID'],
'bet' => $item['bet'],
'win' => $item['win'],
'order_no' => $item['playSessionID'],
'original_data' => json_encode($item,JSON_UNESCAPED_UNICODE),
'platform_action_at' => date('Y-m-d H:i:s', strtotime($item['endDate'])),
'game_type' => 'vs',
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
];
}
}
} catch (Exception $e) {
return [];
}
return $list;
}
}