Files
jk8_admin/app/common/service/XyxServices.php

309 lines
9.5 KiB
PHP

<?php
namespace app\common\service;
use AllowDynamicProperties;
use app\admin\model\Config as ConfigModel;
use app\common\model\UserScoreLog;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Exception\RequestException;
use think\helper\Str;
#[AllowDynamicProperties] class XyxServices
{
public $method = 'POST';
private $domain;
private $appId;
private $appSecret;
private $player;
private $account;
private $password;
public $gameType = [
'ECasino' => 'Casino',
'Fishing' => 'Fishing',
'Bingo' => 'Bingo',
'Slot' => 'Slot',
];
public $localGameType = [
'slot' => '2',
'multiplayer' => '1',
'fishing' => '7',
'bet' => '5',
];
public $failCode = [
'0' => '应用不存在',
'1000' => '参数错误',
'1101' => '玩家账号',
'1102' => '密码',
'1103' => '玩家id',
'1204' => '金额',
'1205' => '开始时间',
'1206' => '结束时间',
'2001' => '渠道不存在',
'2100' => '用户错误',
'2102' => '用户已注册',
'2103' => '玩家不存在',
'2104' => '玩家已被停用',
'2205' => '钱包余额不足',
'2206' => '结束时间必须大于起始时间',
'2207' => '查询时间不能超过1小时',
'3000' => '系统错误',
'3201' => '钱包转出失败',
'3202' => '钱包转入失败',
'3902' => 'JWT清除失败',
];
public function __construct($player = null)
{
$config = ConfigModel::where('group', 'mini_games')->column('value', 'name');
$this->appId = $config['app_id'];
$this->appSecret = $config['app_secret'];
$this->domain = $config['domain'];
if (!empty($player)) {
$this->player = $player;
$this->account = $player['xyx_account'];
$this->password = $player['xyx_password'];
if (empty($this->account) || empty($this->password)) {
$this->createPlayer($player);
}
}
}
/**
* 生成请求
* @param $url
* @param array $params
* @return array|mixed
* @throws \Exception
*/
public function doXyxCurl($url, array $params = [])
{
$headers = [
'appId' => $this->appId,
'timestamp' => time(),
'nonceStr' => Str::random(6),
];
$data = array_merge($params,$headers);
ksort($data);
$signature = hash('sha256', urldecode(http_build_query($data)) . $this->appSecret);
$headers['signature'] = $signature;
$client = new Client([
'timeout' => 7,
'verify' => true,
]);
try {
$response = $client->post($url, [
'json' => $params, // 相当于 asJson(),会自动设置 Content-Type: application/json
'headers' => $headers,
]);
if ($response->getStatusCode() !== 200) {
throw new \Exception(lang('system_busy')); // ThinkPHP 使用 lang() 代替 trans()
}
$contents = $response->getBody()->getContents();
$data = json_decode($contents, true);
if (empty($data)) {
throw new \Exception(lang('system_busy'));
}
return $data;
} catch (GuzzleException $e) {
// 请求失败(如超时、证书错误等)
throw new \Exception(lang('system_busy'));
}
}
/**
* 获取token
*/
public function getToken($gameId)
{
$params = [
'account' => $this->account,
'password' => $this->password,
'game_id' => $gameId,
];
$res = $this->doXyxCurl($this->domain . 'agent/api/get-access-token', $params);
if ($res['code'] != 200) {
throw new \Exception($this->failCode[$res['code']]);
}
return $res['data']['access_token'];
}
/**
* 创建玩家
*/
public function createPlayer($player)
{
$params = [
'account' => 'jk' . $player['jk_user_id'],
'password' => Str::random(12),
];
$res = $this->doXyxCurl($this->domain . 'agent/api/create-player', $params);
if ($res['code'] != 200) {
throw new \Exception($this->failCode[$res['code']]);
}
$player->xyx_account = $params['account'];
$player->xyx_password = $params['password'];
$player->save();
$this->account = $params['account'];
$this->password = $params['password'];
return $res;
}
/**
* 玩家进入游戏
* @param array $data
* @return string
*/
public function login(array $data = []): string
{
$token = $this->getToken($data['gameCode']);
$out = UserScoreLog::where('user_id', $this->player->id)
->where('type', 2)
->whereNotNull('created_by')
->order('id', 'desc')
->find();
if ($out) {
$this->balanceTransferIn($out->game_type);
}
$this->balanceTransferOut($data['gameCode']);
$headers = [
'appId' => $this->appId,
'timestamp' => time(),
'nonceStr' => Str::random(6),
];
ksort($headers);
$signature = hash('sha256', urldecode(http_build_query($headers)) . $this->appSecret);
$headers['signature'] = $signature;
$headers['Authorization'] = 'Bearer ' . $token;
$client = new Client([
'timeout' => 7,
'allow_redirects' => false,
]);
try {
$response = $client->request('GET', $this->domain . 'agent/enter-game', [
'headers' => $headers,
]);
if ($response->getStatusCode() == 302) {
return $response->getHeader('Location')[0] ?? '';
}
} catch (RequestException $e) {
if ($e->hasResponse() && $e->getResponse()->getStatusCode() == 302) {
return $e->getResponse()->getHeader('Location')[0] ?? '';
}
}
return false;
}
/**
* 获取玩家游戏平台余额
*/
public function getBalance()
{
$params = [
'account' => $this->account,
];
$res = $this->doXyxCurl($this->domain . 'agent/api/get-player-info', $params);
if ($res['code'] != 200) {
throw new \Exception($this->failCode[$res['code']]);
}
return $res['data']['point'];
}
/**
* 玩家钱包转入游戏平台
*/
public function balanceTransferOut($gameType)
{
$score = $this->player->userScore()->where('game_type', $gameType)->value('score');
if ($score == 0) {
return true;
}
return $this->setBalanceTransfer(2, $gameType, $score);
}
/**
* 游戏平台转入玩家钱包
*/
public function balanceTransferIn($gameType)
{
$balance = $this->getBalance();
if ($balance == 0) {
$userScore = $this->player->userScore()->where('game_type', $gameType)->find();
$userScoreLog = new UserScoreLog();
$userScoreLog->save([
'user_id' => $this->player->id,
'game_type' => $gameType,
'before' => $userScore->score,
'after' => $userScore->score,
'score' => 0,
'memo' => '转入',
'type' => 1,
'created_by'=> 0,
]);
return true;
}
return $this->setBalanceTransfer(1, $gameType, $balance);
}
/**
* 轉帳進出額度
* @param $type
* @param float $amount
* @return array|mixed|null
* @throws \Exception
*/
protected function setBalanceTransfer($type,$gameType, float $amount = 0)
{
$yCode = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
$tradeno = $yCode[intval(date('Y')) - 2011] . strtoupper(dechex(date('m'))) . date('d') . substr(microtime(), 2, 5) . sprintf('%02d', rand(0, 99));
$params = [
'account' => $this->account,
'point' => $amount,
'tradeno' => $tradeno
];
if ($type == 2) {
$res = $this->doXyxCurl($this->domain . 'agent/api/transfer-in', $params);
} else {
$res = $this->doXyxCurl($this->domain . 'agent/api/transfer-out', $params);
}
if ($res['code'] != 200) {
throw new \Exception($this->failCode[$res['code']]);
}
$userScore = $this->player->userScore()->where('game_type', $gameType)->find();
$userScore->created_by = 0;
if ($type == 2) {
$userScore->score = 0;
$userScore->memo = '转出';
} else {
$userScore->score += $amount;
$userScore->memo = '转入';
}
$userScore->save();
return $res;
}
public function getReportRecord(string $startTime = '', string $endTime = '')
{
$params = [
'start_date' => $startTime,
'end_date' => $endTime,
];
$res = $this->doXyxCurl($this->domain . 'agent/api/draw-records-by-date', $params);
if ($res['code'] != 200) {
throw new \Exception($this->failCode[$res['code']]);
}
return $res['data'];
}
}