初始化

This commit is contained in:
2026-03-02 13:44:38 +08:00
commit 05b785083c
677 changed files with 58662 additions and 0 deletions

View File

@@ -0,0 +1,16 @@
<?php
namespace app\service;
/**
* 发送短信接口
*/
interface BaseSmsServices
{
/**
* 发送短信
* @param string $phone
* @param int $type
* @return mixed
*/
public function send(string $phone, int $type);
}

158
app/service/DrawService.php Normal file
View File

@@ -0,0 +1,158 @@
<?php
// 抽奖核心服务
namespace app\service;
use addons\webman\model\DrawRecord;
use addons\webman\model\Game;
use addons\webman\model\Prize;
use Exception;
use support\Db;
use support\Log;
class DrawService
{
/**
* 执行抽奖
* @param $player
* @param int $gameId
* @param int $departmentId
* @param string $ip 用户IP
* @return array 抽奖结果
*/
public function execute( $player, int $gameId, int $departmentId, string $ip): array
{
try {
DB::beginTransaction();
// 1. 查询有效奖品(加行锁防止并发问题)
$prizes = Prize::query()->where('game_id', $gameId)
->where('department_id', $departmentId)
->where('status', 1)
->where('total_remaining', '>', 0)
->where('daily_remaining', '>', 0)
->lockForUpdate()
->get()
->toArray();
if (empty($prizes)) {
DB::rollBack();
return [
'success' => false,
'message' => '当前游戏不可用'
];
}
$game = Game::query()->select('id', 'game_type', 'consume')->where('id', $gameId)->first()->toArray();
// 2. 计算中奖结果
$result = $this->calculateWinning($player,$prizes, $game['consume']);
$prizeId = $result['prize_id'];
$prizeName = $result['prize_name'];
$prizeType = $result['prize_type'];
$game['department_id'] = $departmentId;
// 3. 记录抽奖信息
$this->createRecord($player->id, $result, $game, $ip);
if ($result['prize_type'] == 3) {
$message = '很遗憾,未中奖';
} else {
$message = '恭喜获得' . $prizeName;
}
DB::commit();
return [
'prize_id' => $prizeId,
'prize_name' => $prizeName,
'prize_type' => $prizeType,
'consume' => $game['consume'],
'message' => $message
];
} catch (Exception $e) {
DB::rollBack();
Log::error("抽奖失败:{$e->getMessage()}", [
'user_id' => $player->id,
'trace' => $e->getTraceAsString()
]);
return [
'success' => false,
'message' => '抽奖过程异常,请稍后再试'
];
}
}
/**
* 计算中奖结果
* @param array $prizes 有效奖品列表
* @return array 中奖信息
* @throws Exception
*/
private function calculateWinning($player, array $prizes, $consume): array
{
// 计算总概率权重
$totalProb = array_sum(array_column($prizes, 'probability'));
if ($totalProb <= 0) {
return ['prize_id' => null, 'type' => Prize::PRIZE_TYPE_LOSE, 'prize_name' => '未中奖', 'prize_pic' => null];
}
$player->wallet->decrement('money', $consume);
// 生成随机数0到总权重之间
$random = mt_rand(1, $totalProb * 10000) / 10000; // 提高精度
$currentSum = 0;
foreach ($prizes as $prize) {
$currentSum += $prize['probability'];
if ($random <= $currentSum) {
// 检查并扣减库存
$this->deductStock($prize['id']);
return [
'prize_id' => $prize['id'],
'prize_type' => $prize['type'],
'prize_name' => $prize['name'],
'prize_pic' => $prize['pic']
];
}
}
return ['prize_id' => null, 'type' => Prize::PRIZE_TYPE_LOSE, 'prize_name' => '未中奖', 'prize_pic' => null];
}
/**
* 扣减库存
* @param int $prizeId 奖品ID
* @throws Exception
*/
private function deductStock(int $prizeId): void
{
$prize = Prize::query()->findOrFail($prizeId);
// 再次检查库存(防止并发超卖)
if ($prize->total_remaining <= 0 || $prize->daily_remaining <= 0) {
throw new \Exception("奖品库存不足");
}
$prize->decrement('total_remaining');
$prize->decrement('daily_remaining');
$prize->save();
}
/**
* 创建抽奖记录
* @param int $userId 用户ID
* @param array|null $prize 奖品
* @param string $ip IP地址
*/
private function createRecord(int $userId, ?array $prize, array $game, string $ip): void
{
DrawRecord::query()->create([
'uid' => $userId,
'prize_id' => $prize['prize_id'],
'prize_type' => $prize['prize_type'],
'prize_name' => $prize['prize_name'],
'prize_pic' => $prize['prize_pic'],
'game_id' => $game['id'],
'consume' => $game['consume'],
'game_type' => $game['game_type'],
'department_id' => $game['department_id'],
'draw_time' => date('Y-m-d H:i:s'),
'ip' => $ip
]);
}
}

View File

@@ -0,0 +1,103 @@
<?php
// 日本手机号发送短信
namespace app\service;
use addons\webman\model\PhoneSmsLog;
use Exception;
use Illuminate\Support\Str;
use support\Cache;
use WebmanTech\LaravelHttpClient\Facades\Http;
class JpSmsServicesServices implements BaseSmsServices
{
// 应用key
private $appKey = '';
// 应用代码
private $appcode = '';
// 应用秘钥
private $appSecret = '';
// domain
private $domain = '';
// 过期时间
public $expireTime = 120;
public function __construct()
{
$this->domain = config('jp-sms.domain');
$this->appKey = config('jp-sms.app_key');
$this->appcode = config('jp-sms.appcode');
$this->appSecret = config('jp-sms.app_secret');
}
/**
* 执行请求
* @param string $api 接口
* @param array $params 参数
* @return mixed
*/
public function doCurl(string $api, array $params)
{
$result = Http::timeout(10)->get($this->domain . $api, $params);
return json_decode($result, true);
}
/**
* 日本供应商短信发送
* @param $phone
* @param $type
* @param int $playerId
* @return bool
* @throws Exception
*/
public function send($phone, $type, int $playerId = 0): bool
{
$env = config('app.env');
$api = config('jp-sms.batchSend');
$code = ($env == 'pro' ? random_int(10000, 99999) : config('sms.default_code'));
$key = setSmsKey($phone, $type);
$uid = gen_uuid();
$msg = Str::replaceFirst('{code}', $code, getContent($type, 'jp'));
//驗證通過
if ($env == 'pro') {
$result = $this->doCurl($api, [
'appKey' => $this->appKey,
'appcode' => $this->appcode,
'appSecret' => $this->appSecret,
'uid' => $uid,
'phone' => PhoneSmsLog::COUNTRY_CODE_JP . $phone,
'msg' => $msg
]);
} else {
$result = $env;
}
$phoneSmsLog = new PhoneSmsLog();
$phoneSmsLog->player_id = $playerId;
$phoneSmsLog->code = $code;
$phoneSmsLog->phone = PhoneSmsLog::COUNTRY_CODE_JP . $phone;
$phoneSmsLog->uid = $uid;
$phoneSmsLog->send_times = 1;
$phoneSmsLog->type = $type;
$phoneSmsLog->expire_time = date("Y-m-d H:i:s", time() + $this->expireTime);
$phoneSmsLog->response = $result ? json_encode($result) : '';
if ($env == 'pro') {
if (isset($result) && $result['code'] == '00000') {
if (isset($result['result']) && $result['result'][0]['status'] == '00000') {
Cache::set($key, $code, $this->expireTime);
$phoneSmsLog->status = 1;
$phoneSmsLog->save();
return true;
}
}
} else {
Cache::set($key, $code, $this->expireTime);
$phoneSmsLog->status = 1;
$phoneSmsLog->save();
return true;
}
$phoneSmsLog->status = 0;
$phoneSmsLog->save();
throw new Exception(trans('phone_code_send_failed', [], 'message'));
}
}

View File

@@ -0,0 +1,147 @@
<?php
// 日本手机号发送短信
namespace app\service;
use app\exception\GameException;
use support\Log;
use WebmanTech\LaravelHttpClient\Facades\Http;
class OnePayServices
{
// 应用key
private $merchantId = '';
// 应用代码
private $key = '';
// 应用秘钥
private $domain = '';
// domain
private $notifyUrl = '';
private $payoutNotifyUrl = '';
private $returnUrl = '';
// 过期时间
public $expireTime = 180;
public function __construct()
{
$this->merchantId = config('one_pay.merchantId');
$this->key = config('one_pay.key');
$this->api_key = config('one_pay.api_key');
$this->domain = config('one_pay.domain');
$this->notifyUrl = config('one_pay.notifyUrl');
$this->payoutNotifyUrl = config('one_pay.payoutNotifyUrl');
$this->returnUrl = config('one_pay.returnUrl');
}
/**
* 执行请求
* @param string $api 接口
* @param array $params 参数
*/
public function doCurl(string $api, array $params): array
{
$result = Http::timeout(10)->asForm()->post($this->domain.$api, $params);
Log::channel('pay_log')->info('onepay:'.$api,json_decode($result, true));
return json_decode($result, true);
}
/**
* 创建签名
* @throws GameException
*/
public function getAuth(): string
{
$data = [
'username' => $this->merchantId,
'api_key' => $this->api_key,
];
$result = $this->doCurl('merchant/auth',$data);
if ($result['status'] == 'true') {
return $result['auth'];
} else {
throw new GameException($result['message'], 0);
}
}
/**
* 创建签名
* @param array $params 参数
*/
public function calculateSignature(array $params): string
{
ksort($params);
$signature_string = '';
foreach ($params as $key => $value) {
$signature_string .= $key . ':' . $value . '&';
}
$signature_string .= 'key:' . $this->key;
return strtoupper(md5($signature_string));
}
/**
* 验证返回签名
* @param array $params 参数
*/
public function verifySign(array $params): string
{
return md5($this->key.$params['order_id']);
}
/**
* 存款
* @param array $params 参数
* @throws GameException
*/
public function deposit(array $params): array
{
$data = [
'username' => $params['uuid'],
'auth' => $this->getAuth(),
'amount' => $params['amount'],
'currency' => 'MYR',
'orderid' => $params['orderNo'],
'email' => $params['email'],
'phone_number' => $params['phone'],
'redirect_url' => $this->returnUrl.'?orderNo='.$params['orderNo'],
'pay_method' => $params['paymentCode'],
'callback_url' => $this->notifyUrl,
];
if ($data['pay_method'] == 'online_banking') {
$data['bank_id'] = $params['bank_id'];
}
return $this->doCurl('merchant/generate_orders',$data);
}
/**
* 代付
* @param array $params 参数
* @throws GameException
*/
public function payout(array $params): array
{
$data = [
'auth' => $this->getAuth(),
'amount' => $params['amount'],
'currency' => 'MYR',
'orderid' => $params['orderNo'],
'bank_id' => $params['bankCode'],
'holder_name' => $params['bankAccountName'],
'account_no' => $params['bankAccountNo'],
'callback_url' => $this->payoutNotifyUrl,
];
return $this->doCurl('merchant/withdraw_orders',$data);
}
/**
* 订单查询
* @param array $params 参数
*/
public function query(array $params): array
{
$data = [
'username' => $this->merchantId,
'id' => $params['orderNo'],
];
return $this->doCurl('merchant/check_status',$data);
}
}

View File

@@ -0,0 +1,130 @@
<?php
// 日本手机号发送短信
namespace app\service;
use support\Log;
use WebmanTech\LaravelHttpClient\Facades\Http;
class SePayServices
{
// 应用key
private $merchantId = '';
// 应用代码
private $key = '';
// 应用秘钥
private $domain = '';
// domain
private $notifyUrl = '';
private $payoutNotifyUrl = '';
private $returnUrl = '';
// 过期时间
public $expireTime = 180;
public function __construct()
{
$this->merchantId = config('se-pay.merchantId');
$this->key = config('se-pay.MD5');
$this->domain = config('se-pay.domain');
$this->notifyUrl = config('se-pay.notifyUrl');
$this->payoutNotifyUrl = config('se-pay.payoutNotifyUrl');
$this->returnUrl = config('se-pay.returnUrl');
}
/**
* 执行请求
* @param string $api 接口
* @param array $params 参数
*/
public function doCurl(string $api, array $params): array
{
$result = Http::timeout(10)->asForm()->post($this->domain.$api, $params);
Log::channel('pay_log')->info('sepay:'.$api,json_decode($result, true));
return json_decode($result, true);
}
/**
* 创建签名
* @param array $params 参数
*/
public function calculateSignature(array $params): string
{
ksort($params);
$signature_string = '';
foreach ($params as $key => $value) {
$signature_string .= $key . ':' . $value . '&';
}
$signature_string .= 'key:' . $this->key;
return strtoupper(md5($signature_string));
}
/**
* 验证返回签名
* @param array $params 参数
*/
public function verifySign(array $params): string
{
ksort($params);
unset($params['signMsg']);
$signature_string = '';
foreach ($params as $key => $value) {
$signature_string .= $key . ':' . $value . '&';
}
$signature_string .= 'key:' . $this->key;
return strtoupper(md5($signature_string));
}
/**
* 存款
* @param array $params 参数
*/
public function deposit(array $params): array
{
$params['notifyUrl'] = $this->notifyUrl;
$params['returnUrl'] = $this->returnUrl.'?orderNo='.$params['orderNo'];
$request_str = base64_encode(json_encode($params));
$data = [
'merchantNo' => $this->merchantId,
'request' => $request_str,
'version' => '1.0',
];
$signature = $this->calculateSignature($data);
$data['signMsg'] = $signature;
return $this->doCurl('qrh5',$data);
}
/**
* 代付
* @param array $params 参数
*/
public function payout(array $params): array
{
$params['notifyUrl'] = $this->payoutNotifyUrl;
$request_str = base64_encode(json_encode($params));
$data = [
'merchantNo' => $this->merchantId,
'request' => $request_str,
'version' => '1.0',
];
$signature = $this->calculateSignature($data);
$data['signMsg'] = $signature;
return $this->doCurl('payout',$data);
}
/**
* 订单查询
* @param array $params 参数
*/
public function query(array $params): array
{
$request_str = base64_encode(json_encode($params));
$data = [
'merchantNo' => $this->merchantId,
'request' => $request_str,
'version' => '1.0',
];
$signature = $this->calculateSignature($data);
$data['signMsg'] = $signature;
return $this->doCurl('query',$data);
}
}

View File

@@ -0,0 +1,96 @@
<?php
// 日本手机号发送短信
namespace app\service;
use app\exception\GameException;
use support\Log;
use WebmanTech\LaravelHttpClient\Facades\Http;
class SklPayServices
{
// 应用key
private $merchantId = '';
// 应用代码
private $api_key = '';
// 应用秘钥
private $domain = '';
// domain
private $notifyUrl = '';
private $payoutNotifyUrl = '';
private $returnUrl = '';
// 过期时间
public $expireTime = 180;
/**
* @var array|mixed|null
*/
public function __construct()
{
$this->merchantId = config('skl_pay.merchantId');
$this->api_key = config('skl_pay.api_key');
$this->domain = config('skl_pay.domain');
$this->notifyUrl = config('skl_pay.notifyUrl');
$this->payoutNotifyUrl = config('skl_pay.payoutNotifyUrl');
$this->returnUrl = config('skl_pay.returnUrl');
}
/**
* 执行请求
* @param string $api 接口
* @param array $params 参数
*/
public function doCurl(string $api, array $params): array
{
$result = Http::timeout(10)->asJson()->post($this->domain.$api, $params);
Log::channel('pay_log')->info('sklpay:'.$api,json_decode($result, true));
return json_decode($result, true);
}
/**
* 存款
* @param array $params 参数
* @throws GameException
*/
public function deposit(array $params): array
{
$data = [
'api_token' => $this->api_key,
'amount' => $params['amount'],
'gateway' => $params['paymentCode'],
'pusername' => $params['name'],
'invoice_no' => $params['orderNo'],
];
return $this->doCurl('/api/transaction/init',$data);
}
/**
* 代付
* @param array $params 参数
* @throws GameException
*/
public function payout(array $params): array
{
$data = [
'api_token' => $this->api_key,
'amount' => $params['amount'],
'to_bank' => $params['bankCode'],
'to_bank_account_no' => $params['bankAccountNo'],
'account_holder' => $params['bankAccountName'],
'invoice_no' => $params['orderNo'],
];
return $this->doCurl('/api/transfer_out/init',$data);
}
/**
* 订单查询
* @param array $params 参数
*/
public function query(array $params): array
{
$data = [
'transaction_id' => $params['orderNo'],
];
return $this->doCurl('/api/transaction/get_status',$data);
}
}

View File

@@ -0,0 +1,41 @@
<?php
namespace app\service;
use addons\webman\model\PhoneSmsLog;
use Exception;
/**
* 短信服务
*/
class SmsServicesServices
{
/**
* @param int $countryCode
* @param string $phone
* @param int $type
* @param int $playerId
* @param string $name
* @return bool
* @throws Exception
*/
public static function sendSms(int $countryCode, string $phone, int $type, int $playerId = 0, string $name = ''): bool
{
$openCountryCode = config('sms.open_country_code');
if (!in_array($countryCode, $openCountryCode)) {
$openCountryName = '';
foreach ($openCountryCode as $item) {
$openCountryName .= ',' . trans('country_code_name.' . $item, [], 'message');
}
throw new Exception(trans('currently_open_countries_and_regions', ['{openCountryCode}', $openCountryName], 'message'));
}
switch ($countryCode) {
case PhoneSmsLog::COUNTRY_CODE_TW:
return (new TwSmsServicesServices())->send($phone, $type, $playerId, $name);
case PhoneSmsLog::COUNTRY_CODE_JP:
return (new JpSmsServicesServices())->send($phone, $type, $playerId);
default:
throw new Exception(trans('country_code_error', [], 'message'));
}
}
}

View File

@@ -0,0 +1,121 @@
<?php
// 台湾手机号发送短信
namespace app\service;
use addons\webman\model\PhoneSmsLog;
use Exception;
use Illuminate\Support\Str;
use support\Cache;
use support\Log;
use WebmanTech\LaravelHttpClient\Facades\Http;
class TwSmsServicesServices implements BaseSmsServices
{
// 使⽤者帳號
private $username = '';
// 使⽤者密碼
private $password = '';
// domain
private $domain = '';
// 过期时间
public $expireTime = 300;
public function __construct()
{
$this->domain = config('tw-sms.domain');
$this->username = config('tw-sms.username');
$this->password = config('tw-sms.password');
}
/**
* 执行请求
* @param string $api 接口
* @param array $params 参数
* @return mixed
* @throws Exception
*/
public function doCurl(string $api, array $params)
{
$result = Http::timeout(10)->post($this->domain . $api . '?' . http_build_query($params));
if ($result->ok()) {
$arr = preg_split('/[;\r\n]+/s', $result->body());
$data = [];
foreach ($arr as $item) {
$arr = explode('=', $item);
if (!empty($arr) && isset($arr[0]) && isset($arr[1])) {
$data[$arr[0]] = $arr[1];
}
}
return $data;
}
throw new Exception(trans('phone_code_send_failed', [], 'message'));
}
/**
* 日本供应商短信发送
* @param $phone
* @param $type
* @param int $playerId
* @param string $name
* @return bool
* @throws Exception
*/
public function send($phone, $type, int $playerId = 0, string $name = ''): bool
{
$env = config('app.env');
$api = config('tw-sms.sm_send_api');
$code = ($env == 'pro' ? random_int(10000, 99999) : config('sms.default_code'));
$key = setSmsKey($phone, $type);
$uid = gen_uuid();
$msg = Str::replaceFirst('{code}', $code, getContent($type, 'tw'));
//驗證通過
if ($env == 'pro') {
$result = $this->doCurl($api, [
'username' => $this->username,
'password' => $this->password,
'dstaddr' => $phone,
'destname' => $name,
'dlvtime' => '',
'vldtime' => $this->expireTime,
'smbody' => $msg,
'CharsetURL' => 'UTF-8',
]);
Log::info('短信发送结果', [$result]);
} else {
$result = $env;
}
$phoneSmsLog = new PhoneSmsLog();
$phoneSmsLog->player_id = $playerId;
$phoneSmsLog->code = $code;
$phoneSmsLog->phone = PhoneSmsLog::COUNTRY_CODE_TW . $phone;
$phoneSmsLog->uid = $uid;
$phoneSmsLog->send_times = 1;
$phoneSmsLog->type = $type;
$phoneSmsLog->expire_time = date("Y-m-d H:i:s", time() + $this->expireTime);
$phoneSmsLog->response = $result ? json_encode($result) : '';
if ($env == 'pro') {
if (isset($result['statuscode'])) {
/* 0 預約傳送中1 已送達業者2 已送達業者4 已送達⼿機5 內容有錯誤6 ⾨號有錯誤7 簡訊已停⽤8 逾時無送達9 預約已取消*/
switch ($result['statuscode']) {
case '0':
case '1':
case '2':
case '4':
Cache::set($key, $code, $this->expireTime);
$phoneSmsLog->status = 1;
$phoneSmsLog->save();
return true;
}
}
} else {
Cache::set($key, $code, $this->expireTime);
$phoneSmsLog->status = 1;
$phoneSmsLog->save();
return true;
}
$phoneSmsLog->status = 0;
$phoneSmsLog->save();
throw new Exception(trans('phone_code_send_failed', [], 'message'));
}
}

View File

@@ -0,0 +1,759 @@
<?php
namespace app\service\game;
use addons\webman\model\Game;
use addons\webman\model\GamePlatform;
use addons\webman\model\GameType;
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 Illuminate\Support\Str;
use support\Log;
use support\Response;
class BigGamingServiceInterface extends GameServiceFactory implements GameServiceInterface
{
public $method = 'POST';
private $apiDomain;
private $domain;
private $appId;
private $appSecret;
private $loginId;
private $sn;
private $adminUser;
private $secretCode;
public $gameType = [
'2' => 'Casino',
'5' => 'Fishing',
'8' => 'Bingo',
'1' => 'Slot',
];
public $localGameType = [
'2' => '2',//赌场
'4' => '4',//捕鱼
'5' => '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->appId = $config['app_id'];
$this->apiDomain = $config['api_domain'];
$this->domain = $config['domain'];
$this->appSecret = $config['app_secret'];
$this->sn = $config['sn'];
$this->adminUser = $config['admin_user'];
$this->secretCode = base64_encode(sha1($config['admin_pass'], true));
$this->platform = GamePlatform::query()->where('name', $type)->first();
if (!empty($player)) {
$this->player = $player;
$this->getLoginId();
}
}
/**
* 生成请求url
* @return string
*/
public function createUrl(): string
{
return $this->apiDomain;
}
//生成签名
public function createSign($params): string
{
$str = '';
foreach ($params as $v) {
$str .= $v;
}
return md5($str);
}
/**
* 生成请求数据
* @param $postData
* @param $method
* @return array
*/
public function buildParams($postData, $method): array
{
return array(
"jsonrpc" => "2.0",
"method" => $method,
"params" => $postData,
"id" => $this->player->uuid ?? uniqid()
);
}
/**
* 创建代理账号
* @throws GameException|\think\Exception
*/
public function createAgent()
{
$params = [
'random' => $this->player->uuid ?? uniqid(),
'sn' => $this->sn,
'loginId' => 'testagent123',
'secretKey' => $this->appSecret,
];
$params['sign'] = $this->createSign($params);
unset($params['secretKey']);
$params['password'] = '123456ss';
$postData = $this->buildParams($params, 'open.agent.create');
$result = doCurl($this->apiDomain,$postData);
if (!empty($result['result']) && empty($result['error'])){
return $result;
}else{
throw new GameException($result['error']['message'], 0);
}
}
/**
* 更新游戏列表
* @return false
*/
public function getSimpleGameList(): bool
{
return false;
}
/**
* 获取玩家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 = [
'random' => $data['uuid'],
'sn' => $this->sn,
'secretCode' => $this->secretCode,
];
$params['digest'] = $this->createSign($params);
$params['loginId'] = $data['uuid'];
$params['nickname'] = $data['name'];
$params['agentLoginId'] = $this->adminUser;
unset($params['secretCode']);
$postData = $this->buildParams($params, 'open.user.create');
$result = doCurl($this->apiDomain,$postData);
if (!empty($result['result']) && empty($result['error'])){
$playerGamePlatform = new PlayerGamePlatform();
$playerGamePlatform->player_id = $this->player->id;
$playerGamePlatform->platform_id = $this->platform->id;
$playerGamePlatform->player_name = $data['name'];
$playerGamePlatform->player_code = $result['result']['loginId'];
$playerGamePlatform->save();
$this->loginId = $playerGamePlatform->player_code;
return $result;
}else{
throw new GameException($result['error']['message'], 0);
}
}
/**
* 获取玩家信息
* @return array|mixed|Response
* @throws GameException|Exception
*/
public function getPlayer()
{
$params = [
'random' => $this->player->uuid ?? uniqid(),
'sn' => $this->sn,
'loginId' => $this->loginId,
'secretCode' => $this->secretCode,
];
$params['digest'] = $this->createSign($params);
unset($params['secretCode']);
$postData = $this->buildParams($params, 'open.user.get');
$result = doCurl($this->apiDomain,$postData);
if (!empty($result['result']) && empty($result['error'])){
return $result;
}else{
throw new GameException($result['error']['message'], 0);
}
}
/**
* 玩家进入游戏
* @param array $data
* @return string
* @throws GameException|\think\Exception
*/
public function login(array $data = []): string
{
$params = [
'random' => $this->player->uuid ?? uniqid(),
'sn' => $this->sn,
'loginId' => $this->loginId,
'secretCode' => $this->secretCode,
];
$params['digest'] = $this->createSign($params);
$params['isMobileUrl'] = 1;
unset($params['secretCode']);
$postData = $this->buildParams($params, 'open.video.game.url');
$result = doCurl($this->apiDomain,$postData);
if (!empty($result['error'])) {
throw new GameException($result['error']['message'], 0);
}
return $result['result'];
}
/**
* 获取玩家游戏平台余额
* @throws GameException|\think\Exception
*/
public function getBalance()
{
$params = [
'random' => $this->player->uuid ?? uniqid(),
'sn' => $this->sn,
'loginId' => $this->loginId,
'secretCode' => $this->secretCode,
];
$params['digest'] = $this->createSign($params);
unset($params['secretCode']);
$postData = $this->buildParams($params, 'open.balance.get');
$result = doCurl($this->apiDomain,$postData);
if (empty($result['error'])){
return $result['result'];
}else{
throw new GameException('Big Gaming System Error,Please contact the administrator', 0);
}
}
/**
* 玩家钱包转入游戏平台
* @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();
return $this->setBalanceTransfer(PlayerWalletTransfer::TYPE_IN, -$balance);
}
/**
* 轉帳進出額度
* @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) {
// 记录玩家钱包转出转入记录
$this->createWalletTransfer($type, $amount, $reward);
return true;
}
$params = [
'random' => $this->player->uuid ?? uniqid(),
'sn' => $this->sn,
'loginId' => $this->loginId,
'amount' => $amount,
'secretCode' => $this->secretCode,
];
$params['digest'] = $this->createSign($params);
unset($params['secretCode']);
$postData = $this->buildParams($params, 'open.balance.transfer');
$result = doCurl($this->apiDomain,$postData);
if (!empty($result['error'])) {
throw new GameException($result['error']['message'], 0);
}
// 记录玩家钱包转出转入记录
$this->createWalletTransfer($type, $amount, $reward);
return $result;
}
/**
* 查询额度转移纪录
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getTransferList(string $startTime = '', string $endTime = '', int $page = 1, int $pageSize = 15)
{
$params = [
'random' => $this->player->uuid ?? uniqid(),
'sn' => $this->sn,
'secretKey' => $this->appSecret,
];
$params['sign'] = $this->createSign($params);
$params['loginId'] = $this->loginId;
$params['startTime'] = $startTime;
$params['endTime'] = $endTime;
$params['timeZone'] = 1;
unset($params['secretKey']);
$postData = $this->buildParams($params, 'open.balance.transfer.query');
$result = doCurl($this->apiDomain,$postData);
if (!empty($result['error'])) {
throw new GameException($result['error']['message'], 0);
}
return $result;
}
/**
* 查询注单统计结果
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getOrderSum(string $startTime = '', string $endTime = '', int $page = 1, int $pageSize = 500)
{
$params = [
'random' => $this->player->uuid ?? uniqid(),
'sn' => $this->sn,
'secretKey' => $this->appSecret,
];
$params['sign'] = $this->createSign($params);
$params['loginIds'] = [$this->loginId];
$params['startTime'] = $startTime;
$params['endTime'] = $endTime;
unset($params['secretKey']);
$postData = $this->buildParams($params, 'open.sn.order.sum');
$result = doCurl($this->apiDomain,$postData);
if (!empty($result['error'])) {
throw new GameException($result['error']['message'], 0);
}
return $result;
}
/**
* 按玩家统计注单
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getUserOrderSum(string $startTime = '', string $endTime = '')
{
$params = [
'random' => $this->player->uuid ?? uniqid(),
'sn' => $this->sn,
'secretKey' => $this->appSecret,
];
$params['sign'] = $this->createSign($params);
$params['startTime'] = $startTime;
$params['endTime'] = $endTime;
unset($params['secretKey']);
$postData = $this->buildParams($params, 'open.user.order.sum');
$result = doCurl($this->apiDomain,$postData);
if (!empty($result['error'])) {
throw new GameException($result['error']['message'], 0);
}
return $result['result'];
}
/**
* 查询玩家游戏记录
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getUserGameRecord(string $startTime = '', string $endTime = '')
{
$params = [
'random' => $this->player->uuid ?? uniqid(),
'sn' => $this->sn,
'loginId' => $this->loginId,
'secretKey' => $this->appSecret,
];
$params['sign'] = $this->createSign($params);
$params['startTime'] = $startTime;
$params['endTime'] = $endTime;
unset($params['secretKey']);
$postData = $this->buildParams($params, 'open.video.round.query');
$result = doCurl($this->apiDomain,$postData);
if (!empty($result['error'])) {
throw new GameException($result['error']['message'], 0);
}
return $result['result'];
}
/**
* 查询玩家游戏记录
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function handleOrderHistories()
{
try {
$page = 1;
$list = [];
$timezone = new DateTimeZone('America/New_York');
$start = new DateTime('-6 minutes', $timezone);
$end = new DateTime('-5 minutes', $timezone);
$startTime = $start->format('Y-m-d H:i:s');
$endTime = $end->format('Y-m-d H:i:s');
$data = $this->getAgentOrderRecord($startTime, $endTime, $page);
$fishData = $this->getUserFishOrderRecord($startTime, $endTime, $page);
if (!empty($data['result'])) {
$total = $data['result']['total'] ?? 0;
if ($total > 0) {
$pageSize = 200;
if (!empty($data['result']['items'])) {
foreach ($data['result']['items'] as $item) {
$list[] = [
'uuid' => $item['loginId'],
'platform_id' => $this->platform->id,
'game_code' => $item['playNameEn'],
'bet' => abs($item['bAmount']),
'win' => $item['aAmount'],
'order_no' => $item['orderId'],
'original_data' => json_encode($item,JSON_UNESCAPED_UNICODE),
'platform_action_at' => $item['lastUpdateTime'],
'game_type' => 5,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
];
}
}
if ($total > $pageSize) {
$totalPages = ceil($total / $pageSize);
for ($page = 2; $page <= $totalPages; $page++) {
$nextData = $this->getAgentOrderRecord($startTime,$endTime,$page);
if (!empty($nextData['result']['items'])) {
foreach ($nextData['result']['items'] as $item) {
$list[] = [
'uuid' => $item['loginId'],
'platform_id' => $this->platform->id,
'game_code' => $item['playNameEn'],
'bet' => abs($item['bAmount']),
'win' => $item['aAmount'],
'order_no' => $item['orderId'],
'original_data' => json_encode($item,JSON_UNESCAPED_UNICODE),
'platform_action_at' => $item['lastUpdateTime'],
'game_type' => 5,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
];
}
}
}
}
}
}
if (!empty($fishData['result'])) {
$fishTotal = $fishData['result']['total'] ?? 0;
if ($fishTotal > 0) {
$pageSize = 200;
if (!empty($fishData['result']['items'])) {
foreach ($fishData['result']['items'] as $item) {
$list[] = [
'uuid' => $item['loginId'],
'platform_id' => $this->platform->id,
'game_code' => $item['gameType'],
'bet' => abs($item['betAmount']),
'win' => $item['calcAmount'],
'order_no' => $item['betId'],
'original_data' => json_encode($item, JSON_UNESCAPED_UNICODE),
'platform_action_at' => $item['orderTimeBj'],
'game_type' => 4,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
];
}
}
if ($fishTotal > $pageSize) {
$totalPages = ceil($fishTotal / $pageSize);
for ($page = 2; $page <= $totalPages; $page++) {
$nextFishData = $this->getUserFishOrderRecord($startTime,$endTime,$page);
if (!empty($nextFishData['result']['items'])) {
foreach ($nextFishData['result']['items'] as $item) {
$list[] = [
'uuid' => $item['loginId'],
'platform_id' => $this->platform->id,
'game_code' => $item['gameType'],
'bet' => abs($item['betAmount']),
'win' => $item['calcAmount'],
'order_no' => $item['betId'],
'original_data' => json_encode($item, JSON_UNESCAPED_UNICODE),
'platform_action_at' => $item['orderTimeBj'],
'game_type' => 4,
'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|mixed|Response
* @throws GameException|\think\Exception
*/
public function getUserOrderRecord(string $startTime = '', string $endTime = '', $page = 1)
{
$pageSize = 200;
$params = [
'random' => $this->player->uuid ?? uniqid(),
'sn' => $this->sn,
'secretKey' => $this->appSecret,
];
$params['sign'] = $this->createSign($params);
$params['startTime'] = $startTime;
$params['endTime'] = $endTime;
$params['pageIndex'] = $page;
$params['pageSize'] = $pageSize;
unset($params['secretKey']);
$postData = $this->buildParams($params, 'open.order.query');
$result = doCurl($this->apiDomain,$postData);
if (!empty($result['error'])) {
throw new GameException($result['error']['message'], 0);
}
return $result;
}
/**
* 查询玩家注单详情
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getUserOrderDetail($orderId)
{
$params = [
'random' => $this->player->uuid ?? uniqid(),
'sn' => $this->sn,
'orderId' => $orderId,
'reqTime' => date('Y-m-d H:i:s'),
'secretKey' => $this->appSecret,
];
$params['sign'] = $this->createSign($params);
unset($params['secretKey']);
$postData = $this->buildParams($params, 'open.sn.video.order.detail');
$result = doCurl($this->apiDomain,$postData);
if (!empty($result['error'])) {
throw new GameException($result['error']['message'], 0);
}
return $result['result'];
}
/**
* 查询玩家注单详情地址
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getUserOrderDetailUrl($orderId)
{
$params = [
'random' => $this->player->uuid ?? uniqid(),
'sn' => $this->sn,
'orderId' => $orderId,
'secretKey' => $this->appSecret,
];
$params['sign'] = $this->createSign($params);
unset($params['secretKey']);
$postData = $this->buildParams($params, 'open.sn.video.order.detail.url.get');
$result = doCurl($this->apiDomain,$postData);
if (!empty($result['error'])) {
throw new GameException($result['error']['message'], 0);
}
return $result['result'];
}
/**
* 查询玩家捕鱼注单
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getUserFishOrderRecord(string $startTime = '', string $endTime = '', $page = 1)
{
$pageSize = 200;
$params = [
'random' => $this->player->uuid ?? uniqid(),
'sn' => $this->sn,
'secretKey' => $this->appSecret,
];
$params['sign'] = $this->createSign($params);
$params['gameType'] = 1;
$params['agentLoginId'] = $this->adminUser;
$params['startTime'] = $startTime;
$params['endTime'] = $endTime;
$params['pageIndex'] = $page;
$params['pageSize'] = $pageSize;
unset($params['secretKey']);
$postData = $this->buildParams($params, 'open.order.bg.query');
$result = doCurl($this->apiDomain,$postData);
if (!empty($result['error'])) {
throw new GameException($result['error']['message'], 0);
}
return $result;
}
/**
* 查询代理注单
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getAgentOrderRecord(string $startTime = '', string $endTime = '', $page = 1)
{
$pageSize = 200;
$params = [
'random' => $this->player->uuid ?? uniqid(),
'sn' => $this->sn,
'secretCode' => $this->secretCode,
];
$params['digest'] = $this->createSign($params);
$params['agentLoginId'] = $this->adminUser;
$params['startTime'] = $startTime;
$params['endTime'] = $endTime;
$params['pageIndex'] = $page;
$params['pageSize'] = $pageSize;
unset($params['secretCode']);
$postData = $this->buildParams($params, 'open.order.agent.query');
$result = doCurl($this->apiDomain,$postData);
if (!empty($result['error'])) {
throw new GameException($result['error']['message'], 0);
}
return $result;
}
/**
* 查询投注限红盘口
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getLimitations()
{
$params = [
'random' => $this->player->uuid ?? uniqid(),
'sn' => $this->sn,
'time' => date('Y-m-d H:i:s'),
'secretKey' => $this->appSecret,
];
$params['sign'] = $this->createSign($params);
unset($params['secretKey']);
$postData = $this->buildParams($params, 'open.game.limitations.get');
$result = doCurl($this->apiDomain,$postData);
if (!empty($result['error'])) {
throw new GameException($result['error']['message'], 0);
}
return $result;
}
/**
* 修改投注限红盘口
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function setLimitations($value)
{
$params = [
'random' => $this->player->uuid ?? uniqid(),
'sn' => $this->sn,
'time' => date('Y-m-d H:i:s'),
'secretKey' => $this->appSecret,
];
$params['sign'] = $this->createSign($params);
$params['loginId'] = $this->loginId;
$params['value'] = $value;
unset($params['secretKey']);
$postData = $this->buildParams($params, 'open.game.limitations.set');
$result = doCurl($this->apiDomain,$postData);
if (!empty($result['error'])) {
throw new GameException($result['error']['message'], 0);
}
return $result;
}
/**
* 获取限红盘口列表
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getLimitationsList()
{
$params = [
'random' => $this->player->uuid ?? uniqid(),
'sn' => $this->sn,
'time' => date('Y-m-d H:i:s'),
'secretKey' => $this->appSecret,
];
$params['sign'] = $this->createSign($params);
unset($params['secretKey']);
$postData = $this->buildParams($params, 'open.game.limitations.list');
$result = doCurl($this->apiDomain,$postData);
if (!empty($result['error'])) {
throw new GameException($result['error']['message'], 0);
}
return $result;
}
}

View File

@@ -0,0 +1,371 @@
<?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\Log;
use support\Response;
class CSServiceInterface extends GameServiceFactory implements GameServiceInterface
{
public $method = 'POST';
public $successCode = '0';
/** @var PlayerGamePlatform $playerGamePlatform */
public $playerGamePlatform;
public $gameType = [
'CB' => 'CARD & BOARDGAME',
'ES' => 'E-GAMES',
'SB' => 'SPORTBOOK',
'LC' => 'LIVE-CASINO',
'SL' => 'SLOTS',
'LK' => 'LOTTO',
'FH' => 'FISH HUNTER',
'PK' => 'POKER',
'MG' => 'MINI GAME',
'OT' => 'OTHERS'
];
public $failCode = [
'61' => '货币不兼容',
'70' => '集成系统余额不足',
'71' => '单据号不正确',
'72' => '余额不足',
'73' => '转账金额不正确',
'74' => '转账金额不能多过两个小数点 0.00',
'75' => '不允许在游戏中进行转移',
'81' => '会员账号不存在',
'82' => '会员账号已存在',
'83' => '代理号已存在',
'90' => '请求参数不正确',
'91' => '代理号不正确',
'92' => '供应商代号不正确',
'93' => '请求参数类型不正确',
'94' => '账号不正确',
'95' => '密码不正确',
'96' => '旧密码不正确',
'97' => '请求链接/域名不正确',
'98' => '账号/密码错误',
'99' => '加密错误',
'600' => '前期检验失败。 存款/取款 操作已被无视',
'601' => '此产品的存款 功能暂时停用维修',
'602' => '此产品的取款 功能暂时停用维修',
'603' => '即将执行在线系统维护为了避免维护时导致的系统不稳定转账API暂时停止暂停时间大约510分钟若提早完毕会提早解放',
'992' => '平台不兼容请求的游戏类型',
'991' => '代理号已冻结',
'994' => '接口访问被禁止',
'995' => '平台未开通',
'996' => '平台不支持',
'998' => '请联系客服',
'999' => '系统维护中',
'9999' => '未知错误',
'-987' => '交易单号不存在;产品不支持',
'-997' => '系统错误,请联络客服。',
'-998' => '集成系统接口余额不足',
'-999' => '接口错误',
];
private $apiDomain;
private $providerCode;
private $appId;
private $appSecret;
private $path = [
'createPlayer' => '/createMember.aspx',
'getGameList' => '/getGameList.aspx',
'getBalance' => '/getBalance.aspx',
'getLoginH5' => '/launchGames.aspx',
'getDLoginH5' => '/launchDGames.ashx',
'changePassword' => '/changePassword.aspx',
'checkAgentCredit' => '/checkAgentCredit.aspx',
'checkMemberProductUsername' => '/checkMemberProductUsername.aspx',
'launchAPP' => '/launchAPP.ashx',
'checkTransaction' => '/checkTransaction.ashx',
'setBalanceTransfer' => '/makeTransfer.aspx',
'getDailyWager' => '/getDailyWager.ashx',
'fetchArchieve' => '/fetchArchieve.aspx',
'markbyjson' => '/markbyjson.aspx',
'markArchieve' => '/markArchieve.ashx',
'getGameRecord' => '/fetchbykey.aspx',
];
private $lang = [
'zh-CN' => 'zh-ch',
'en' => 'en_us',
'zh_tc' => 'zh_tc',
'en-us' => 'en-us',
'id' => 'id',
'th' => 'th',
'my' => 'my',
'vi' => 'vi',
'fi_fi' => 'fi_fi',
'kr_ko' => 'kr_ko',
'hi_hi' => 'hi_hi',
'br_po' => 'br_po',
'lo_la' => 'lo_la',
'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->appSecret = $config['app_secret'];
$this->apiDomain = $config['api_domain'];
$this->providerCode = $config['provider_code'];
$this->platform = GamePlatform::query()->where('name', $type)->first();
if (!empty($player)) {
$this->player = $player;
/** @var PlayerGamePlatform $playerGamePlatform */
$playerGamePlatform = $this->player->playerGamePlatform->where('platform_id', $this->platform->id)->first();
if (empty($playerGamePlatform)) {
$this->createPlayer();
} else {
$this->playerGamePlatform = $playerGamePlatform;
}
}
}
/**
* 创建玩家 MD5(operatorcode + username +secret_key)
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function createPlayer()
{
$userName = mb_strtolower($this->providerCode . generateUniqueUsername());
$params = [
'operatorcode' => $this->appId,
'username' => $userName,
];
$params['signature'] = mb_strtoupper(md5($this->appId . $userName . $this->appSecret));
$res = dogGetCurl($this->createUrl('createPlayer'), $params);
if ($res['errCode'] != $this->successCode) {
throw new GameException($this->failCode[$res['errCode']], 0);
}
$playerGamePlatform = new PlayerGamePlatform();
$playerGamePlatform->player_id = $this->player->id;
$playerGamePlatform->platform_id = $this->platform->id;
$playerGamePlatform->player_name = $this->player->name;
$playerGamePlatform->player_code = $userName;
$playerGamePlatform->player_password = generateRandomPassword();
$playerGamePlatform->save();
$this->playerGamePlatform = $playerGamePlatform;
return $res;
}
/**
* 生成请求url
* @param $method
* @return string
*/
public function createUrl($method): string
{
return $this->apiDomain . $this->path[$method];
}
/**
* 查询玩家游戏平台帐号接口 MD5(operatorcode + providercode + username + secret_key)
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getPlayer()
{
$params = [
'operatorcode' => $this->appId,
'providercode' => $this->providerCode,
'username' => $this->playerGamePlatform->player_code,
];
$params['signature'] = mb_strtoupper(md5($this->appId . $this->providerCode . $this->playerGamePlatform->player_code . $this->appSecret));
$res = dogGetCurl($this->createUrl('checkMemberProductUsername'), $params);
if ($res['errCode'] != $this->successCode) {
throw new GameException($this->failCode[$res['errCode']], 0);
}
return $res;
}
/**
* 获取游戏列表 MD5(operatorcode.toLower() + providercode.toUpper() + secret_key)
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getSimpleGameList()
{
$params = [
'providercode' => $this->providerCode,
'operatorcode' => $this->appId,
'lang' => 'en',
'html' => '0',
'reformatJson' => 'yes',
];
$params['signature'] = strtoupper(md5(mb_strtolower($this->appId) . mb_strtoupper($this->providerCode) . $this->appSecret));
$data = dogGetCurl($this->createUrl('getGameList'), $params);
if ($data['errCode'] != $this->successCode) {
throw new GameException($this->failCode[$data['errCode']], 0);
}
if (!empty($data['gamelist'])) {
$gameList = json_decode($data['gamelist'], true);
foreach ($gameList as $game) {
try {
Game::query()->updateOrCreate(
[
'platform_id' => $this->platform->id,
'game_code' => $game['g_code']
],
[
'platform_game_type' => $game['p_type'],
'game_data' => json_encode($game),
'name' => $game['gameName']['gameName_enus'] ?? '',
'game_image' => $game['imgFileName'] ?? '',
]
);
} catch (Exception $e) {
Log::error($e->getMessage());
}
}
}
return $data;
}
/**
* 登录游戏MD5(operatorcode + password + providercode + type + username + secret_key)
* @param array $data
* @return string
* @throws GameException|\think\Exception
*/
public function login(array $data = []): string
{
$params = [
'operatorcode' => $this->appId,
'providercode' => $this->providerCode,
'username' => $this->playerGamePlatform->player_code,
'password' => $this->playerGamePlatform->player_password,
'type' => $data['platformGameType'],
'gameid' => $data['gameCode'] ?? 0,
'lang' => 'en',
'html5' => 1,
];
$params['signature'] = mb_strtoupper(md5($this->appId . $this->playerGamePlatform->player_password . $this->providerCode . $data['platformGameType'] . $this->playerGamePlatform->player_code . $this->appSecret));
$res = dogGetCurl($this->createUrl('getLoginH5'), $params);
if ($res['errCode'] != $this->successCode) {
Log::error($this->failCode[$res['errCode']], ['res' => $res]);
throw new GameException($this->failCode[$res['errCode']], 0);
}
return $res['gameUrl'];
}
/**
* 玩家钱包转入游戏平台
* @return array|mixed|null
* @throws GameException|\think\Exception
*/
public function balanceTransferOut()
{
return $this->setBalanceTransfer(PlayerWalletTransfer::TYPE_OUT, intval($this->player->wallet->money));
}
/**
* 资金转账接口MD5(amount + operatorcode + password + providercode + referenceid + type + username + secret_key)
* @param $type
* @param float $amount
* @return array|mixed|null
* @throws GameException
* @throws \think\Exception
*/
protected function setBalanceTransfer($type, float $amount = 0)
{
if ($type == PlayerWalletTransfer::TYPE_OUT) {
$platformType = 0;
} else {
$platformType = 1;
}
$no = createOrderNo();
$params = [
'operatorcode' => $this->appId,
'providercode' => $this->providerCode,
'username' => $this->playerGamePlatform->player_code,
'password' => $this->playerGamePlatform->player_password,
'referenceid' => $no,
'type' => $platformType,
'amount' => $amount
];
$params['signature'] = mb_strtoupper(md5($amount . $this->appId . $this->playerGamePlatform->player_password . $this->providerCode . $no . $platformType . $this->playerGamePlatform->player_code . $this->appSecret));
$res = dogGetCurl($this->createUrl('setBalanceTransfer'), $params);
if ($res['errCode'] != $this->successCode) {
throw new GameException($this->failCode[$res['errCode']], 0);
}
// 记录玩家钱包转出转入记录
$this->createWalletTransfer($type, $amount, 0, $res['innerCode'] ?? '');
return $res;
}
/**
* 玩家钱包转入游戏平台
* @return array|mixed|null
* @throws GameException|\think\Exception
*/
public function balanceTransferIn()
{
$balance = $this->getBalance();
return $this->setBalanceTransfer(PlayerWalletTransfer::TYPE_IN, $balance['balance'] ?? 0);
}
/**
* 獲取玩家餘額信息
* 簽名密鑰方式 MD5(operatorcode + password + providercode + username + secret_key)
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getBalance()
{
$params = [
'operatorcode' => $this->appId,
'providercode' => $this->providerCode,
'username' => $this->playerGamePlatform->player_code,
'password' => $this->playerGamePlatform->player_password
];
$params['signature'] = mb_strtoupper(md5($this->appId . $this->playerGamePlatform->player_password . $this->providerCode . $this->playerGamePlatform->player_code . $this->appSecret));
$res = dogGetCurl($this->createUrl('getBalance'), $params);
if ($res['errCode'] != $this->successCode) {
throw new GameException($this->failCode[$res['errCode']], 0);
}
return $res;
}
/**
* 依據時間獲取遊戲紀錄
* MD5 (Id+Method+SN+StartTime+EndTime+APISecretKey)
* @param int $pageIndex
* @param string $startTime
* @param string $endTime
* @return array|mixed|null
* @throws GameException
*/
public function getGameRecordByTime(int $pageIndex = 1, string $startTime = '', string $endTime = '')
{
}
/**
* 獲取玩家遊戲歷史紀錄
* MD5 (Id+Method+SN+APISecretKey)
* @return array|mixed|null
* @throws GameException
*/
public function getGameRecord()
{
}
}

View File

@@ -0,0 +1,141 @@
<?php
namespace app\service\game;
use addons\webman\model\GamePlatform;
use addons\webman\model\Player;
use addons\webman\model\PlayerDeliveryRecord;
use addons\webman\model\PlayerWalletTransfer;
use Exception;
/**
* 游戏服务工厂
*/
class GameServiceFactory
{
const TYPE_LUCKY365 = 'LUCKY365'; // lucky365
const TYPE_BIGGAMING = 'BIGGAMING'; // BigGaming
const TYPE_JILI = 'JILI'; // jili
const TYPE_MEGA888 = 'MEGA888'; // Mega888
const TYPE_KISS918 = 'KISS918'; // Kiss918
const TYPE_JDB = 'JDB'; // JDB
const TYPE_PRAGMATIC = 'PRAGMATIC'; // PRAGMATIC
const TYPE_MARIOCLUB = 'MARIOCLUB'; // MARIOCLUB
const TYPE_JOKER = 'JOKER'; // JOKER
const TYPE_LIONKING = 'LIONKING'; // LionKing
const TYPE_MONKEY_KING = 'MONKEYKING'; // monkey king
const TYPE_ASIAGAMING = 'ASIAGAMING'; // AsiaGaming
const TYPE_TFGAMING = 'TFGAMING'; // TfGaming
const TYPE_IBC = 'IBC'; // IBC
const TYPE_PLAYSTAR = 'PLAYSTAR'; // PlayStar
const TYPE_AWC68 = 'AWC68'; // AWC68
const TYPE_GAMEPLAY = 'GAMEPLAY'; // GamePlay
const TYPE_NEXTSPIN = 'NEXTSPIN'; // GamePlay
const TYPE_WMCASINO = 'WMCASINO'; // WMcasino
const TYPE_SPADEGAMING = 'SPADEGAMING'; // SpadeGaming
const TYPE_FUNKYGAME = 'FUNKYGAME'; // FunkyGame
const TYPE_R5 = 'R5'; // R5
const TYPE_JK = 'JK'; // JK
const DEVICE_TYPE_WEB = 1; // web
const DEVICE_TYPE_IOS = 2; // ios
const DEVICE_TYPE_ANDROID = 3; // android
/** @var Player $player */
public $player;
/** @var GamePlatform $platform */
public $platform;
/**
* 创建服务
* @throws Exception
*/
public static function createService(string $type, $player = null): GameServiceInterface
{
switch ($type) {
case self::TYPE_LUCKY365:
return new Lucky365ServiceInterface(self::TYPE_LUCKY365, $player);
case self::TYPE_JILI:
return new JiLiServiceInterface(self::TYPE_JILI, $player);
case self::TYPE_MEGA888:
return new MeGa888ServiceInterface(self::TYPE_MEGA888, $player);
case self::TYPE_BIGGAMING:
return new BigGamingServiceInterface(self::TYPE_BIGGAMING, $player);
case self::TYPE_KISS918:
return new Kiss918ServiceInterface(self::TYPE_KISS918, $player);
case self::TYPE_JDB:
return new JDBServiceInterface(self::TYPE_JDB, $player);
case self::TYPE_PRAGMATIC:
return new PragmaticServiceInterface(self::TYPE_PRAGMATIC, $player);
case self::TYPE_MARIOCLUB:
return new MarioClubServiceInterface(self::TYPE_MARIOCLUB, $player);
case self::TYPE_JOKER:
return new JokerServiceInterface(self::TYPE_JOKER, $player);
case self::TYPE_NEXTSPIN:
return new NextSpinServiceInterface(self::TYPE_NEXTSPIN, $player);
case self::TYPE_MONKEY_KING:
return new MonkeyKingServiceInterface(self::TYPE_MONKEY_KING, $player);
case self::TYPE_LIONKING:
return new LionKingServiceInterface(self::TYPE_LIONKING, $player);
case self::TYPE_ASIAGAMING:
case self::TYPE_TFGAMING:
case self::TYPE_IBC:
case self::TYPE_PLAYSTAR:
case self::TYPE_AWC68:
case self::TYPE_GAMEPLAY:
case self::TYPE_WMCASINO:
case self::TYPE_SPADEGAMING:
case self::TYPE_FUNKYGAME:
case self::TYPE_R5:
case self::TYPE_JK:
return new CSServiceInterface($type, $player);
default:
throw new Exception("未知的游戏服务类型: $type");
}
}
/**
* 报错平台转出/入记录
* @param int $type
* @param float $amount
* @param float $reward
* @param string $platformNo
* @return void
*/
public function createWalletTransfer(int $type = 1, float $amount = 0, float $reward = 0, string $platformNo = '')
{
$playerWalletTransfer = new PlayerWalletTransfer();
$playerWalletTransfer->player_id = $this->player->id;
$playerWalletTransfer->platform_id = $this->platform->id;
$playerWalletTransfer->department_id = $this->player->department_id;
$playerWalletTransfer->type = $type;
$playerWalletTransfer->amount = abs($amount);
$playerWalletTransfer->reward = abs($reward);
$playerWalletTransfer->platform_no = $platformNo;
$playerWalletTransfer->tradeno = createOrderNo();
$playerWalletTransfer->save();
$beforeGameAmount = $this->player->wallet->money;
$playerDeliveryRecord = new PlayerDeliveryRecord;
if ($type == PlayerWalletTransfer::TYPE_OUT) {
$this->player->wallet->money = 0;
$playerDeliveryRecord->type = PlayerDeliveryRecord::TYPE_GAME_OUT;
}
if ($type == PlayerWalletTransfer::TYPE_IN) {
$this->player->wallet->money = bcadd($this->player->wallet->money, bcadd(abs($amount), abs($reward), 2), 2);
$playerDeliveryRecord->type = PlayerDeliveryRecord::TYPE_GAME_IN;
}
$this->player->push();
//寫入金流明細
$playerDeliveryRecord->player_id = $playerWalletTransfer->player_id;
$playerDeliveryRecord->department_id = $playerWalletTransfer->department_id;
$playerDeliveryRecord->target = $playerWalletTransfer->getTable();
$playerDeliveryRecord->target_id = $playerWalletTransfer->id;
$playerDeliveryRecord->source = 'play_game';
$playerDeliveryRecord->amount = $playerWalletTransfer->amount;
$playerDeliveryRecord->amount_before = $beforeGameAmount;
$playerDeliveryRecord->amount_after = $this->player->wallet->money;
$playerDeliveryRecord->tradeno = '';
$playerDeliveryRecord->remark = '';
$playerDeliveryRecord->save();
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace app\service\game;
interface GameServiceInterface
{
/**
* 创建玩家
* @return mixed
*/
public function createPlayer();
/**
* 获取玩家信息
* @return mixed
*/
public function getPlayer();
/**
* 获取游戏列表
* @return mixed
*/
public function getSimpleGameList();
/**
* 登录
* @return mixed
*/
public function login();
}

View File

@@ -0,0 +1,511 @@
<?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'] ?? [];
}
}

View File

@@ -0,0 +1,529 @@
<?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 Illuminate\Support\Str;
use support\Log;
use support\Response;
class JiLiServiceInterface extends GameServiceFactory implements GameServiceInterface
{
public $method = 'POST';
private $apiDomain;
private $domain;
private $appId;
private $appSecret;
public $loginId;
public $gameType = [
'2' => 'Casino',
'5' => 'Fishing',
'8' => 'Bingo',
'1' => 'Slot',
];
public $localGameType = [
'2' => '2',//赌场
'5' => '4',//捕鱼
'8' => '8',//宾果
'1' => '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' => '系統錯誤',
];
/**
* @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($method): string
{
return $this->apiDomain.$method;
}
public function createSign($params): string
{
$date = new DateTime('now', new DateTimeZone('UTC'));
$date->setTimezone(new DateTimeZone('America/Puerto_Rico'));
$key_g = md5($date->format('ymj').$this->appId.$this->appSecret);
$paramStr = urldecode(http_build_query($params));
$key = mt_rand(100000,999999).MD5($paramStr.$key_g).mt_rand(100000,999999);
return $key;
}
/**
* 更新游戏列表
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getSimpleGameList()
{
$params = [
'AgentId' => $this->appId
];
$signature = $this->createSign($params);
$params['Key'] = $signature;
$result = doFormCurl($this->createUrl('GetGameList'), $params);
if ($result['ErrorCode'] == 0 && !empty($result['Data'])) {
foreach ($result['Data'] as $game) {
if($game['GameCategoryId'] == 3){
continue;
}
Game::query()->updateOrCreate(
[
'platform_id' => $this->platform->id,
'game_code' => $game['GameId'],
],
[
'platform_game_type' => $game['GameCategoryId'],
'game_type' => $this->localGameType[$game['GameCategoryId']],
'name' => $game['name']['en-US'],
]
);
}
}else{
throw new GameException($result['Message'], 0);
}
return $result;
}
/**
* 获取游戏列表
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getGamesList()
{
$params = [
'AgentId' => $this->appId
];
$signature = $this->createSign($params);
$params['Key'] = $signature;
$result = doFormCurl($this->createUrl('GetGameList'), $params);
if ($result['ErrorCode'] == 0 && !empty($result['Data'])) {
return $result;
}else{
throw new GameException($result['Message'], 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 = [
'Account' => $data['uuid'],
'AgentId' => $this->appId
];
$signature = $this->createSign($params);
$params['Key'] = $signature;
$result = doFormCurl($this->createUrl('CreateMember'), $params);
if (!in_array($result['ErrorCode'],[0,101])) {
Log::error($result['Message'], ['res' => $result]);
throw new GameException($result['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 $result;
}
/**
* 获取玩家
* @return array|mixed|Response
* @throws GameException|Exception
*/
public function getPlayer()
{
$params = [
'Accounts' => $this->loginId,
'AgentId' => $this->appId
];
$signature = $this->createSign($params);
$params['Key'] = $signature;
$result = doFormCurl($this->createUrl('GetMemberInfo'), $params);
if ($result['ErrorCode'] != 0) {
throw new GameException($result['Message'], 0);
}
return $result;
}
/**
* 玩家进入游戏
* @param array $data
* @return string
* @throws GameException|\think\Exception
*/
public function login(array $data = []): string
{
$params = [
'Account'=> $this->loginId,
'GameId'=> intval($data['gameCode']),
'Lang'=> $data['lang'],
'AgentId' => $this->appId
];
$signature = $this->createSign($params);
$params['Key'] = $signature;
$result = doFormCurl($this->createUrl('LoginWithoutRedirect'), $params);
if ($result['ErrorCode'] == 0 && !empty($result['Data'])) {
$link = $result['Data'];
}else{
throw new GameException($result['Message'], 0);
}
return $link;
}
/**
* 获取玩家游戏平台余额
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getBalance()
{
$params = [
'Accounts' => $this->loginId,
'AgentId' => $this->appId
];
$signature = $this->createSign($params);
$params['Key'] = $signature;
$result = doFormCurl($this->createUrl('GetMemberInfo'), $params);
if ($result['ErrorCode'] != 0) {
throw new GameException('JiLi System Error,Please contact the administrator', 0);
}
return bcdiv($result['Data'][0]['Balance'], 100 , 2);
}
/**
* 玩家钱包转入游戏平台
* @return array|mixed|null
* @throws GameException|\think\Exception
*/
public function balanceTransferOut()
{
return $this->setBalanceTransfer(PlayerWalletTransfer::TYPE_IN, $this->player->wallet->money);
}
/**
* 游戏平台转入玩家钱包
* @return array|mixed|null
* @throws GameException|\think\Exception
*/
public function balanceTransferIn()
{
$balance = $this->getBalance();
return $this->setBalanceTransfer(PlayerWalletTransfer::TYPE_OUT, $balance);
}
/**
* 轉帳進出額度
* @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 ($type == 2 && $amount == 0 && $reward == 0) {
throw new GameException('转出/入金额错误', 0);
}
$params = [
'Account' => $this->loginId,
'TransactionId' => createOrderNo(),
'Amount' => $amount,
'TransferType' => $type,
'AgentId' => $this->appId
];
$signature = $this->createSign($params);
$params['Key'] = $signature;
$result = doFormCurl($this->createUrl('ExchangeTransferByAgentId'), $params);
if ($result['ErrorCode'] != 0) {
throw new GameException($result['Message'], 0);
}
if($type == 1){
$type = 2;
}else{
$type = 1;
}
// 记录玩家钱包转出转入记录
$this->createWalletTransfer($type, $amount, $reward, $result['Data']['TransactionId'] ?? '');
return $result;
}
/**
* 查询额度转移纪录
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getTransferList(string $startTime = '', string $endTime = '', int $page = 1, int $pageSize = 10)
{
$params = [
'StartTime' => $startTime,
'EndTime' => $endTime,
'Page' => $page,
'PageLimit' => $pageSize,
'AgentId' => $this->appId
];
$signature = $this->createSign($params);
$params['Key'] = $signature;
$result = doFormCurl($this->createUrl('GetTransferRecordByTime'), $params);
if ($result['ErrorCode'] != 0) {
throw new GameException($result['Message'], 0);
}
return $result['Data'];
}
/**
* 查询一笔额度转移纪录
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getTransferById(string $transactionId)
{
$params = [
'TransactionId' => $transactionId,
'AgentId' => $this->appId
];
$signature = $this->createSign($params);
$params['Key'] = $signature;
$result = doFormCurl($this->createUrl('CheckTransferByTransactionId'), $params);
if ($result['ErrorCode'] != 0) {
throw new GameException($result['Message'], 0);
}
return $result['Data'];
}
/**
* 查询游戏纪录
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getGameRecordList(string $startTime = '', string $endTime = '', int $page = 1, int $pageSize = 10000, int $gameId = null)
{
$params = [
'StartTime' => $startTime,
'EndTime' => $endTime,
'Page' => $page,
'PageLimit' => $pageSize,
'AgentId' => $this->appId
];
$signature = $this->createSign($params);
$params['Key'] = $signature;
if(!empty($gameId)){
$params['GameId'] = $gameId;
}
$result = doFormCurl($this->createUrl('GetBetRecordByTime'), $params);
if ($result['ErrorCode'] != 0) {
throw new GameException($result['Message'], 0);
}
return $result['Data'];
}
/**
* 查询指定游戏记录详情
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getGameRecordById(string $wagersId)
{
$params = [
'WagersId' => $wagersId,
'AgentId' => $this->appId
];
$signature = $this->createSign($params);
$params['Key'] = $signature;
$lang = locale();
$lang = Str::replace('_', '-', $lang);
$params['Lang'] = $lang;
$result = doFormCurl($this->createUrl('GetGameDetailUrl'), $params);
if ($result['ErrorCode'] != 0) {
throw new GameException($result['Message'], 0);
}
return $result['Data'];
}
/**
* 查询指定玩家游戏记录
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getUserGameRecord(string $startTime = '', string $endTime = '', int $page = 1, int $pageSize = 10, int $gameId = null, int $gameType = null)
{
$params = [
'StartTime' => $startTime,
'EndTime' => $endTime,
'Page' => $page,
'PageLimit' => $pageSize,
'Account' => $this->loginId,
'AgentId' => $this->appId
];
$signature = $this->createSign($params);
$params['Key'] = $signature;
if(!empty($gameId)){
$params['GameId'] = $gameId;
}
if(!empty($gameType)){
$params['GameType'] = $gameType;
}
$lang = locale();
$lang = Str::replace('_', '-', $lang);
$params['Lang'] = $lang;
$result = doFormCurl($this->createUrl('GetUserBetRecordByTime'), $params);
if ($result['ErrorCode'] != 0) {
throw new GameException($result['Message'], 0);
}
return $result['Data'];
}
/**
* 查询玩家游戏记录
* @param string $startTime
* @param string $endTime
* @return array
*/
public function handleOrderHistories(string $startTime = '', string $endTime = ''): array
{
try {
$page = 1;
$list = [];
$timezone = new DateTimeZone('Etc/GMT+4');
$start = new DateTime('-6 minutes', $timezone);
$end = new DateTime('-5 minutes', $timezone);
$startTime = $start->format('Y-m-d\TH:i:s');
$endTime = $end->format('Y-m-d\TH:i:s');
$data = $this->getGameRecordList($startTime, $endTime, $page);
if (!empty($data['Result'])) {
$total = $data['Pagination']['TotalNumber'] ?? 0;
if ($total > 0) {
$pageSize = 10000;
if (!empty($data['Result'])) {
foreach ($data['Result'] as $item) {
$list[] = [
'uuid' => $item['Account'],
'platform_id' => $this->platform->id,
'game_code' => $item['GameId'],
'bet' => abs(bcdiv($item['Turnover'], 100, 2)),
'win' => bcdiv($item['PayoffAmount'],100, 2),
'order_no' => $item['WagersId'],
'original_data' => json_encode($item,JSON_UNESCAPED_UNICODE),
'platform_action_at' => date('Y-m-d H:i:s', strtotime($item['SettlementTime'])),
'game_type' => $item['GameCategoryId'],
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
];
}
}
if ($total > $pageSize) {
$totalPages = ceil($total / $pageSize);
for ($page = 2; $page <= $totalPages; $page++) {
$nextData = $this->getGameRecordList($startTime,$endTime,$page);
if (!empty($nextData['Result'])) {
foreach ($nextData['Result'] as $item) {
$list[] = [
'uuid' => $item['Account'],
'platform_id' => $this->platform->id,
'game_code' => $item['GameId'],
'bet' => abs(bcdiv($item['Turnover'], 100, 2)),
'win' => bcdiv($item['PayoffAmount'],100, 2),
'order_no' => $item['WagersId'],
'original_data' => json_encode($item,JSON_UNESCAPED_UNICODE),
'platform_action_at' => date('Y-m-d H:i:s', strtotime($item['SettlementTime'])),
'game_type' => $item['GameCategoryId'],
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
];
}
}
}
}
}
}
} catch (Exception $e) {
return [];
}
return $list;
}
}

View File

@@ -0,0 +1,465 @@
<?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\Log;
use support\Response;
class JokerServiceInterface extends GameServiceFactory implements GameServiceInterface
{
public $method = 'POST';
private $apiDomain;
private $domain;
private $appId;
private $appSecret;
public $loginId;
public $gameType = [
'ECasino' => '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;
}
}

View File

@@ -0,0 +1,389 @@
<?php
namespace app\service\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 Kiss918ServiceInterface extends GameServiceFactory implements GameServiceInterface
{
public $method = 'POST';
private $apiDomain;
private $domain;
private $auth;
private $appSecret;
public $loginId;
public $password;
public $gameType = [
'2' => 'Casino',
'5' => 'Fishing',
'8' => 'Bingo',
'1' => 'Slot',
];
public $localGameType = [
'2' => '2',//赌场
'5' => '4',//捕鱼
'8' => '2',//宾果
'1' => '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 $admin_user;
/**
* @param Player|null $player
* @param $type
* @throws Exception
*/
public function __construct($type, Player $player = null)
{
$config = config('game_platform.' . $type);
$this->auth = $config['auth'];
$this->admin_user = $config['admin_user'];
$this->apiDomain = $config['api_domain'];
$this->recordApi = $config['record_api'];
$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();
}
}
public function createSign($params): string
{
$str = implode('', $params);
return strtoupper(md5(strtolower($str)));
}
/**
* 更新游戏列表
* @return false
*/
public function getSimpleGameList(): bool
{
return false;
}
/**
* 获取玩家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)) {
$this->password = $playerGamePlatform->player_password;
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 = [])
{
$time = round(microtime(true)*1000);
$randomParams = [
'action' => 'RandomUserName',
'userName' => $this->admin_user,
'time' => $time,
'authcode' => $this->auth,
];
$signature = $this->createSign([$this->auth, $randomParams['userName'], $time ,$this->appSecret]);
$randomParams['sign'] = $signature;
$randomUser = dogGetCurl($this->apiDomain.'ashx/account/account.ashx', $randomParams);;
if(!$randomUser['success'] || empty($randomUser['account'])){
throw new GameException($randomUser['msg'], 0);
}
$password = uniqid();
$params = [
'action' => 'addUser',
'agent' => $this->admin_user,
'PassWd' => $password,
'pwdtype' => 1,
'userName' => $randomUser['account'],
'Name' => $data['name'],
'Tel' => $this->player->phone ?? '',
'Memo' => $data['name'],
'UserType' => 1,
'time' => $time,
'authcode' => $this->auth,
];
$signature = $this->createSign([$this->auth, $params['userName'], $time ,$this->appSecret]);
$params['sign'] = $signature;
$result = dogGetCurl($this->apiDomain.'ashx/account/account.ashx', $params);;
if ($result['code'] == 0 && $result['success']) {
$playerGamePlatform = new PlayerGamePlatform();
$playerGamePlatform->player_id = $this->player->id;
$playerGamePlatform->platform_id = $this->platform->id;
$playerGamePlatform->player_name = $data['name'];
$playerGamePlatform->player_code = $randomUser['account'];
$playerGamePlatform->player_password = $password;
$playerGamePlatform->save();
$this->loginId = $playerGamePlatform->player_code;
$this->password = $playerGamePlatform->player_password;
return $result;
}else{
throw new GameException($result['msg'], 0);
}
}
/**
* 获取玩家
* @return array|mixed|Response
* @throws Exception
*/
public function getPlayer()
{
$time = round(microtime(true)*1000);
$params = [
'action' => 'getUserInfo',
'userName' => $this->loginId,
'time' => $time,
'authcode' => $this->auth,
];
$signature = $this->createSign([$this->auth, $this->loginId, $time ,$this->appSecret]);
$params['sign'] = $signature;
$result = dogGetCurl($this->apiDomain.'ashx/account/account.ashx', $params);
if($result['success']){
return $result;
}else{
throw new GameException('Kiss 918 System Error,Please contact the administrator', 0);
}
}
/**
* 玩家进入游戏
* @param array $data
* @return array
*/
public function login(array $data = []): array
{
return ['url' => 'https://yop1.918kiss.com/', 'account' => $this->loginId, 'password' => $this->password];
}
/**
* 获取玩家游戏平台余额
* @return string|null
* @throws Exception
*/
public function getBalance(): string
{
$playerInfo = $this->getPlayer();
return $playerInfo['MoneyNum'];
}
/**
* 玩家钱包转入游戏平台
* @return array|mixed|null
* @throws GameException|\think\Exception
*/
public function balanceTransferOut()
{
if($this->player->wallet->money <= 0){
return true;
}
return $this->setBalanceTransfer(PlayerWalletTransfer::TYPE_OUT, $this->player->wallet->money);
}
/**
* 游戏平台转入玩家钱包
* @return array|mixed|null
* @throws 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);
}
/**
* 轉帳進出額度
* @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)
{
$time = round(microtime(true)*1000);
$params = [
'action' => 'setServerScore',
'orderid' => date('YmdHis').uniqid(),
'scoreNum' => $amount,
'userName' => $this->loginId,
'ActionUser' => $this->loginId,
'ActionIp' => request()->getRealIp(),
'time' => $time,
'authcode' => $this->auth,
];
$signature = $this->createSign([$this->auth, $this->loginId, $time ,$this->appSecret]);
$params['sign'] = $signature;
$result = dogGetCurl($this->apiDomain.'ashx/account/setScore.ashx', $params);
if($result['code'] != 0 || !$result['success']){
throw new GameException($result['msg'], 0);
}
// 记录玩家钱包转出转入记录
$this->createWalletTransfer($type, $amount, $reward, $params['orderid']);
return $result;
}
/**
* 查询游戏纪录
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getGameRecordList(string $startTime = '', string $endTime = '', $uuid, int $page = 1, int $pageSize = 1000)
{
$time = round(microtime(true)*1000);
$params = [
'pageIndex' => $page,
'pageSize' => $pageSize,
'userName' => $this->loginId,
'sDate' => $startTime,
'eDate' => $endTime,
'time' => $time,
'authcode' => $this->auth,
];
$signature = $this->createSign([$this->auth, $this->loginId, $time ,$this->appSecret]);
$params['sign'] = $signature;
$result = dogGetCurl($this->apiDomain, $params);
if($result['code'] == 0 || !$result['success']){
throw new GameException($result['msg'], 0);
}
return $result;
}
/**
* 查询全部玩家账单
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getReportRecord(string $startTime = '', string $endTime = '')
{
$time = round(microtime(true)*1000);
$params = [
'userName' => $this->admin_user,
'sDate' => $startTime,
'eDate' => $endTime,
'Type' => 'ServerTotalReport',
'time' => $time,
'authcode' => $this->auth,
];
$signature = $this->createSign([$this->auth, $this->admin_user, $time ,$this->appSecret]);
$params['sign'] = $signature;
$result = dogGetCurl($this->recordApi.'ashx/AgentTotalReport.ashx', $params);
if(!$result['success'] && !empty($result['results'])){
throw new GameException($result['msg'], 0);
}
return $result['results'];
}
/**
* 查询单个玩家单日输赢
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getAccountReport(string $startTime = '', string $endTime = '', $playerCode)
{
$time = round(microtime(true)*1000);
$params = [
'userName' => $playerCode,
'sDate' => $startTime,
'eDate' => $endTime,
'time' => $time,
'authcode' => $this->auth,
];
$signature = $this->createSign([$this->auth, $playerCode, $time ,$this->appSecret]);
$params['sign'] = $signature;
$result = dogGetCurl($this->apiDomain.'ashx/AccountReport.ashx', $params);
if($result['code'] == 0 || !$result['success']){
throw new GameException($result['msg'], 0);
}
return $result;
}
/**
* 查询玩家游戏记录
* @return array
*/
public function handleOrderHistories(): array
{
try {
$list = [];
$startTime = date('Y-m-d');
$endTime = date('Y-m-d');
$data = $this->getReportRecord($startTime, $endTime);
if (!empty($data)) {
foreach ($data as $item) {
$list[] = [
'player_code' => $item['Account'],
'platform_id' => $this->platform->id,
'game_code' => 'Kiss918',
'bet' => $item['press'],
'win' => $item['win'],
'order_no' => $item['idx'].date('Ymd'),
'original_data' => json_encode($item,JSON_UNESCAPED_UNICODE),
'platform_action_at' => $startTime,
'game_type' => 1,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
];
}
}
} catch (Exception $e) {
return [];
}
return $list;
}
}

View File

@@ -0,0 +1,435 @@
<?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\Log;
use support\Response;
class LionKingServiceInterface extends GameServiceFactory implements GameServiceInterface
{
public $method = 'POST';
private $apiDomain;
private $domain;
private $appId;
private $appSecret;
private $path = [
'createPlayer' => '/UserInfo/CreatePlayer',
'getPlayer' => '/UserInfo/GetPlayer',
'getGameList' => '/Game/GetGameList',
'getSimpleGameList' => '/Game/GetSimpleGameList',
'getLoginH5' => '/UserInfo/GetLoginH5',
'setPlayerStatus' => '/UserInfo/SetPlayerStatus',
'getBalance' => '/Account/GetBalance',
'setBalanceTransfer' => '/Account/SetBalanceTransfer',
'getGameRecordByTime' => '/Game/GetGameRecordByTime',
'getGameRecord' => '/Game/GetGameRecord',
'removeRecords' => '/Game/RemoveRecords',
];
public $successCode = 'S100';
public $loginId;
public $gameType = [
'10' => 'Slot',
'12' => 'Casino',
'13' => 'Arcade',
'16' => 'Fishing'
];
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();
}
}
/**
* @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 = [
'ID' => createOrderNo(),
'Method' => 'CreatePlayer',
'SN' => $this->appId,
'PlayerCode' => $data['uuid'],
];
$params['Signature'] = $this->createSign($params);
$params['PlayerName'] = $data['uuid'];
$res = doCurl($this->createUrl('createPlayer'), $params);
if ($res['code'] != $this->successCode) {
throw new GameException($this->failCode[$res['code']], 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;
}
/**
* 获取游戏摘要MD5 (id+method+sn+APlSecretKey)
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getSimpleGameList()
{
$params = [
'ID' => createOrderNo(),
'Method' => 'GetSimpleGameList',
'SN' => $this->appId,
];
$params['Signature'] = $this->createSign($params);
$data = doCurl($this->createUrl('getSimpleGameList'), $params);
if ($data['code'] != $this->successCode) {
throw new GameException($this->failCode[$data['code']], 0);
}
if (!empty($data['data']['games'])) {
foreach ($data['data']['games'] as $game) {
Game::query()->updateOrCreate(
[
'platform_id' => $this->platform->id,
'game_code' => $game['gameCode'],
],
[
'platform_game_type' => $game['type'],
]
);
}
}
return $data;
}
/**
* 获取游戏摘要MD5 (id+method+sn+APlSecretKey)
* @param array $data
* @return string
* @throws GameException|\think\Exception
*/
public function login(array $data = []): string
{
$params = [
'ID' => createOrderNo(),
'Method' => 'GetLoginH5',
'SN' => $this->appId,
'LoginId' => $this->loginId,
];
$params['Signature'] = $this->createSign($params);
$res = doCurl($this->createUrl('getLoginH5'), $params);
if ($res['code'] != $this->successCode) {
Log::error($this->failCode[$res['code']], ['res' => $res]);
throw new GameException($this->failCode[$res['code']], 0);
}
$responseH5 = [
'Language' => $this->lang[$data['lang']] ?? 'ch',
"GameId" => $data['gameCode'],
'CallbackAddress' => $data['callBackUrl'] ?? '',
"AppType" => $data['appType'] ?? 1,
"DeviceType" => 1,
];
$jsonString = json_encode($responseH5);
$parametersValue = base64_encode($jsonString);
$link = $this->domain . '/linkgame' . ($res['data']['loginUrl'] ?? '') . '&' . $parametersValue;
if (!empty($data['gameCode'])) {
$link .= '&' . $data['gameCode'];
}
return $link;
}
/**
* 設置登入玩家狀態。當玩家處於禁用狀態,該玩家無法在平台進行任何操作,如果玩家在遊戲進行中該玩家將會自動退出遊戲。
* 簽名密鑰方式 Md5(Id+Method+SN+LoginId+APISecretKey)
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function setPlayerStatus($status)
{
$params = [
'ID' => createOrderNo(),
'Method' => 'GetSimpleGameList',
'SN' => $this->appId,
'LoginId' => $this->loginId,
];
$params['Signature'] = $this->createSign($params);
$params['Status'] = $status;
$data = doCurl($this->createUrl('setPlayerStatus'), $params);
if ($data['code'] != $this->successCode) {
throw new GameException($this->failCode[$data['code']], 0);
}
return $data;
}
/**
* 獲取玩家餘額信息
* 簽名密鑰方式 MD5 (Id+Method+SN+LoginId+APISecretKey)
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getBalance()
{
$params = [
'ID' => createOrderNo(),
'Method' => 'GetBalance',
'SN' => $this->appId,
'LoginId' => $this->loginId,
];
$params['Signature'] = $this->createSign($params);
$data = doCurl($this->createUrl('getBalance'), $params);
if ($data['code'] != $this->successCode) {
throw new GameException($this->failCode[$data['code']], 0);
}
return $data;
}
/**
* 玩家钱包转入游戏平台
* @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();
return $this->setBalanceTransfer(PlayerWalletTransfer::TYPE_IN, !empty($balance['data']['result']) ? -$balance['data']['result'] : 0, !empty($balance['data']['reward']) ? -$balance['data']['reward'] : 0);
}
/**
* 轉帳進出額度
* 簽名密鑰方式 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 = [
'ID' => createOrderNo(),
'Method' => 'SetBalanceTransfer',
'SN' => $this->appId,
'LoginId' => $this->loginId,
];
$params['Signature'] = $this->createSign($params);
$params['Amount'] = $amount;
$params['Reward'] = $reward;
$res = doCurl($this->createUrl('setBalanceTransfer'), $params);
if ($res['code'] != $this->successCode) {
throw new GameException($this->failCode[$res['code']], 0);
}
// 记录玩家钱包转出转入记录
$this->createWalletTransfer($type, $amount, $reward, $res['data']['refId'] ?? '');
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(int $pageIndex = 1, string $startTime = '', string $endTime = '')
{
$params = [
'ID' => createOrderNo(),
'Method' => 'GetGameRecordByTime',
'SN' => $this->appId,
'StartTime' => $startTime,
'EndTime' => $endTime,
];
$pageSize = 500;
$params['Signature'] = $this->createSign($params);
$params['PageSize'] = $pageSize;
$params['PageIndex'] = $pageIndex;
$res = doCurl($this->createUrl('getGameRecordByTime'), $params);
if ($res['code'] != $this->successCode) {
throw new GameException($this->failCode[$res['code']], 0);
}
return $res;
}
/**
* 獲取玩家遊戲歷史紀錄
* MD5 (Id+Method+SN+APISecretKey)
* @return array|mixed|null
* @throws GameException|\think\Exception
*/
public function getGameRecord()
{
$params = [
'ID' => createOrderNo(),
'Method' => 'GetGameRecord',
'SN' => $this->appId,
];
$params['Signature'] = $this->createSign($params);
$res = doCurl($this->createUrl('getGameRecord'), $params);
if ($res['code'] != $this->successCode) {
throw new GameException($this->failCode[$res['code']], 0);
}
return $res;
}
/**
* 刪除遊戲紀錄
* MD5 (Id+Method+SN+IdsToBeRemoved+APISecretKey)
* @return array|mixed|null
* @throws GameException|\think\Exception
*/
public function removeRecords($idsToBeRemoved)
{
$params = [
'ID' => createOrderNo(),
'Method' => 'RemoveRecords',
'SN' => $this->appId,
'IdsToBeRemoved' => implode(',', $idsToBeRemoved),
];
$params['Signature'] = $this->createSign($params);
$res = doCurl($this->createUrl('removeRecords'), $params);
if ($res['code'] != $this->successCode) {
throw new GameException($this->failCode[$res['code']], 0);
}
return $res;
}
public function createSign($params): string
{
return md5(implode('', $params) . $this->appSecret);
}
/**
* 生成请求url
* @param $method
* @return string
*/
public function createUrl($method): string
{
return $this->apiDomain . $this->path[$method];
}
}

View File

@@ -0,0 +1,444 @@
<?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\Log;
use support\Response;
class Lucky365ServiceInterface extends GameServiceFactory implements GameServiceInterface
{
public $method = 'POST';
private $apiDomain;
private $domain;
private $appId;
private $appSecret;
private $path = [
'createPlayer' => '/UserInfo/CreatePlayer',
'getPlayer' => '/UserInfo/GetPlayer',
'getGameList' => '/Game/GetGameList',
'getSimpleGameList' => '/Game/GetSimpleGameList',
'getLoginH5' => '/UserInfo/GetLoginH5',
'setPlayerStatus' => '/UserInfo/SetPlayerStatus',
'getBalance' => '/Account/GetBalance',
'setBalanceTransfer' => '/Account/SetBalanceTransfer',
'getGameRecordByTime' => '/Game/GetGameRecordByTime',
'getGameRecord' => '/Game/GetGameRecord',
'removeRecords' => '/Game/RemoveRecords',
];
public $successCode = 'S100';
public $loginId;
public $gameType = [
'10' => 'Slot',
'12' => 'Casino',
'13' => 'Arcade',
'16' => 'Fishing'
];
public $localGameType = [
'10' => '1',
'12' => '2',
'13' => '3',
'16' => '4',
];
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();
}
}
/**
* @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 = [
'ID' => createOrderNo(),
'Method' => 'CreatePlayer',
'SN' => $this->appId,
'PlayerCode' => $data['uuid'],
];
$params['Signature'] = $this->createSign($params);
$params['PlayerName'] = $data['uuid'];
$res = doCurl($this->createUrl('createPlayer'), $params);
if ($res['code'] != $this->successCode) {
throw new GameException($this->failCode[$res['code']], 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;
}
/**
* 获取游戏摘要MD5 (id+method+sn+APlSecretKey)
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getSimpleGameList()
{
$params = [
'ID' => createOrderNo(),
'Method' => 'GetSimpleGameList',
'SN' => $this->appId,
];
$params['Signature'] = $this->createSign($params);
$data = doCurl($this->createUrl('getSimpleGameList'), $params);
if ($data['code'] != $this->successCode) {
throw new GameException($this->failCode[$data['code']], 0);
}
if (!empty($data['data']['games'])) {
foreach ($data['data']['games'] as $game) {
Game::query()->updateOrCreate(
[
'platform_id' => $this->platform->id,
'game_code' => $game['gameCode'],
],
[
'platform_game_type' => $game['type'],
'game_type' => $this->localGameType[$game['type']],
'name' => $game['gameName'],
]
);
}
}
return $data;
}
/**
* 获取游戏摘要MD5 (id+method+sn+APlSecretKey)
* @param array $data
* @return string
* @throws GameException|\think\Exception
*/
public function login(array $data = []): string
{
$params = [
'ID' => createOrderNo(),
'Method' => 'GetLoginH5',
'SN' => $this->appId,
'LoginId' => $this->loginId,
];
$params['Signature'] = $this->createSign($params);
$res = doCurl($this->createUrl('getLoginH5'), $params);
if ($res['code'] != $this->successCode) {
Log::error($this->failCode[$res['code']], ['res' => $res]);
throw new GameException($this->failCode[$res['code']], 0);
}
$responseH5 = [
'Language' => $this->lang[$data['lang']] ?? 'ch',
"GameId" => $data['gameCode'],
'CallbackAddress' => $data['callBackUrl'] ?? '',
"AppType" => $data['appType'] ?? 1,
"DeviceType" => 1,
];
$jsonString = json_encode($responseH5);
$parametersValue = base64_encode($jsonString);
if (!empty($data['gameCode'])) {
$link = $this->domain .'/linkgame'. ($res['data']['loginUrl'] ?? '') . '&' . $parametersValue . '&' . $data['gameCode'];
}else{
$link = $this->domain . ($res['data']['loginUrl'] ?? '') . '&' . $parametersValue;
}
return $link;
}
/**
* 設置登入玩家狀態。當玩家處於禁用狀態,該玩家無法在平台進行任何操作,如果玩家在遊戲進行中該玩家將會自動退出遊戲。
* 簽名密鑰方式 Md5(Id+Method+SN+LoginId+APISecretKey)
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function setPlayerStatus($status)
{
$params = [
'ID' => createOrderNo(),
'Method' => 'GetSimpleGameList',
'SN' => $this->appId,
'LoginId' => $this->loginId,
];
$params['Signature'] = $this->createSign($params);
$params['Status'] = $status;
$data = doCurl($this->createUrl('setPlayerStatus'), $params);
if ($data['code'] != $this->successCode) {
throw new GameException($this->failCode[$data['code']], 0);
}
return $data;
}
/**
* 獲取玩家餘額信息
* 簽名密鑰方式 MD5 (Id+Method+SN+LoginId+APISecretKey)
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getBalance()
{
$params = [
'ID' => createOrderNo(),
'Method' => 'GetBalance',
'SN' => $this->appId,
'LoginId' => $this->loginId,
];
$params['Signature'] = $this->createSign($params);
$data = doCurl($this->createUrl('getBalance'), $params);
if ($data['code'] != $this->successCode) {
throw new GameException('Lucky365 System Error,Please contact the administrator', 0);
}
return $data;
}
/**
* 玩家钱包转入游戏平台
* @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();
return $this->setBalanceTransfer(PlayerWalletTransfer::TYPE_IN, !empty($balance['data']['result']) ? -$balance['data']['result'] : 0, !empty($balance['data']['reward']) ? -$balance['data']['reward'] : 0);
}
/**
* 轉帳進出額度
* 簽名密鑰方式 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)
{
$params = [
'ID' => createOrderNo(),
'Method' => 'SetBalanceTransfer',
'SN' => $this->appId,
'LoginId' => $this->loginId,
];
$params['Signature'] = $this->createSign($params);
$params['Amount'] = $amount;
$params['Reward'] = $reward;
$res = doCurl($this->createUrl('setBalanceTransfer'), $params);
if ($res['code'] != $this->successCode) {
throw new GameException($this->failCode[$res['code']], 0);
}
// 记录玩家钱包转出转入记录
$this->createWalletTransfer($type, $amount, $reward, $res['data']['refId'] ?? '');
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(int $pageIndex = 1, string $startTime = '', string $endTime = '')
{
$params = [
'ID' => createOrderNo(),
'Method' => 'GetGameRecordByTime',
'SN' => $this->appId,
'StartTime' => $startTime,
'EndTime' => $endTime,
];
$pageSize = 500;
$params['Signature'] = $this->createSign($params);
$params['PageSize'] = $pageSize;
$params['PageIndex'] = $pageIndex;
$res = doCurl($this->createUrl('getGameRecordByTime'), $params);
if ($res['code'] != $this->successCode) {
throw new GameException($this->failCode[$res['code']], 0);
}
return $res;
}
/**
* 獲取玩家遊戲歷史紀錄
* MD5 (Id+Method+SN+APISecretKey)
* @return array|mixed|null
* @throws GameException|\think\Exception
*/
public function getGameRecord()
{
$params = [
'ID' => createOrderNo(),
'Method' => 'GetGameRecord',
'SN' => $this->appId,
];
$params['Signature'] = $this->createSign($params);
$res = doCurl($this->createUrl('getGameRecord'), $params);
if ($res['code'] != $this->successCode) {
throw new GameException($this->failCode[$res['code']], 0);
}
return $res;
}
/**
* 刪除遊戲紀錄
* MD5 (Id+Method+SN+IdsToBeRemoved+APISecretKey)
* @return array|mixed|null
* @throws GameException|\think\Exception
*/
public function removeRecords($idsToBeRemoved)
{
$params = [
'ID' => createOrderNo(),
'Method' => 'RemoveRecords',
'SN' => $this->appId,
'IdsToBeRemoved' => implode(',', $idsToBeRemoved),
];
$params['Signature'] = $this->createSign($params);
$res = doCurl($this->createUrl('removeRecords'), $params);
if ($res['code'] != $this->successCode) {
throw new GameException($this->failCode[$res['code']], 0);
}
return $res;
}
public function createSign($params): string
{
return md5(implode('', $params) . $this->appSecret);
}
/**
* 生成请求url
* @param $method
* @return string
*/
public function createUrl($method): string
{
return $this->apiDomain . $this->path[$method];
}
}

View File

@@ -0,0 +1,411 @@
<?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 Illuminate\Support\Str;
use support\Log;
use support\Response;
class MarioClubServiceInterface extends GameServiceFactory implements GameServiceInterface
{
public $method = 'POST';
private $apiDomain;
private $appId;
private $appSecret;
public $loginId;
public $gameType = [
'2' => 'Casino',
'5' => 'Fishing',
'8' => 'Bingo',
'1' => 'Slot',
];
public $localGameType = [
'FISHING' => '4',//捕鱼
'SLOT' => '1',//斯洛
'1' => '1',
'4' => '4',
];
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->appId = $config['app_id'];
$this->apiDomain = $config['api_domain'];
$this->appSecret = $config['app_secret'];
$this->platform = GamePlatform::query()->where('name', $type)->first();
if (!empty($player)) {
$this->player = $player;
$this->getLoginId();
}
}
/**
* 生成签名
* @param $time
* @return string
*/
public function createSign($time): string
{
return md5($this->appId.$time.$this->appSecret);
}
/**
* 更新游戏列表
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getSimpleGameList()
{
$time = time();
$params = [
'api_id' => $this->appId,
'timestamp' => $time,
];
$params['sign'] = $this->createSign($time);
$result = doFormCurl($this->apiDomain.'/getGames',$params);
if ($result['code'] == 0 && !empty($result['gameList'])) {
foreach ($result['gameList'] 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'],
'game_image' => $game['gameIconUrl']
]
);
}
}else{
throw new GameException($result['Message'], 0);
}
return $result;
}
/**
* 获取游戏列表
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getGamesList()
{
$time = time();
$params = [
'api_id' => $this->appId,
'timestamp' => $time,
];
$params['sign'] = $this->createSign($time);
$result = doFormCurl($this->apiDomain.'/getGames',$params);
if ($result['code'] == 0 && !empty($result['gameList'])) {
return $result;
}else{
throw new GameException($result['Message'], 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 = [])
{
$time = time();
$params = [
'api_id' => $this->appId,
'timestamp' => $time,
'user_id' => $data['uuid'],
];
$params['sign'] = $this->createSign($time);
$result = doFormCurl($this->apiDomain.'/api/acc/created',$params);
if ($result['code'] != 0) {
Log::error($result['msg'], ['res' => $result]);
throw new GameException($result['msg'], 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 array|mixed|Response
* @throws GameException|Exception
*/
public function getPlayer()
{
$time = time();
$params = [
'api_id' => $this->appId,
'timestamp' => $time,
'user_id' => $this->loginId,
'language' => 'en',
];
$params['sign'] = $this->createSign($time);
$result = doFormCurl($this->apiDomain.'/api/acc/gameLogIn',$params);
if ($result['code'] != 0) {
throw new GameException($result['msg'], 0);
}
return $result;
}
/**
* 玩家进入游戏
* @param array $data
* @return string
* @throws GameException|\think\Exception
*/
public function login(array $data = []): string
{
$time = time();
$params = [
'api_id' => $this->appId,
'timestamp' => $time,
'user_id' => $this->loginId,
'game_code' => $data['gameCode'],
'language' => 'en',
];
$params['sign'] = $this->createSign($time);
$result = doFormCurl($this->apiDomain.'/api/acc/gameLogIn',$params);
if ($result['code'] == 0 && !empty($result['gameUrl'])) {
$link = $result['gameUrl'];
}else{
throw new GameException($result['msg'], 0);
}
return $link;
}
/**
* 获取玩家游戏平台余额
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getBalance()
{
$time = time();
$params = [
'api_id' => $this->appId,
'timestamp' => $time,
'user_id' => $this->loginId,
];
$params['sign'] = $this->createSign($time);
$result = doFormCurl($this->apiDomain.'/api/acc/getBalance',$params);
if ($result['code'] != 0) {
throw new GameException('MarioClub 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);
}
/**
* 轉帳進出額度
* @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 ($type == 1) {
$action = 'deposit';
} else {
$action = 'withdraw';
}
$time = time();
$params = [
'api_id' => $this->appId,
'timestamp' => $time,
'user_id' => $this->loginId,
'amount' => $amount,
'action' => $action,
];
$params['sign'] = $this->createSign($time);
$result = doFormCurl($this->apiDomain.'/api/acc/updateBalance',$params);
if ($result['code'] != 0) {
throw new GameException($result['msg'], 0);
}
// 记录玩家钱包转出转入记录
$this->createWalletTransfer($type, $amount, $reward, $result['transId'] ?? '');
return $result;
}
/**
* 查询额度转移纪录
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getTransferList(string $startTime = '', string $endTime = '', int $page = 1, int $pageSize = 10)
{
$time = time();
$params = [
'api_id' => $this->appId,
'timestamp' => $time,
'user_id' => $this->loginId,
'date_from' => date('d/m/Y', strtotime($startTime)),
'date_to' => date('d/m/Y', strtotime($endTime)),
];
$params['sign'] = $this->createSign($time);
$result = doFormCurl($this->apiDomain.'/api/acc/getTransactionLog',$params);
if ($result['code'] != 0) {
throw new GameException($result['msg'], 0);
}
return $result['walletLogDTO'];
}
/**
* 查询游戏纪录
* @param string $startTime
* @param string $endTime
* @return array
* @throws GameException
* @throws \think\Exception
*/
public function getGameRecordList(string $startTime = '', string $endTime = ''): array
{
$time = time();
$params = [
'api_id' => $this->appId,
'timestamp' => $time,
'date_from' => $startTime,
'date_to' => $endTime,
];
$params['sign'] = $this->createSign($time);
$result = doFormCurl($this->apiDomain.'/api/acc/getGameLog',$params);
if ($result['code'] != 0) {
throw new GameException($result['msg'], 0);
}
return $result['userGameLogDTO'];
}
/**
* 查询玩家游戏记录
* @return array
*/
public function handleOrderHistories(): array
{
try {
$list = [];
$startTime = date('d/m/Y H:i:s', strtotime('-3 minutes'));
$endTime = date('d/m/Y H:i:s', strtotime('-2 minutes'));
$data = $this->getGameRecordList($startTime, $endTime);
if (!empty($data)) {
foreach ($data as $item) {
$list[] = [
'uuid' => $item['loginId'],
'platform_id' => $this->platform->id,
'game_code' => $item['gameCode'],
'bet' => $item['betAmount'],
'win' => bcadd($item['betAmount'], $item['winAmount'], 2),
'order_no' => $item['logId'],
'original_data' => json_encode($item,JSON_UNESCAPED_UNICODE),
'platform_action_at' => date('Y-m-d H:i:s', $item['createdDate']/1000),
'game_type' => $item['gameTypeId'],
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
];
}
}
} catch (Exception $e) {
return [];
}
return $list;
}
}

View File

@@ -0,0 +1,472 @@
<?php
namespace app\service\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 MeGa888ServiceInterface extends GameServiceFactory implements GameServiceInterface
{
public $method = 'POST';
private $apiDomain;
private $appId;
public $appSecret;
private $sn;
public $loginId;
public $password;
public $gameType = [
'2' => 'Casino',
'5' => 'Fishing',
'8' => 'Bingo',
'1' => 'Slot',
];
public $localGameType = [
'2' => '2',//赌场
'5' => '4',//捕鱼
'8' => '8',//宾果
'1' => '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' => '系統錯誤',
];
/**
* @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->appSecret = $config['app_secret'];
$this->sn = $config['sn'];
$this->platform = GamePlatform::query()->where('name', $type)->first();
if (!empty($player)) {
$this->player = $player;
$this->getLoginId();
}
}
/**
* 生成请求url
* @return string
*/
public function createUrl(): string
{
return $this->apiDomain;
}
//生成签名
public function createSign($params): string
{
$str = '';
foreach ($params as $v) {
$str .= $v;
}
return md5($str);
}
/**
* 生成请求数据
* @param $postData
* @param $method
* @return array
*/
function buildParams($postData, $method): array
{
return array(
"jsonrpc" => "2.0",
"method" => $method,
"params" => $postData,
"id" => $this->player->uuid ?? uniqid()
);
}
/**
* 获取下载地址
* @throws GameException|\think\Exception
*/
public function getDownload()
{
$params = [
'random' => $this->player->uuid ?? uniqid(),
'sn' => $this->sn,
'secretCode' => $this->appSecret,
];
$params['digest'] = $this->createSign($params);
$params['agentLoginId'] = $this->appId;
$postData = $this->buildParams($params, 'open.mega.app.url.download');
$result = doCurl($this->apiDomain,$postData);
if(!empty($result['result'])){
return $result['result'];
}else{
throw new GameException($result['error']['message'], 0);
}
}
/**
* 更新游戏列表
* @return false
*/
public function getSimpleGameList(): bool
{
return false;
}
/**
* 获取玩家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)) {
$this->password = $playerGamePlatform->player_password;
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 = [
'random' => $data['uuid'] ?? uniqid(),
'sn' => $this->sn,
'secretCode' => $this->appSecret,
];
$params['digest'] = $this->createSign($params);
$params['agentLoginId'] = $this->appId;
$params['nickname'] = $data['name'];
$postData = $this->buildParams($params, 'open.mega.user.create');
$result = doCurl($this->apiDomain,$postData);
if (!empty($result['result']) && empty($result['error'])) {
$playerGamePlatform = new PlayerGamePlatform();
$playerGamePlatform->player_id = $this->player->id;
$playerGamePlatform->platform_id = $this->platform->id;
$playerGamePlatform->player_name = $data['name'];
$playerGamePlatform->player_code = $result['result']['loginId'];
$playerGamePlatform->player_password = uniqid();
$playerGamePlatform->save();
$this->loginId = $playerGamePlatform->player_code;
$this->password = $playerGamePlatform->player_password;
return $result;
}else{
throw new GameException($result['error']['message'], 0);
}
}
/**
* 获取玩家信息
* @return array|mixed|Response
* @throws GameException|Exception
*/
public function getPlayer()
{
$params = [
'random' => $this->player->uuid ?? uniqid(),
'sn' => $this->sn,
'loginId' => $this->loginId,
'secretCode' => $this->appSecret,
];
$params['digest'] = $this->createSign($params);
$postData = $this->buildParams($params, 'open.mega.user.get');
$result = doCurl($this->apiDomain,$postData);
if (!empty($result['result']) && empty($result['error'])) {
return $result;
}else{
throw new GameException($result['error']['message'], 0);
}
}
/**
* 玩家进入游戏
* @param array $data
* @return array
* @throws GameException
* @throws \think\Exception
*/
public function login(array $data = []): array
{
return ['url' => $this->getDownload(), 'account' => $this->loginId, 'password' => $this->password];
}
/**
* 获取玩家游戏平台余额
* @throws GameException|\think\Exception
*/
public function getBalance()
{
$params = [
'random' => $this->player->uuid ?? uniqid(),
'sn' => $this->sn,
'loginId' => $this->loginId,
'secretCode' => $this->appSecret,
];
$params['digest'] = $this->createSign($params);
$postData = $this->buildParams($params, 'open.mega.balance.get');
$result = doCurl($this->apiDomain,$postData);
if (empty($result['error'])) {
return $result['result'];
}else{
throw new GameException('MeGa888 System Error,Please contact the administrator', 0);
}
}
/**
* 玩家钱包转入游戏平台
* @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->getBalance() == 0){
// 记录玩家钱包转出转入记录
$this->createWalletTransfer(PlayerWalletTransfer::TYPE_IN, 0, 0);
return true;
}
return $this->autoTransfer();
}
/**
* 轉帳進出額度
* @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 = [
'random' => $this->player->uuid ?? uniqid(),
'sn' => $this->sn,
'loginId' => $this->loginId,
'amount' => $amount,
'secretCode' => $this->appSecret,
];
$params['digest'] = $this->createSign($params);
$postData = $this->buildParams($params, 'open.mega.balance.transfer');
$result = doCurl($this->apiDomain,$postData);
if (!empty($result['error'])) {
throw new GameException($result['error']['message'], 0);
}
// 记录玩家钱包转出转入记录
$this->createWalletTransfer($type, $amount, $reward);
return $result;
}
/**
* 自动下分
* @return array|mixed|null
* @throws GameException|\think\Exception
*/
public function autoTransfer()
{
$params = [
'random' => $this->player->uuid ?? uniqid(),
'sn' => $this->sn,
'loginId' => $this->loginId,
'secretCode' => $this->appSecret,
];
$params['digest'] = $this->createSign($params);
$postData = $this->buildParams($params, 'open.mega.balance.auto.transfer.out');
$result = doCurl($this->apiDomain,$postData);
if (!empty($result['error'])) {
throw new GameException($result['error']['message'], 0);
}
// 记录玩家钱包转出转入记录
$this->createWalletTransfer(PlayerWalletTransfer::TYPE_IN, $result['result'], 0);
return $result;
}
/**
* 查询额度转移纪录
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getTransferList(string $startTime = '', string $endTime = '', int $page = 1, int $pageSize = 15)
{
$params = [
'random' => $this->player->uuid ?? uniqid(),
'sn' => $this->sn,
'secretCode' => $this->appSecret,
];
$params['digest'] = $this->createSign($params);
$params['loginId'] = $this->loginId;
$params['agentLoginId'] = $this->appId;
$params['startTime'] = $startTime;
$params['endTime'] = $endTime;
$params['timeZone'] = 1;
$postData = $this->buildParams($params, 'open.mega.balance.transfer.query');
$result = doCurl($this->apiDomain,$postData);
if (!empty($result['error'])) {
throw new GameException($result['error']['message'], 0);
}
return $result;
}
/**
* 查询玩家游戏记录
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getUserGameRecord(string $startTime = '', string $endTime = '')
{
$params = [
'random' => $this->player->uuid ?? uniqid(),
'sn' => $this->sn,
'loginId' => $this->loginId,
'secretCode' => $this->appSecret,
];
$params['digest'] = $this->createSign($params);
$params['startTime'] = $startTime;
$params['endTime'] = $endTime;
$params['timeZone'] = 1;
$postData = $this->buildParams($params, 'open.mega.player.game.log.url.get');
$result = doCurl($this->apiDomain,$postData);
if (!empty($result['error'])) {
throw new GameException($result['error']['message'], 0);
}
return $result['result'];
}
/**
* 查询全部玩家账单
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getReportRecord(string $startTime = '', string $endTime = '')
{
$params = [
'random' => $this->player->uuid ?? uniqid(),
'sn' => $this->sn,
'agentLoginId' => $this->appId,
'secretCode' => $this->appSecret,
];
$params['digest'] = $this->createSign($params);
$params['startTime'] = $startTime;
$params['endTime'] = $endTime;
$params['timeZone'] = 1;
$params['type'] = 1;
$postData = $this->buildParams($params, 'open.mega.player.total.report');
$result = doCurl($this->apiDomain,$postData);
if (!empty($result['error'])) {
throw new GameException($result['error']['message'], 0);
}
return $result['result'];
}
/**
* 获取电子游戏注单分页列表
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getGameOrderById(string $startTime = '', string $endTime = '')
{
$params = [
'random' => $this->player->uuid ?? uniqid(),
'sn' => $this->sn,
'loginId' => $this->loginId,
'secretCode' => $this->appSecret,
];
$params['digest'] = $this->createSign($params);
$params['startTime'] = $startTime;
$params['endTime'] = $endTime;
$params['timeZone'] = 1;
$postData = $this->buildParams($params, 'open.mega.game.order.page');
$result = doCurl($this->apiDomain,$postData);
if (!empty($result['error'])) {
throw new GameException($result['error']['message'], 0);
}
return $result;
}
/**
* 查询玩家游戏记录
* @return array
*/
public function handleOrderHistories(): array
{
try {
$list = [];
$startTime = date('Y-m-d');
$endTime = date('Y-m-d');
$data = $this->getReportRecord($startTime, $endTime);
if (!empty($data)) {
foreach ($data as $item) {
$list[] = [
'player_code' => $item['loginId'],
'platform_id' => $this->platform->id,
'game_code' => 'MeGa888',
'bet' => $item['bet'],
'win' => $item['win'],
'order_no' => $item['userId'].date('Ymd'),
'original_data' => json_encode($item,JSON_UNESCAPED_UNICODE),
'platform_action_at' => $startTime,
'game_type' => 1,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
];
}
}
} catch (Exception $e) {
return [];
}
return $list;
}
}

View File

@@ -0,0 +1,444 @@
<?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\Log;
use support\Response;
class MonkeyKingServiceInterface extends GameServiceFactory implements GameServiceInterface
{
public $method = 'POST';
public $successCode = 'S100';
public $loginId;
public $gameType = [
'10' => 'Slot',
'12' => 'Casino',
'13' => 'Arcade',
'16' => 'Fishing'
];
public $failCode = [
'S200' => '重復請求',
'150001' => '無效的簽名',
'150002' => '無效的SN',
'150003' => '無效的參數',
'150004' => '無效的貨幣',
'150005' => '玩家已存在',
'150006' => '玩家不存在',
'150007' => '次级代理不存在',
'150008' => '執行失敗',
'150009' => '無效的方法',
'150010' => '無效的用戶狀態',
'150011' => '玩家狀態無需更新',
'150012' => '超出數據範圍',
'150013' => '無匹配數據',
'150014' => '登入位置被禁止',
'150015' => '分數不足夠',
'150016' => '不支持禮碼',
'150017' => '交易流水號不得重複',
'150018' => '系統繁忙',
'150019' => '日期時間各式錯誤',
'150020' => '超出時間限制範圍開始時間與結束時間之間不能大於120分鐘',
];
private $apiDomain;
private $domain;
private $appId;
private $appSecret;
private $path = [
'createPlayer' => '/UserInfo/CreatePlayer',
'getPlayer' => '/UserInfo/GetPlayer',
'getGameList' => '/Game/GetGameList',
'getSimpleGameList' => '/Game/GetSimpleGameList',
'getLoginH5' => '/UserInfo/GetLoginH5',
'setPlayerStatus' => '/UserInfo/SetPlayerStatus',
'getBalance' => '/Account/GetBalance',
'setBalanceTransfer' => '/Account/SetBalanceTransfer',
'getGameRecordByTime' => '/Game/GetGameRecordByTime',
'getGameRecord' => '/Game/GetGameRecord',
'removeRecords' => '/Game/RemoveRecords',
];
private $lang = [
'zh-CN' => 'zh-ch',
'en' => 'en_us',
'zh_tc' => 'zh_tc',
'en-us' => 'en-us',
'id' => 'id',
'th' => 'th',
'my' => 'my',
'vi' => 'vi',
'fi_fi' => 'fi_fi',
'kr_ko' => 'kr_ko',
'hi_hi' => 'hi_hi',
'br_po' => 'br_po',
'lo_la' => 'lo_la',
'cam_dia' => 'en_us', // 柬埔寨语
];
/**
* @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();
}
}
/**
* @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|\think\Exception
*/
public function createPlayer(array $data = [])
{
$params = [
'ID' => createOrderNo(),
'Method' => 'CreatePlayer',
'SN' => $this->appId,
'PlayerCode' => $data['uuid'],
];
$params['Signature'] = $this->createSign($params);
$params['PlayerName'] = $data['uuid'];
Log::info('MonkeyKing请求参数', [$params]);
$res = doCurl($this->createUrl('createPlayer'), $params);
Log::info('MonkeyKing请求返回数据', [$res]);
if ($res['code'] != $this->successCode) {
throw new GameException($this->failCode[$res['code']], 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 createSign($params): string
{
return md5(implode('', $params) . $this->appSecret);
}
/**
* 生成请求url
* @param $method
* @return string
*/
public function createUrl($method): string
{
return $this->apiDomain . $this->path[$method];
}
/**
* 创建玩家
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getPlayer()
{
$params = [
'ID' => createOrderNo(),
'Method' => 'GetPlayer',
'SN' => $this->appId,
'LoginId' => $this->loginId,
];
$params['Signature'] = $this->createSign($params);
Log::info('MonkeyKing请求参数', [$params]);
$data = doCurl($this->createUrl('getPlayer'), $params);
Log::info('MonkeyKing请求返回数据', [$data]);
if ($data['code'] != $this->successCode) {
throw new GameException($this->failCode[$data['code']], 0);
}
return $data;
}
/**
* 获取游戏摘要MD5 (id+method+sn+APlSecretKey)
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getSimpleGameList()
{
$params = [
'ID' => createOrderNo(),
'Method' => 'GetSimpleGameList',
'SN' => $this->appId,
];
$params['Signature'] = $this->createSign($params);
Log::info('MonkeyKing请求参数', [$params]);
$data = doCurl($this->createUrl('getSimpleGameList'), $params);
Log::info('MonkeyKing请求返回数据', [$data]);
if ($data['code'] != $this->successCode) {
throw new GameException($this->failCode[$data['code']], 0);
}
if (!empty($data['data']['games'])) {
foreach ($data['data']['games'] as $game) {
Game::query()->updateOrCreate(
[
'platform_id' => $this->platform->id,
'game_code' => $game['gameCode'],
'platform_game_type' => $game['type'],
]
);
}
}
return $data;
}
/**
* 获取游戏摘要MD5 (id+method+sn+APlSecretKey)
* @param array $data
* @return string
* @throws GameException|\think\Exception
*/
public function login(array $data = []): string
{
$params = [
'ID' => createOrderNo(),
'Method' => 'GetLoginH5',
'SN' => $this->appId,
'LoginId' => $this->loginId,
];
$params['Signature'] = $this->createSign($params);
Log::info('MonkeyKing请求参数', [$params]);
$res = doCurl($this->createUrl('getLoginH5'), $params);
Log::info('MonkeyKing请求返回数据', [$res]);
if ($res['code'] != $this->successCode) {
throw new GameException($this->failCode[$res['code']], 0);
}
$responseH5 = [
'Language' => $this->lang[$data['lang']] ?? 'ch',
"GameId" => $data['gameCode'],
'CallbackAddress' => $data['callBackUrl'] ?? '',
"AppType" => $data['appType'] ?? 1,
"DeviceType" => 1,
];
$jsonString = json_encode($responseH5);
$parametersValue = base64_encode($jsonString);
return $this->domain . '/linkgame' . ($res['data']['loginUrl'] ?? '') . '&' . $parametersValue . '&' . $data['gameCode'];
}
/**
* 設置登入玩家狀態。當玩家處於禁用狀態,該玩家無法在平台進行任何操作,如果玩家在遊戲進行中該玩家將會自動退出遊戲。
* 簽名密鑰方式 Md5(Id+Method+SN+LoginId+APISecretKey)
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function setPlayerStatus($status)
{
$params = [
'ID' => createOrderNo(),
'Method' => 'GetSimpleGameList',
'SN' => $this->appId,
'LoginId' => $this->loginId,
];
$params['Signature'] = $this->createSign($params);
$params['Status'] = $status;
Log::info('MonkeyKing请求参数', [$params]);
$data = doCurl($this->createUrl('setPlayerStatus'), $params);
Log::info('MonkeyKing请求返回数据', [$data]);
if ($data['code'] != $this->successCode) {
throw new GameException($this->failCode[$data['code']], 0);
}
return $data;
}
/**
* 玩家钱包转入游戏平台
* @return array|mixed|null
* @throws GameException|\think\Exception
*/
public function balanceTransferOut()
{
return $this->setBalanceTransfer(PlayerWalletTransfer::TYPE_OUT, $this->player->wallet->money);
}
/**
* 轉帳進出額度
* 簽名密鑰方式 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 = [
'ID' => createOrderNo(),
'Method' => 'SetBalanceTransfer',
'SN' => $this->appId,
'LoginId' => $this->loginId,
];
$params['Signature'] = $this->createSign($params);
$params['Amount'] = $amount;
$params['Reward'] = $reward;
Log::info('MonkeyKing请求参数', [$params]);
$res = doCurl($this->createUrl('setBalanceTransfer'), $params);
Log::info('MonkeyKing请求返回数据', [$res]);
if ($res['code'] != $this->successCode) {
Log::error($this->failCode[$res['code']], ['res' => $res]);
throw new GameException($this->failCode[$res['code']], 0);
}
// 记录玩家钱包转出转入记录
$this->createWalletTransfer($type, $amount, $reward, $res['data']['refId'] ?? '');
return $res;
}
/**
* 玩家钱包转入游戏平台
* @return array|mixed|null
* @throws GameException|\think\Exception
*/
public function balanceTransferIn()
{
$balance = $this->getBalance();
return $this->setBalanceTransfer(PlayerWalletTransfer::TYPE_IN, !empty($balance['data']['result']) ? -$balance['data']['result'] : 0, !empty($balance['data']['reward']) ? -$balance['data']['reward'] : 0);
}
/**
* 獲取玩家餘額信息
* 簽名密鑰方式 MD5 (Id+Method+SN+LoginId+APISecretKey)
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getBalance()
{
$params = [
'ID' => createOrderNo(),
'Method' => 'GetBalance',
'SN' => $this->appId,
'LoginId' => $this->loginId,
];
$params['Signature'] = $this->createSign($params);
Log::info('MonkeyKing请求参数', [$params]);
$data = doCurl($this->createUrl('getBalance'), $params);
Log::info('MonkeyKing请求返回数据', [$data]);
if ($data['code'] != $this->successCode) {
throw new GameException($this->failCode[$data['code']], 0);
}
return $data;
}
/**
* 依據時間獲取遊戲紀錄
* 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(int $pageIndex = 1, string $startTime = '', string $endTime = '')
{
$params = [
'ID' => createOrderNo(),
'Method' => 'GetGameRecordByTime',
'SN' => $this->appId,
'StartTime' => $startTime,
'EndTime' => $endTime,
];
$pageSize = 500;
$params['Signature'] = $this->createSign($params);
$params['PageSize'] = $pageSize;
$params['PageIndex'] = $pageIndex;
Log::info('MonkeyKing请求参数', [$params]);
$res = doCurl($this->createUrl('getGameRecordByTime'), $params);
Log::info('MonkeyKing请求返回数据', [$res]);
if ($res['code'] != $this->successCode) {
throw new GameException($this->failCode[$res['code']], 0);
}
return $res;
}
/**
* 獲取玩家遊戲歷史紀錄
* MD5 (Id+Method+SN+APISecretKey)
* @return array|mixed|null
* @throws GameException|\think\Exception
*/
public function getGameRecord()
{
$params = [
'ID' => createOrderNo(),
'Method' => 'GetGameRecord',
'SN' => $this->appId,
];
$params['Signature'] = $this->createSign($params);
Log::info('MonkeyKing请求参数', [$params]);
$res = doCurl($this->createUrl('getGameRecord'), $params);
Log::info('MonkeyKing请求返回数据', [$res]);
if ($res['code'] != $this->successCode) {
throw new GameException($this->failCode[$res['code']], 0);
}
return $res;
}
/**
* 刪除遊戲紀錄
* MD5 (Id+Method+SN+IdsToBeRemoved+APISecretKey)
* @return array|mixed|null
* @throws GameException|\think\Exception
*/
public function removeRecords($idsToBeRemoved)
{
$params = [
'ID' => createOrderNo(),
'Method' => 'RemoveRecords',
'SN' => $this->appId,
'IdsToBeRemoved' => implode(',', $idsToBeRemoved),
];
$params['Signature'] = $this->createSign($params);
Log::info('MonkeyKing请求参数', [$params]);
$res = doCurl($this->createUrl('removeRecords'), $params);
Log::info('MonkeyKing请求返回数据', [$res]);
if ($res['code'] != $this->successCode) {
throw new GameException($this->failCode[$res['code']], 0);
}
return $res;
}
}

View File

@@ -0,0 +1,504 @@
<?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\Log;
use support\Response;
class NextSpinServiceInterface extends GameServiceFactory implements GameServiceInterface
{
public $method = 'POST';
private $apiDomain;
private $domain;
private $appId;
private $appSecret;
private $path = [
'ListGames' => 'ListGames',//获取游戏列表
'createPlayer' => '/UserInfo/CreatePlayer',
'getPlayer' => '/UserInfo/GetPlayer',
'getGameList' => '/Game/GetGameList',
'getSimpleGameList' => '/Game/GetSimpleGameList',
'getLoginH5' => '/UserInfo/GetLoginH5',
'setPlayerStatus' => '/UserInfo/SetPlayerStatus',
'getBalance' => '/Account/GetBalance',
'setBalanceTransfer' => '/Account/SetBalanceTransfer',
'getGameRecordByTime' => '/Game/GetGameRecordByTime',
'getGameRecord' => '/Game/GetGameRecord',
'removeRecords' => '/Game/RemoveRecords',
];
public $successCode = 'S100';
public $loginId;
public $gameType = [
'AD' => 'Casino',
'SM' => 'Fishing',
];
public $localGameType = [
'AD' => '2',
'SM' => '4',
];
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();
}
}
public function httpRequest($url,$api,$method = 'POST',$fields)
{
$fields = json_encode(["merchantCode"=> "ZCH6747",
"serialNo"=>"20240722224255982841"]);
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_POSTFIELDS => $fields,
CURLOPT_HTTPHEADER => [
"API: $api",
"Accept: */*",
"Accept-Encoding: gzip, deflate, br",
"Connection: keep-alive",
"Content-Type: application/json",
"DataType: JSON",
"User-Agent: PostmanRuntime-ApipostRuntime/1.1.0"
],
]);
$response = curl_exec($curl);
curl_close($curl);
$data = json_decode($response,true);
return $data;
}
/**
* 更新游戏列表
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getSimpleGameList()
{
$api = 'getGames';
$method = 'POST';
$serialNo = createOrderNo();
$fields = json_encode([
"merchantCode" => $this->appId,
"serialNo" => $serialNo
]);
$result = $this->httpRequest($this->apiDomain,$api,$method,$fields);
if (isset($result['games']) && $result['code'] == 0) {
foreach ($result['games'] as $game) {
Game::query()->updateOrCreate(
[
'platform_id' => $this->platform->id,
'game_code' => $game['gameCode'],
],
[
'platform_game_type' => $game['category'],
'game_type' => $this->localGameType[$game['category']],
'name' => $game['gameName'],
]
);
}
}else{
throw new GameException($result['msg'], 0);
}
return $result;
}
/**
* 获取游戏列表
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getGamesList()
{
$api = 'getGames';
$method = 'POST';
$serialNo = createOrderNo();
$fields = json_encode([
"merchantCode" => $this->appId,
"serialNo" => $serialNo
]);
$result = $this->httpRequest($this->apiDomain,$api,$method,$fields);
if (isset($result['games']) && $result['code'] == 0) {
return $result['games'];
}else{
throw new GameException($result['msg'], 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 = [
'ID' => createOrderNo(),
'Method' => 'CreatePlayer',
'SN' => $this->appId,
'PlayerCode' => $data['uuid'],
];
$params['Signature'] = $this->createSign($params);
$params['PlayerName'] = $data['uuid'];
$res = doCurl($this->createUrl('createPlayer'), $params);
if ($res['code'] != $this->successCode) {
throw new GameException($this->failCode[$res['code']], 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;
}
/**
* 获取游戏摘要MD5 (id+method+sn+APlSecretKey)
* @param array $data
* @return string
* @throws GameException|\think\Exception
*/
public function login(array $data = []): string
{
$params = [
'ID' => createOrderNo(),
'Method' => 'GetLoginH5',
'SN' => $this->appId,
'LoginId' => $this->loginId,
];
$params['Signature'] = $this->createSign($params);
$res = doCurl($this->createUrl('getLoginH5'), $params);
if ($res['code'] != $this->successCode) {
Log::error($this->failCode[$res['code']], ['res' => $res]);
throw new GameException($this->failCode[$res['code']], 0);
}
$responseH5 = [
'Language' => $this->lang[$data['lang']] ?? 'ch',
"GameId" => $data['gameCode'],
'CallbackAddress' => $data['callBackUrl'] ?? '',
"AppType" => $data['appType'] ?? 1,
"DeviceType" => 1,
];
$jsonString = json_encode($responseH5);
$parametersValue = base64_encode($jsonString);
$link = $this->domain . '/linkgame' . ($res['data']['loginUrl'] ?? '') . '&' . $parametersValue;
if (!empty($data['gameCode'])) {
$link .= '&' . $data['gameCode'];
}
return $link;
}
/**
* 設置登入玩家狀態。當玩家處於禁用狀態,該玩家無法在平台進行任何操作,如果玩家在遊戲進行中該玩家將會自動退出遊戲。
* 簽名密鑰方式 Md5(Id+Method+SN+LoginId+APISecretKey)
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function setPlayerStatus($status)
{
$params = [
'ID' => createOrderNo(),
'Method' => 'GetSimpleGameList',
'SN' => $this->appId,
'LoginId' => $this->loginId,
];
$params['Signature'] = $this->createSign($params);
$params['Status'] = $status;
$data = doCurl($this->createUrl('setPlayerStatus'), $params);
if ($data['code'] != $this->successCode) {
throw new GameException($this->failCode[$data['code']], 0);
}
return $data;
}
/**
* 獲取玩家餘額信息
* 簽名密鑰方式 MD5 (Id+Method+SN+LoginId+APISecretKey)
* @return array|mixed|Response
* @throws GameException|\think\Exception
*/
public function getBalance()
{
$params = [
'ID' => createOrderNo(),
'Method' => 'GetBalance',
'SN' => $this->appId,
'LoginId' => $this->loginId,
];
$params['Signature'] = $this->createSign($params);
$data = doCurl($this->createUrl('getBalance'), $params);
if ($data['code'] != $this->successCode) {
throw new GameException($this->failCode[$data['code']], 0);
}
return $data;
}
/**
* 玩家钱包转入游戏平台
* @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();
return $this->setBalanceTransfer(PlayerWalletTransfer::TYPE_IN, !empty($balance['data']['result']) ? -$balance['data']['result'] : 0, !empty($balance['data']['reward']) ? -$balance['data']['reward'] : 0);
}
/**
* 轉帳進出額度
* 簽名密鑰方式 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 = [
'ID' => createOrderNo(),
'Method' => 'SetBalanceTransfer',
'SN' => $this->appId,
'LoginId' => $this->loginId,
];
$params['Signature'] = $this->createSign($params);
$params['Amount'] = $amount;
$params['Reward'] = $reward;
$res = doCurl($this->createUrl('setBalanceTransfer'), $params);
if ($res['code'] != $this->successCode) {
throw new GameException($this->failCode[$res['code']], 0);
}
// 记录玩家钱包转出转入记录
$this->createWalletTransfer($type, $amount, $reward, $res['data']['refId'] ?? '');
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(int $pageIndex = 1, string $startTime = '', string $endTime = '')
{
$params = [
'ID' => createOrderNo(),
'Method' => 'GetGameRecordByTime',
'SN' => $this->appId,
'StartTime' => $startTime,
'EndTime' => $endTime,
];
$pageSize = 500;
$params['Signature'] = $this->createSign($params);
$params['PageSize'] = $pageSize;
$params['PageIndex'] = $pageIndex;
$res = doCurl($this->createUrl('getGameRecordByTime'), $params);
if ($res['code'] != $this->successCode) {
throw new GameException($this->failCode[$res['code']], 0);
}
return $res;
}
/**
* 獲取玩家遊戲歷史紀錄
* MD5 (Id+Method+SN+APISecretKey)
* @return array|mixed|null
* @throws GameException|\think\Exception
*/
public function getGameRecord()
{
$params = [
'ID' => createOrderNo(),
'Method' => 'GetGameRecord',
'SN' => $this->appId,
];
$params['Signature'] = $this->createSign($params);
$res = doCurl($this->createUrl('getGameRecord'), $params);
if ($res['code'] != $this->successCode) {
throw new GameException($this->failCode[$res['code']], 0);
}
return $res;
}
/**
* 刪除遊戲紀錄
* MD5 (Id+Method+SN+IdsToBeRemoved+APISecretKey)
* @return array|mixed|null
* @throws GameException|\think\Exception
*/
public function removeRecords($idsToBeRemoved)
{
$params = [
'ID' => createOrderNo(),
'Method' => 'RemoveRecords',
'SN' => $this->appId,
'IdsToBeRemoved' => implode(',', $idsToBeRemoved),
];
$params['Signature'] = $this->createSign($params);
$res = doCurl($this->createUrl('removeRecords'), $params);
if ($res['code'] != $this->successCode) {
throw new GameException($this->failCode[$res['code']], 0);
}
return $res;
}
}

View File

@@ -0,0 +1,473 @@
<?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;
}
}