初始化

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

1379
app/functions.php Normal file
View File

@@ -0,0 +1,1379 @@
<?php
/**
* Here is your custom functions.
*/
use addons\webman\Admin;
use addons\webman\model\Channel;
use addons\webman\model\ChannelFinancialRecord;
use addons\webman\model\CommissionRecord;
use addons\webman\model\GamePlatform;
use addons\webman\model\PhoneSmsLog;
use addons\webman\model\Player;
use addons\webman\model\PlayerBankruptcyRecord;
use addons\webman\model\PlayerChipRecord;
use addons\webman\model\PlayerDeliveryRecord;
use addons\webman\model\PlayerExtend;
use addons\webman\model\PlayerLoginRecord;
use addons\webman\model\PlayerMoneyEditLog;
use addons\webman\model\PlayerPlatformCash;
use addons\webman\model\PlayerRechargeRecord;
use addons\webman\model\PlayerRegisterRecord;
use addons\webman\model\PlayerWalletTransfer;
use addons\webman\model\PlayerWithdrawRecord;
use addons\webman\model\PlayGameRecord;
use addons\webman\model\PromoterProfitSettlementRecord;
use addons\webman\model\SystemSetting;
use app\exception\GameException;
use app\exception\PlayerCheckException;
use app\service\game\GameServiceFactory;
use Carbon\Carbon;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Support\Arr;
use Respect\Validation\Exceptions\AllOfException;
use support\Cache;
use support\Db;
use support\Log;
use support\Model;
use support\Response;
use think\Exception;
use Tinywan\Jwt\JwtToken;
use Webman\Push\Api;
use Webman\Push\PushException;
use WebmanTech\LaravelHttpClient\Facades\Http;
use Workbunny\WebmanIpAttribution\Exceptions\IpAttributionException;
use Workbunny\WebmanIpAttribution\Location;
use addons\webman\model\PlayerPromoter;
use addons\webman\model\PromoterProfitRecord;
/**
* @param array $data
* @param string $message
* @return Response
*/
function jsonSuccessResponse(string $message = '', array $data = []): Response
{
return new Response(200, ['Content-Type' => 'application/json'], json_encode([
'code' => 200,
'msg' => $message,
'data' => $data,
], JSON_UNESCAPED_UNICODE));
}
/**
* @param array $data
* @param string $message
* @param integer $code
* @return Response
*/
function jsonFailResponse(string $message = '', array $data = [], int $code = 100): Response
{
return new Response(200, ['Content-Type' => 'application/json'], json_encode([
'code' => $code,
'msg' => $message,
'data' => $data,
], JSON_UNESCAPED_UNICODE));
}
/**
* 生成唯一邀请码
* @return string
*/
function createCode(): string
{
$code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$rand = $code[rand(0, 25)] . strtoupper(dechex(date('m'))) . date('d') . substr(time(), -5) . substr(microtime(), 2, 5) . sprintf('%02d', rand(0, 99));
for ($a = md5($rand, true), $s = '0123456789ABCDEFGHIJKLMNOPQRSTUV', $d = '', $f = 0; $f < 8; $g = ord($a[$f]), $d .= $s[($g ^ ord($a[$f + 8])) - $g & 0x1F], $f++) ;
return $d;
}
/**
* 获取验证消息
* @param AllOfException $e
* @return mixed
*/
function getValidationMessages(AllOfException $e)
{
$message = $e->getMessages([
'notOptional' => trans('required', [], 'validator'),
'notEmpty' => trans('required', [], 'validator'),
'email' => trans('email', [], 'validator'),
'idCard' => trans('idCard', [], 'validator'),
'url' => trans('url', [], 'validator'),
'number' => trans('number', [], 'validator'),
'integer' => trans('integer', [], 'validator'),
'float' => trans('float', [], 'validator'),
'mobile' => trans('mobile', [], 'validator'),
'length' => trans('length', [], 'validator'),
'alpha' => trans('alpha', [], 'validator'),
'alnum' => trans('alnum', [], 'validator'),
'alphaDash' => trans('alphaDash', [], 'validator'),
'chs' => trans('chs', [], 'validator'),
'chsAlpha' => trans('chsAlpha', [], 'validator'),
'chsAlphaNum' => trans('chsAlphaNum', [], 'validator'),
'chsDash' => trans('chsDash', [], 'validator'),
'equals' => trans('equals', [], 'validator'),
'in' => trans('in', [], 'validator'),
'image' => trans('image', [], 'validator'),
'creditCard' => trans('creditCard', [], 'validator'),
'digit' => trans('digit', [], 'validator'),
'base64' => trans('base64', [], 'validator'),
'arrayVal' => trans('arrayVal', [], 'validator'),
])['key'];
$message = is_array($message) ? Arr::first($message) : $message;
return $message ?? trans('validation_error', [], 'message');
}
/**
* 生成uuid
* @return string
*/
function gen_uuid(): string
{
do {
$timestamp = time();
$randomNumber = str_pad(rand(0, 9999), 4, '0', STR_PAD_LEFT);
$uniqueNumericId = substr($timestamp, -5) . $randomNumber;
} while (Player::query()->where('uuid', $uniqueNumericId)->withTrashed()->exists());
return $uniqueNumericId;
}
/**
* 金额转换
* @param $number
* @return float|int
*/
function floorToCoinsSecondNumber($number)
{
return floor($number * 100) / 100;
}
/**
* 添加用户登录信息
* @param $id
* @return PlayerLoginRecord|Model
*/
function addLoginRecord($id)
{
$ip = request()->getRealIp();
if (!empty($ip)) {
try {
$location = new Location();
$result = $location->getLocation($ip);
} catch (IpAttributionException $exception) {
Log::error('获取ip信息错误');
}
}
$country_name = ($result['country'] ?? '') . ($result['city'] ?? '');
$domain = isset($_SERVER['HTTP_ORIGIN']) ? parse_url($_SERVER['HTTP_ORIGIN']) : null;
return PlayerLoginRecord::create([
'player_id' => $id,
'login_domain' => !empty($domain) ? $domain['host'] : null,
'ip' => $ip,
'country_name' => $country_name,
'city_name' => $result['city'] ?? '',
'remark' => $request->remark ?? null,
'department_id' => request()->department_id,
]);
}
/**
* 添加用户注册信息
* @param $id
* @param $type
* @param $department_id
* @return PlayerRegisterRecord|Model
*/
function addRegisterRecord($id, $type, $department_id)
{
$ip = request()->getRealIp();
if (!empty($ip)) {
try {
$location = new Location();
$result = $location->getLocation($ip);
} catch (IpAttributionException $exception) {
Log::error('获取ip信息错误');
}
}
$country_name = ($result['country'] ?? '') . ($result['city'] ?? '');
$domain = isset($_SERVER['HTTP_ORIGIN']) ? parse_url($_SERVER['HTTP_ORIGIN']) : null;
return PlayerRegisterRecord::create([
'player_id' => $id,
'register_domain' => !empty($domain) ? $domain['host'] : null,
'ip' => $ip,
'country_name' => $country_name,
'city_name' => $result['city'] ?? '',
'device' => 'app',
'type' => $type,
'department_id' => $department_id,
]);
}
/**
* 保存头像到本地
* @param $avatar
* @return string
*/
function saveAvatar($avatar): string
{
if (empty($avatar)) {
return '';
}
try {
if (strpos($avatar, 'http://') === 0 || strpos($avatar, 'https://') === 0) {
$client = new Client(['verify' => false]); //忽略SSL错误
$fileName = md5($avatar) . '.jpg';
$path = public_path() . '/storage/avatar/';
if (!is_dir($path) && !mkdir($path, 0777, true)) {
throw new Exception('创建文件夹失败');
}
$client->request('GET', $avatar, ['sink' => public_path('/storage/avatar/' . $fileName)]);
} else {
throw new Exception('网络地址错误');
}
} catch (Exception|GuzzleException $e) {
Log::error('保存头像错误' . $e->getMessage());
return '';
}
return '/storage/avatar/' . $fileName;
}
/**
* 生成唯一单号
* @return string
*/
function createOrderNo(): string
{
$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'];
return $yCode[intval(date('Y')) - 2011] . strtoupper(dechex(date('m'))) . date('d') . substr(time(), -5) . substr(microtime(), 2, 5) . sprintf('%02d', rand(0, 99));
}
/**
* 设置短信key
* @param string $phone 手机号
* @param int $type 模式 1 为修改密码短信
* @return string
*/
function setSmsKey(string $phone, int $type): string
{
switch ($type) {
case PhoneSmsLog::TYPE_LOGIN:
return 'sms-login' . $phone;
case PhoneSmsLog::TYPE_REGISTER:
return 'sms-register' . $phone;
case PhoneSmsLog::TYPE_CHANGE_PASSWORD:
return 'sms-change-password' . $phone;
case PhoneSmsLog::TYPE_CHANGE_PAY_PASSWORD:
return 'sms-change-pay-password' . $phone;
case PhoneSmsLog::TYPE_CHANGE_PHONE:
return 'sms-change-phone' . $phone;
case PhoneSmsLog::TYPE_BIND_NEW_PHONE:
return 'sms-type-bind-new-phone' . $phone;
case PhoneSmsLog::TYPE_TALK_BIND:
return 'sms-type-talk-bind' . $phone;
default:
return 'sms-' . $phone;
}
}
/**
* 验证短信
* @param string $country_code 国家编号
* @param string $phone 手机号
* @param string $code 验证码
* @param int $type 类型
* @return string
*/
function verifySMS(string $country_code, string $phone, string $code, int $type): string
{
switch ($country_code) {
case PhoneSmsLog::COUNTRY_CODE_JP:
$phone = ltrim($phone, '0');
break;
case PhoneSmsLog::COUNTRY_CODE_MY:
$phone = ltrim($phone, '0');
break;
default:
break;
}
$phoneCode = Cache::get(setSmsKey($phone, $type));
return $phoneCode == $code;
}
/**
* 获取短信消息
* @param int $type 模式 1 为修改密码短信
* @param string $source 来源
* @return string
*/
function getContent(int $type, string $source): string
{
switch ($type) {
case PhoneSmsLog::TYPE_LOGIN:
return config($source . '-sms.login_content');
case PhoneSmsLog::TYPE_REGISTER:
return config($source . '-sms.register_content');
case PhoneSmsLog::TYPE_CHANGE_PASSWORD:
return config($source . '-sms.change_password_content');
case PhoneSmsLog::TYPE_CHANGE_PAY_PASSWORD:
return config($source . '-sms.change_pay_password');
case PhoneSmsLog::TYPE_CHANGE_PHONE:
return config($source . '-sms.change_phone');
case PhoneSmsLog::TYPE_BIND_NEW_PHONE:
return config($source . '-sms.bind_new_phone');
case PhoneSmsLog::TYPE_TALK_BIND:
return config($source . '-sms.talk_bind');
default:
return config($source . '-sms.sm_content');
}
}
/**
* 提现订单回滚
* @param PlayerWithdrawRecord $playerWithdrawRecord
* @param string $rejectReason
* @param int $withdrawStatus
* @return string
* @throws Exception
*/
function withdrawBack(PlayerWithdrawRecord $playerWithdrawRecord, string $rejectReason = '', int $withdrawStatus = PlayerWithdrawRecord::STATUS_PENDING_REJECT): string
{
DB::beginTransaction();
try {
// 更新提现订单
$playerWithdrawRecord->status = $withdrawStatus;
$playerWithdrawRecord->reject_reason = $rejectReason;
$playerWithdrawRecord->finish_time = date('Y-m-d H:i:s');
$playerWithdrawRecord->user_id = Admin::id() ?? 0;
$playerWithdrawRecord->user_name = !empty(Admin::user()) ? Admin::user()->username : '';
// 更新玩家钱包
$beforeGameAmount = $playerWithdrawRecord->player->wallet->money;
$playerWithdrawRecord->player->wallet->money = bcadd($playerWithdrawRecord->player->wallet->money, $playerWithdrawRecord->coins, 2);
// 跟新玩家统计
$playerWithdrawRecord->player->player_extend->withdraw_amount = bcsub($playerWithdrawRecord->player->player_extend->withdraw_amount, $playerWithdrawRecord->coins, 2);
$playerWithdrawRecord->push();
//寫入金流明細
$playerDeliveryRecord = new PlayerDeliveryRecord;
$playerDeliveryRecord->player_id = $playerWithdrawRecord->player_id;
$playerDeliveryRecord->department_id = $playerWithdrawRecord->department_id;
$playerDeliveryRecord->target = $playerWithdrawRecord->getTable();
$playerDeliveryRecord->target_id = $playerWithdrawRecord->id;
$playerDeliveryRecord->type = PlayerDeliveryRecord::TYPE_WITHDRAWAL_BACK;
$playerDeliveryRecord->source = 'withdraw_back';
$playerDeliveryRecord->amount = $playerWithdrawRecord->coins;
$playerDeliveryRecord->amount_before = $beforeGameAmount;
$playerDeliveryRecord->amount_after = $playerWithdrawRecord->player->wallet->money;
$playerDeliveryRecord->tradeno = $playerWithdrawRecord->tradeno ?? '';
$playerDeliveryRecord->remark = $playerWithdrawRecord->remark ?? '';
$playerDeliveryRecord->save();
DB::commit();
sendSocketMessage('private-recharge_withdrawal', [
'msg_type' => 'withdrawal',
'player_id' => $playerWithdrawRecord->player_id,
'amount' => $playerWithdrawRecord->player->wallet->money,
]);
} catch (\Exception $e) {
DB::rollBack();
throw new Exception($e->getMessage());
}
return true;
}
/**
* 添加渠道财务操作
* @param $target
* @param $action
* @return void
*/
function saveChannelFinancialRecord($target, $action)
{
$channelFinancialRecord = new ChannelFinancialRecord();
$channelFinancialRecord->action = $action;
$channelFinancialRecord->department_id = Admin::user()->department_id ?? 0;
$channelFinancialRecord->player_id = $target->player_id ?? 0;
$channelFinancialRecord->target = $target->getTable();
$channelFinancialRecord->target_id = $target->id;
$channelFinancialRecord->user_id = Admin::id() ?? 0;
$channelFinancialRecord->tradeno = $target->tradeno ?? '';
$channelFinancialRecord->user_name = Admin::user()->username ?? '';
$channelFinancialRecord->save();
}
/**
* 上传base64图片
* @param $img
* @param $path
* @return false|string
*/
function uploadBaseImg($img, $path)
{
if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $img, $result)) {
$type = $result[2];//图片后缀
$savePath = '/storage/' . $path . '/' . date("Ymd", time()) . "/";
$newPath = public_path() . $savePath;
if (!file_exists($newPath)) {
//检查是否有该文件夹,如果没有就创建,并给予最高权限
mkdir($newPath, 0755, true);
}
$filename = time() . '_' . uniqid() . ".{$type}"; //文件名
$newPath = $newPath . $filename;
//写入操作
if (file_put_contents($newPath, base64_decode(str_replace($result[1], '', $img)))) {
return env('APP_URL', 'http://127.0.0.1:8787') . $savePath . $filename;
}
return false;
}
return false;
}
/**
* 检查充值订单取消超时订单
* @throws Exception
*/
function cancelRecharge()
{
/** @var SystemSetting $setting */
$setting = SystemSetting::where('status', 1)->where('feature', 'recharge_order_expiration')->first();
if (!empty($setting)) {
$playerRechargeRecord = PlayerRechargeRecord::where('type', PlayerRechargeRecord::TYPE_REGULAR)
->where('status', PlayerRechargeRecord::STATUS_WAIT)
->where('created_at', '<', Carbon::now()->subMinutes($setting->num))
->get();
/** @var PlayerRechargeRecord $order */
foreach ($playerRechargeRecord as $order) {
$order->status = PlayerRechargeRecord::STATUS_RECHARGED_SYSTEM_CANCEL;
$order->cancel_time = date('Y-m-d H:i:s');
$order->save();
}
}
}
/**
* 发送socket消息
* @param $channels
* @param $content
* @param string $form
* @return bool|string
* @throws PushException
*/
function sendSocketMessage($channels, $content, string $form = 'system')
{
try {
// 发送进入保留状态消息
$api = new Api(
config('plugin.webman.push.app.api'),
config('plugin.webman.push.app.app_key'),
config('plugin.webman.push.app.app_secret')
);
return $api->trigger($channels, 'message', [
'from_uid' => $form,
'content' => json_encode($content)
]);
} catch (Exception $e) {
Log::error('sendSocketMessage', [$e->getMessage()]);
return false;
}
}
/**
* 获取渠道信息
* @param $siteId
* @return array
*/
function getChannel($siteId): array
{
$cacheKey = "channel_" . $siteId;
$channel = Cache::get($cacheKey);
if (empty($channel)) {
$channel = Channel::where('id', $siteId)->whereNull('deleted_at')->first()->toArray();
if (!empty($channel)) {
$cacheKey = "channel_" . $channel->site_id;
Cache::set($cacheKey, $channel->toArray());
} else {
return [];
}
}
return $channel;
}
/**
* 获取堆栈信息
* @return void
*/
function getStackList(): void
{
$line = [];
$debugList = array_reverse(debug_backtrace());
foreach ($debugList as $key => $val) {
$class = $val['class'] ?? "";
$arg = $val['args'];
$parameter = '';
$stringLine = '';
if (!empty($arg) && is_array($arg)) {
foreach ($arg as $v) {
$className = $v;
if (is_object($v)) {
$className = get_class($v);
} elseif (is_array($v)) {
$className = json_encode($v);
}
$parameter .= $className . ',';
}
}
$stringLine .= '程序执行' . $key . ':=>';
$stringLine .= '[1.所在文件(' . $val['file'] . ']';
$stringLine .= '[2.函数调用情况[第' . $val['line'] . '行]' . $class . '->' . $val['function'] . '(' . $parameter . ')]' . "\n";
$line[] = $stringLine;
}
Log::error("堆栈信息", $line);
}
/**
* 获取毫秒级
* @return float
*/
function millisecond(): float
{
list($millisecond, $sec) = explode(' ', microtime());
return (float)sprintf('%.0f', (floatval($millisecond) + floatval($sec)) * 1000);
}
/**
* 创建玩家
* @param $departmentId
* @param $data
* @return Player
* @throws Exception
*/
function createPlayer($departmentId, $data): Player
{
/** @var Channel $channel */
$channel = Channel::where('department_id', $departmentId)->first();
if (empty($channel)) {
throw new Exception(trans('channel_not_found', [], 'message'));
}
DB::beginTransaction();
try {
$count = Player::whereBetween('created_at', [date('Y-m-d') . ' 00:00:00', date('Y-m-d') . ' 23:59:59'])->count('*');
if (empty($data['avatar'])) {
$defAvatars = config('def_avatar') ?? [];
$randomKey = array_rand($defAvatars);
$randomAvatar = $defAvatars[$randomKey] ?? '';
} else {
$randomAvatar = $data['avatar'];
}
$player = new Player();
$player->uuid = gen_uuid();
$player->type = Player::TYPE_PLAYER;
$player->currency = $channel->currency;
$player->department_id = $channel->department_id;
$player->avatar = $randomAvatar;
$player->device_number = $data['device_number'] ?? '';
$player->name = $data['name'] ?? 'channel_' . $departmentId . date('Ymd') . $count;
$player->facebook_id = $data['facebook_id'] ?? '';
$player->phone = $data['phone'] ?? '';
if(isset($data['password'])){
$player->password = $data['password'];
}
if(isset($data['recommend_id'])){
$player->recommend_id = $data['recommend_id'];
}
$player->recommended_code = $data['recommended_code'] ?? '';
$player->status = Player::STATUS_ENABLE;
$player->recommend_code = createCode();
$player->save();
addPlayerExtend($player, [
'email' => $data['email'] ?? ''
]);
addRegisterRecord($player->id, PlayerRegisterRecord::TYPE_CLIENT, $player->department_id);
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
Log::error(trans('register_player_failed', [], 'message') . $e->getMessage());
throw new Exception();
}
unset($player->password);
return $player;
}
/**
* 增加玩家扩展信息
* @param Player $player
* @param array $extend
* @return void
*/
function addPlayerExtend(Player $player, array $extend = [])
{
$registerPresent = SystemSetting::where('feature', 'register_present')->where('status', 1)->value('num') ?? 0;
$playerPlatformCash = new PlayerPlatformCash();
$playerPlatformCash->player_id = $player->id;
$playerPlatformCash->platform_id = PlayerPlatformCash::PLATFORM_SELF;
$playerPlatformCash->money = $registerPresent;
$playerPlatformCash->save();
$playerExtend = new PlayerExtend();
$playerExtend->player_id = $player->id;
$playerExtend->email = $extend['email'];
$playerExtend->save();
if (isset($registerPresent) && $registerPresent > 0) {
//添加玩家钱包日志
$playerMoneyEditLog = new PlayerMoneyEditLog;
$playerMoneyEditLog->player_id = $player->id;
$playerMoneyEditLog->department_id = $player->department_id;
$playerMoneyEditLog->type = PlayerMoneyEditLog::TYPE_INCREASE;
$playerMoneyEditLog->action = PlayerMoneyEditLog::OTHER;
$playerMoneyEditLog->tradeno = date('YmdHis') . rand(10000, 99999);
$playerMoneyEditLog->currency = $player->currency;
$playerMoneyEditLog->money = $registerPresent;
$playerMoneyEditLog->inmoney = $registerPresent;
$playerMoneyEditLog->remark = '';
$playerMoneyEditLog->user_id = Admin::id() ?? 0;
$playerMoneyEditLog->user_name = !empty(Admin::user()) ? Admin::user()->toArray()['username'] : trans('system_automatic', [], 'message');
$playerMoneyEditLog->save();
//寫入金流明細
$playerDeliveryRecord = new PlayerDeliveryRecord;
$playerDeliveryRecord->player_id = $player->id;
$playerDeliveryRecord->department_id = $player->department_id;
$playerDeliveryRecord->target = $playerMoneyEditLog->getTable();
$playerDeliveryRecord->target_id = $playerMoneyEditLog->id;
$playerDeliveryRecord->type = PlayerDeliveryRecord::TYPE_REGISTER_PRESENT;
$playerDeliveryRecord->source = 'register_present';
$playerDeliveryRecord->amount = $playerMoneyEditLog->money;
$playerDeliveryRecord->amount_before = 0;
$playerDeliveryRecord->amount_after = $registerPresent;
$playerDeliveryRecord->tradeno = $playerMoneyEditLog->tradeno ?? '';
$playerDeliveryRecord->remark = $playerMoneyEditLog->remark ?? '';
$playerDeliveryRecord->save();
}
}
/**
* @return Player
* @throws GameException
* @throws PlayerCheckException
* @throws \Exception
*/
function checkPlayer(): Player
{
$departmentId = request()->department_id;
$id = JwtToken::getCurrentId();
/** @var Player $player */
$player = Player::where('id', $id)->where('department_id', $departmentId)->first();
if (empty($player)) {
throw new PlayerCheckException(trans('player_not_fount', [], 'message'), 100);
}
if ($player->status == Player::STATUS_STOP) {
throw new PlayerCheckException(trans('player_stop', [], 'message'), 100);
}
return $player;
}
/**
* 组装请求
* @param string $url
* @param array $params
* @return array|mixed
* @throws Exception
*/
function doCurl(string $url, array $params = [])
{
$response = Http::timeout(7)
->contentType('application/json')
->accept('application/json')
->asJson()
->post($url, $params);
if (!$response->ok()) {
throw new Exception(trans('system_busy', [], 'message'));
}
$data = $response->json();
if (empty($data)) {
throw new Exception(trans('system_busy', [], 'message'));
}
return $data;
}
/**
* 组装请求
* @param $id
* @param array $range
* @return array|mixed|null
*/
function getGamePlayerNum($id, array $range = [])
{
$cacheKey = 'game_player_num_' . $id;
$playerNum = Cache::get($cacheKey);
if ($playerNum === null) {
$playerNum = rand($range[0] ?? 0, $range[1] ?? 0);
Cache::set($cacheKey, $playerNum, 30 * 60);
}
return $playerNum;
}
/**
* 分润结算
* @return void
*/
function commissionSettlement()
{
$date = Carbon::now()->subDay()->format('Y-m-d');
$data = PlayGameRecord::query()
->selectRaw('SUM(bet) - SUM(win) AS damage_amount, player_id, parent_player_id, department_id,sum(deficit) as deficit')
->whereDate('created_at', $date)
->where('status', 0)
->groupBy('player_id', 'parent_player_id', 'department_id')
->get();
Log::info('分润结算开始------------------');
if ($data->isEmpty()) {
return;
}
// 提取父玩家ID
$playerIds = $data->pluck('parent_player_id')->unique()->toArray();
// 获取玩家数据
$players = Player::query()
->with(['player_extend'])
->whereIn('id', $playerIds)
->get()
->keyBy('id');
// 获取系统设置
$systemSettingMap = SystemSetting::query()
->where('status', 1)
->where('feature', 'commission_setting')
->get()
->keyBy('department_id');
$commissionRecord = [];
$unsettledCommissionAmount = [];
foreach ($data->toArray() as $item) {
/** @var SystemSetting $systemSettingData */
//边玩边赚,只返给上级
$systemSettingData = $systemSettingMap->get($item['department_id']);
if(empty($systemSettingData)){
continue;
}
$systemSetting = json_decode($systemSettingData->content, true);
if ($item['deficit'] == 0) {
continue;
}
if ($systemSetting && !empty($systemSetting['commission_damage']) && is_numeric($systemSetting['commission_damage']) && $systemSetting['commission_damage'] > 0) {
$commissionAmount = max(bcmul($item['damage_amount'], bcdiv($systemSetting['commission_damage'], 100, 2), 2), 0);
/** @var Player $player */
$player = $players->get($item['parent_player_id']);
if ($player) {
$commissionRecord[] = [
'player_id' => $item['player_id'],
'department_id' => $item['department_id'],
'parent_player_id' => $item['parent_player_id'],
'recharge_amount' => 0,
'chip_amount' => 0,
'total_amount' => $player->player_extend->commission_amount,
'damage_amount' => $item['damage_amount'],
'amount' => $commissionAmount,
'ratio' => $systemSetting['commission_damage'],
'date' => $date,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
];
if (!isset($unsettledCommissionAmount[$item['parent_player_id']])) {
$unsettledCommissionAmount[$item['parent_player_id']] = $commissionAmount;
} else {
$unsettledCommissionAmount[$item['parent_player_id']] = bcadd($unsettledCommissionAmount[$item['parent_player_id']], $commissionAmount, 2);
}
}
}
}
// 前天发生账变的玩家
$playerList = Player::with(['wallet'])
->whereHas('wallet', function ($query) use ($date) {
$query->where('updated_at', '>=', $date . ' 00:00:00');
})
->get();
// 账变记录
$playerDeliveryRecords = collect(PlayerDeliveryRecord::whereDate('updated_at', '2024-11-26')
->groupBy('player_id')
->whereIn('type', [
PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD,
PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT,
PlayerDeliveryRecord::TYPE_REGISTER_PRESENT,
PlayerDeliveryRecord::TYPE_GAME_OUT,
PlayerDeliveryRecord::TYPE_GAME_IN,
PlayerDeliveryRecord::TYPE_RECHARGE,
])
->get([
DB::raw("SUM(if(`type`=" . PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_ADD . ",`amount`,0)) as admin_add_amount"),
DB::raw("SUM(if(`type`=" . PlayerDeliveryRecord::TYPE_MODIFIED_AMOUNT_DEDUCT . ",`amount`,0)) as admin_deduct_amount"),
DB::raw("SUM(if(`type`=" . PlayerDeliveryRecord::TYPE_REGISTER_PRESENT . ",`amount`,0)) as present_amount"),
DB::raw("SUM(if(`type`=" . PlayerDeliveryRecord::TYPE_RECHARGE . ",`amount`,0)) as recharge_amount"),
'player_id'
])->toArray())
->keyBy('player_id')
->toArray();
// 提现记录
$playerWithdrawRecord = collect(PlayerWithdrawRecord::whereDate('updated_at', $date)
->where('status', PlayerWithdrawRecord::STATUS_SUCCESS)
->groupBy('player_id')
->get([
DB::raw('SUM(`money`) as withdraw_amount'),
'player_id'
]))
->keyBy('player_id')
->toArray();
/** @var Player $player */
foreach ($playerList as $player) {
$change = [
'recharge_amount' => $playerDeliveryRecords[$player->id]['recharge_amount'] ?? 0,
'admin_add_amount' => $playerDeliveryRecords[$player->id]['admin_add_amount'] ?? 0,
'admin_deduct_amount' => $playerDeliveryRecords[$player->id]['admin_deduct_amount'] ?? 0,
'present_amount' => $playerDeliveryRecords[$player->id]['present_amount'] ?? 0,
'bonus_amount' => $playerDeliveryRecords[$player->id]['bonus_amount'] ?? 0,
'withdraw_amount' => $playerWithdrawRecord[$player->id]['withdraw_amount'] ?? 0,
'date' => $date,
];
$change_list[$player->id] = $change;
}
DB::beginTransaction();
try {
$playerUpdates = [];
$playerDeliveryRecord = [];
$promoterProfitRecords = []; // 保存所有的PromoterProfitRecord
foreach ($unsettledCommissionAmount as $key => $amount) {
/** @var Player $player */
$player = $players->get($key);
if ($player) {
$commissionAmount = bcadd($amount, $player->player_extend->unsettled_commission_amount, 2);
if ($commissionAmount > 0) {
$player->player_extend->commission_amount = bcadd($player->player_extend->commission_amount, $commissionAmount, 2);
$player->player_extend->unsettled_commission_amount = 0;
$beforeAmount = $player->wallet->money;
$player->wallet->money = bcadd($player->wallet->money, $commissionAmount, 2);
$playerDeliveryRecord[] = [
'player_id' => $player->id,
'department_id' => $player->department_id,
'target' => 'commission_record',
'target_id' => 0,
'type' => PlayerDeliveryRecord::TYPE_COMMISSION,
'source' => 'commission',
'amount' => $commissionAmount,
'amount_before' => $beforeAmount,
'amount_after' => $player->wallet->money,
'tradeno' => '',
'remark' => '',
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
];
} else {
$player->player_extend->unsettled_commission_amount = $commissionAmount;
}
$playerUpdates[] = $player;
}
}
if (!empty($playerUpdates)) {
/** @var Player $player */
foreach ($playerUpdates as $player) {
$player->push();
}
}
if (!empty($commissionRecord)) {
CommissionRecord::query()->insert($commissionRecord);
}
if (!empty($playerDeliveryRecord)) {
PlayerDeliveryRecord::query()->insert($playerDeliveryRecord);
}
PlayGameRecord::query()
->whereDate('created_at', $date)
->update([
'status' => 1,
'action_at' => date('Y-m-d H:i:s'),
]);
foreach ($data as $value) {
$up_ids = [];
//玩家为代理
if(isset($value->player->player_promoter->path)){
$path = $value->player->player_promoter->path;
$up_ids = explode(',',$path);
//代理不给自己返利
array_pop($up_ids);
}else{
//查询玩家无限上级
if(isset($value->player->recommend_id)){
$path = PlayerPromoter::where('player_id',$value->player->recommend_id)->value('path');
$up_ids = explode(',',$path);
}else{
//未绑定上级的玩家不参与返利计算
continue;
}
}
$up_list = PlayerPromoter::whereIn('player_id',$up_ids)->orderBy('id','asc')->get();
foreach($up_list as $k => &$up_val){
$player_profit_amount = 0;//直属玩家提供的分润
$diff_ratio = 0;//每级代理获得的分润比例
if(isset($up_list[$k+1])){
//上级代理获得的返利比例
$diff_ratio = bcsub($up_val->ratio, $up_list[$k+1]->ratio, 2);
}else{
$diff_ratio = $up_val->ratio;
$player_profit_amount = bcdiv(bcmul($diff_ratio, $value->deficit, 2),100,2);
}
$rebate = bcdiv(bcmul($diff_ratio, $value->deficit, 2),100,2);
//更新推广员信息表
$up_val->player_profit_amount = bcadd($up_val->player_profit_amount,$player_profit_amount,2);//直属玩家提供的分润
$up_val->profit_amount = bcadd($up_val->profit_amount,$rebate,2);//总分润
$team_withdraw_total_amount = isset($change_list[$up_val->player_id]['withdraw_amount']) ? $change_list[$up_val->player_id]['withdraw_amount'] : 0;
$up_val->team_withdraw_total_amount = bcadd($up_val->team_withdraw_total_amount, $team_withdraw_total_amount, 2);
$team_recharge_total_amount = isset($change_list[$up_val->player_id]['recharge_amount']) ? $change_list[$up_val->player_id]['recharge_amount'] : 0;
$up_val->team_recharge_total_amount = bcadd($up_val->team_recharge_total_amount, $team_recharge_total_amount, 2);
$up_val->total_profit_amount = bcadd($up_val->total_profit_amount, $rebate, 2);
$up_val->team_total_profit_amount = bcadd($up_val->team_total_profit_amount, bcmul($value->deficit,bcdiv($up_val->ratio,100,2), 2),2);
$up_val->team_profit_amount = bcadd($up_val->team_profit_amount, bcmul($value->deficit,bcdiv($up_val->ratio,100,2), 2), 2);
$up_val->save();
$promoter_profit_record = [];
$promoter_profit_record['player_id'] = $value->player_id;//玩家id
$promoter_profit_record['department_id'] = $up_val->department_id;
$promoter_profit_record['promoter_player_id'] = $up_val->player_id;//获得分润的id
$promoter_profit_record['source_player_id'] = $value->player->recommend_id;//玩家上级id
$promoter_profit_record['withdraw_amount'] = isset($change_list[$up_val->player_id]['withdraw_amount']) ? $change_list[$up_val->player_id]['withdraw_amount'] : 0;
$promoter_profit_record['recharge_amount'] = isset($change_list[$up_val->player_id]['recharge_amount']) ? $change_list[$up_val->player_id]['recharge_amount'] : 0;
$promoter_profit_record['bonus_amount'] = isset($change_list[$up_val->player_id]['bonus_amount']) ? $change_list[$up_val->player_id]['bonus_amount'] : 0;
$promoter_profit_record['admin_deduct_amount'] = isset($change_list[$up_val->player_id]['admin_deduct_amount']) ? $change_list[$up_val->player_id]['admin_deduct_amount'] : 0;
$promoter_profit_record['admin_add_amount'] = isset($change_list[$up_val->player_id]['admin_add_amount']) ? $change_list[$up_val->player_id]['admin_add_amount'] : 0;
$promoter_profit_record['present_amount'] = isset($change_list[$up_val->player_id]['present_amount']) ? $change_list[$up_val->player_id]['present_amount'] : 0;
$promoter_profit_record['ratio'] = $up_val->ratio;
$promoter_profit_record['actual_ratio'] = $diff_ratio;
$promoter_profit_record['date'] = $date;
$promoter_profit_record['model'] = PromoterProfitRecord::MODEL_TASK;
$promoter_profit_record['profit_amount'] = $rebate;
$promoter_profit_record['player_profit_amount'] = $player_profit_amount;
$created_at = Carbon::now();
$promoter_profit_record['created_at'] = $created_at;
$promoter_profit_record['updated_at'] = $created_at;
$promoterProfitRecords[] = $promoter_profit_record;
}
unset($up_val);
}
PromoterProfitRecord::insert($promoterProfitRecords);
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
Log::error('CommissionSettlement', [$e->getMessage(), $e->getTraceAsString()]);
}
Log::info('分润结算结束------------------');
}
/**
* 客损返水结算
* @return void
*/
function damageRebate()
{
$date = Carbon::now()->subDay()->format('Y-m-d');
$data = CommissionRecord::query()->where('date', $date)->get();
Log::info('客损返水结算------------------');
if ($data->isEmpty()) {
return;
}
// 提取玩家ID
$playerIds = $data->pluck('player_id')->unique()->toArray();
// 获取玩家数据
$players = Player::query()
->with(['wallet', 'player_level'])
->whereIn('id', $playerIds)
->get()
->keyBy('id');
DB::beginTransaction();
try {
/** @var CommissionRecord $item */
foreach ($data as $item) {
/** @var Player $player */
$player = $players->get($item->player_id);
$playerLevel = $player->player_level;
if (!empty($playerLevel) && $playerLevel->damage_rebate_ratio > 0 && $item->damage_amount > 0) {
$damageAmount = bcmul($item->damage_amount, $playerLevel->damage_rebate_ratio, 2);
$beforeGameAmount = $player->wallet->money;
if ($damageAmount > 0) {
// 更新钱包
$player->wallet->money = bcadd($player->wallet->money, $damageAmount, 2);
if ($playerLevel->chip_multiple) {
$chipAmount = bcmul($damageAmount, $playerLevel->chip_multiple);
if ($chipAmount) {
$beforeMustChipAmount = $player->must_chip_amount;
$player->must_chip_amount = bcadd($player->must_chip_amount, $chipAmount, 2);
// 记录打码量明细
$playerChipRecord = new PlayerChipRecord();
$playerChipRecord->player_id = $player->id;
$playerChipRecord->department_id = $player->department_id;
$playerChipRecord->type = PlayerChipRecord::TYPE_INC;
$playerChipRecord->record_type = PlayerChipRecord::RECORD_TYPE_BET_REBATE;
$playerChipRecord->amount = $chipAmount;
$playerChipRecord->chip_amount = 0;
$playerChipRecord->before_chip_amount = $player->chip_amount;
$playerChipRecord->after_chip_amount = $player->chip_amount;
$playerChipRecord->must_chip_amount = $chipAmount;
$playerChipRecord->before_must_chip_amount = $beforeMustChipAmount;
$playerChipRecord->after_must_chip_amount = $player->must_chip_amount;
$playerChipRecord->source_type = CommissionRecord::class;
$playerChipRecord->source_id = $item->id;
$playerChipRecord->save();
}
}
// 根据打码量返水玩家
$playerDeliveryRecord = new PlayerDeliveryRecord;
$playerDeliveryRecord->player_id = $player->id;
$playerDeliveryRecord->department_id = $player->department_id;
$playerDeliveryRecord->target = $item->getTable();
$playerDeliveryRecord->target_id = $item->id;
$playerDeliveryRecord->type = PlayerDeliveryRecord::TYPE_DAMAGE_REBATE;
$playerDeliveryRecord->source = 'damage_rebate';
$playerDeliveryRecord->amount = $damageAmount;
$playerDeliveryRecord->amount_before = $beforeGameAmount;
$playerDeliveryRecord->amount_after = $player->wallet->money;
$playerDeliveryRecord->tradeno = '';
$playerDeliveryRecord->remark = '';
$playerDeliveryRecord->save();
}
}
$player->push();
}
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
Log::error('damageRebate', [$e->getMessage(), $e->getTraceAsString()]);
}
Log::info('客损返水结算结束------------------');
}
/**
* 玩家等级选项
* @return array
*/
function playerLevelOptions(): array
{
$options = [];
for ($i = 0; $i <= 13; $i++) {
if ($i == 0) {
$options[$i] = admin_trans('player.no_level');
} else {
$options[$i] = admin_trans('player.level.' . $i);
}
}
return $options;
}
/**
* 自动生成密码
* @return string
*/
function generateRandomPassword(): string
{
$uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$lowercase = 'abcdefghijklmnopqrstuvwxyz';
$numbers = '0123456789';
$password = '';
$password .= $uppercase[rand(0, strlen($uppercase) - 1)];
$password .= $lowercase[rand(0, strlen($lowercase) - 1)];
$password .= $numbers[rand(0, strlen($numbers) - 1)];
$length = rand(7, 12); // Random length between 7 and 12
$remainingLength = $length - 3;
$allChars = $uppercase . $lowercase . $numbers;
for ($i = 0; $i < $remainingLength; $i++) {
$password .= $allChars[rand(0, strlen($allChars) - 1)];
}
return str_shuffle($password);
}
/**
* 生成用户名
* @param int $length
* @return string
*/
function generateUniqueUsername(int $length = 10): string
{
$characters = 'abcdefghijklmnopqrstuvwxyz0123456789'; // 可选的字符集合
$uniqueUsername = ''; // 初始化唯一用户名
// 生成不重复的用户名
for ($i = 0; $i < $length; $i++) {
$uniqueUsername .= $characters[rand(0, strlen($characters) - 1)];
}
return $uniqueUsername;
}
/**
* 组装请求
* @param string $url
* @param array $params
* @return array|mixed|null
* @throws Exception
*/
function dogGetCurl(string $url, array $params = [])
{
$response = Http::timeout(7)
->contentType('application/json')
->accept('application/json')
->asJson()
->get($url, $params);
if (!$response->ok()) {
throw new Exception(trans('system_busy', [], 'message'));
}
$data = $response->json();
if (empty($data)) {
throw new Exception(trans('system_busy', [], 'message'));
}
return $data;
}
/**
* 设置推广员
* @param $id
* @param $ratio
* @param $name
* @return true
* @throws Exception
*/
function setPromoter($id, $ratio, $name,$recommend_id): bool
{
DB::beginTransaction();
try {
/** @var Player $player */
$player = Player::find($id);
if (empty($player)) {
throw new Exception(trans('player_not_found', [], 'message'));
}
if (!empty($player->player_promoter)) {
throw new Exception(trans('player_is_promoter', [], 'message'));
}
if ($player->status == Player::STATUS_STOP) {
throw new Exception(trans('player_stop', [], 'message'));
}
if($recommend_id != $player->recommend_id){
throw new Exception(trans('not_sub_recommend_player', [], 'message'));
}
$promoter = new PlayerPromoter();
/** @var PlayerPromoter $parentPromoter */
$parentPromoter = PlayerPromoter::where('player_id', $player->recommend_id)->first();
$maxRatio = $parentPromoter->ratio ?? 100;
if ($ratio > $maxRatio) {
throw new Exception(trans('ratio_max_error', ['{max_ratio}' => $maxRatio], 'message'));
}
$orgPromoter = $player->is_promoter;
$path = [];
if (isset($parentPromoter->path) && !empty($parentPromoter->path)) {
$path = explode(',', $parentPromoter->path);
}
$path[] = $player->id;
$promoter->ratio = $ratio;
$promoter->player_id = $player->id;
$promoter->recommend_id = $parentPromoter->player_id ?? 0;
$promoter->department_id = $player->department_id;
$promoter->name = !empty($name) ? $name : $player->name;
$promoter->path = implode(',', $path);
$promoter->save();
// 更新玩家信息
$player->is_promoter = 1;
$player->recommend_code = createCode();
$player->save();
$parentPromoter && $orgPromoter == 0 && $parentPromoter->increment('team_num');
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
throw new Exception($e->getMessage());
}
return true;
}
/**
* 验证手机号格式
* @param $phoneNumber
* @return true
*/
function validateMalaysianPhoneNumber($phoneNumber): bool
{
$pattern = '/^(01\d{8,9}|(\+60|60|0060)(0?1)\d{8,9})$/';
return preg_match($pattern, $phoneNumber);
}
/**
* post表单请求
* @param string $url
* @param array $params
* @return array|mixed
* @throws Exception
*/
function doFormCurl(string $url, array $params = [])
{
$response = Http::timeout(10)->asForm()->post($url, $params);
if (!$response->ok()) {
throw new Exception(trans('system_busy', [], 'message'));
}
$data = $response->json();
if (empty($data)) {
throw new Exception(trans('system_busy', [], 'message'));
}
return $data;
}
/**
* 结算
* @param $id
* @param int $userId
* @param string $userName
* @return void
* @throws Exception
*/
function doSettlement($id, int $userId = 0, string $userName = '')
{
/** @var PlayerPromoter $playerPromoter */
$playerPromoter = PlayerPromoter::where('player_id', $id)->first();
if (empty($playerPromoter)) {
throw new Exception(trans('profit_amount_not_found', [], 'message'));
}
if ($playerPromoter->status == 0) {
throw new Exception(trans('player_promoter_has_disable', [], 'message'));
}
if (!isset($playerPromoter->profit_amount)) {
throw new Exception(trans('profit_amount_not_found', [], 'message'));
}
$profitAmount = PromoterProfitRecord::where('status', PromoterProfitRecord::STATUS_UNCOMPLETED)
->where('promoter_player_id', $id)
->first([
DB::raw('SUM(`withdraw_amount`) as total_withdraw_amount'),
DB::raw('SUM(`recharge_amount`) as total_recharge_amount'),
DB::raw('SUM(`bonus_amount`) as total_bonus_amount'),
DB::raw('SUM(`admin_deduct_amount`) as total_admin_deduct_amount'),
DB::raw('SUM(`admin_add_amount`) as total_admin_add_amount'),
DB::raw('SUM(`present_amount`) as total_present_amount'),
DB::raw('SUM(`profit_amount`) as total_profit_amount'),
DB::raw('SUM(`player_profit_amount`) as total_player_profit_amount'),
])
->toArray();
DB::beginTransaction();
try {
$promoterProfitSettlementRecord = new PromoterProfitSettlementRecord();
$promoterProfitSettlementRecord->department_id = $playerPromoter->player->department_id;
$promoterProfitSettlementRecord->promoter_player_id = $playerPromoter->player_id;
$promoterProfitSettlementRecord->total_withdraw_amount = $profitAmount['total_withdraw_amount'] ?? 0;
$promoterProfitSettlementRecord->total_recharge_amount = $profitAmount['total_recharge_amount'] ?? 0;
$promoterProfitSettlementRecord->total_bonus_amount = $profitAmount['total_bonus_amount'] ?? 0;
$promoterProfitSettlementRecord->total_admin_deduct_amount = $profitAmount['total_admin_deduct_amount'] ?? 0;
$promoterProfitSettlementRecord->total_admin_add_amount = $profitAmount['total_admin_add_amount'] ?? 0;
$promoterProfitSettlementRecord->total_present_amount = $profitAmount['total_present_amount'] ?? 0;
$promoterProfitSettlementRecord->total_profit_amount = $profitAmount['total_profit_amount'] ?? 0;
$promoterProfitSettlementRecord->total_player_profit_amount = $profitAmount['total_player_profit_amount'] ?? 0;
$promoterProfitSettlementRecord->last_profit_amount = $playerPromoter->last_profit_amount;
$promoterProfitSettlementRecord->adjust_amount = $playerPromoter->adjust_amount;
$promoterProfitSettlementRecord->type = PromoterProfitSettlementRecord::TYPE_SETTLEMENT;
$promoterProfitSettlementRecord->tradeno = createOrderNo();
$promoterProfitSettlementRecord->user_id = $userId;
$promoterProfitSettlementRecord->user_name = $userName;
$settlement = $amount = bcadd($promoterProfitSettlementRecord->total_profit_amount,
$promoterProfitSettlementRecord->adjust_amount, 2);
if ($amount > 0) {
if ($playerPromoter->settlement_amount < 0) {
$diffAmount = bcadd($amount, $playerPromoter->settlement_amount, 2);
$settlement = max($diffAmount, 0);
}
}
$promoterProfitSettlementRecord->actual_amount = $settlement;
$promoterProfitSettlementRecord->save();
// 更新结算报表
PromoterProfitRecord::where('status', PromoterProfitRecord::STATUS_UNCOMPLETED)
->where('promoter_player_id', $id)
->update([
'status' => PromoterProfitRecord::STATUS_COMPLETED,
'settlement_time' => date('Y-m-d H:i:s'),
'settlement_tradeno' => $promoterProfitSettlementRecord->tradeno,
'settlement_id' => $promoterProfitSettlementRecord->id,
]);
// 结算后这些数据清零
$playerPromoter->profit_amount = 0;
$playerPromoter->player_profit_amount = 0;
$playerPromoter->team_recharge_total_amount = 0;
$playerPromoter->team_withdraw_total_amount = 0;
$playerPromoter->adjust_amount = 0;
// 更新数据
$playerPromoter->team_profit_amount = bcsub($playerPromoter->team_profit_amount,
$promoterProfitSettlementRecord->total_profit_amount, 2);
$playerPromoter->last_profit_amount = $settlement;
$playerPromoter->settlement_amount = bcadd($playerPromoter->settlement_amount, $amount, 2);
$playerPromoter->team_settlement_amount = bcadd($playerPromoter->team_settlement_amount,
$promoterProfitSettlementRecord->total_profit_amount, 2);
$playerPromoter->last_settlement_time = date('Y-m-d', strtotime('-1 day'));
if (!empty($playerPromoter->path)) {
PlayerPromoter::where('player_id', '!=', $playerPromoter->player_id)
->whereIn('player_id', explode(',', $playerPromoter->path))
->update([
'team_profit_amount' => DB::raw("team_profit_amount - {$promoterProfitSettlementRecord->total_profit_amount}"),
'team_settlement_amount' => DB::raw("team_settlement_amount + $promoterProfitSettlementRecord->total_profit_amount"),
]);
}
if ($settlement > 0) {
// 增加钱包余额
$amountBefore = $playerPromoter->player->wallet->money;
$amountAfter = bcadd($amountBefore, $settlement, 2);
$playerDeliveryRecord = new PlayerDeliveryRecord;
$playerDeliveryRecord->player_id = $playerPromoter->player_id;
$playerDeliveryRecord->department_id = $playerPromoter->department_id;
$playerDeliveryRecord->target = $promoterProfitSettlementRecord->getTable();
$playerDeliveryRecord->target_id = $promoterProfitSettlementRecord->id;
$playerDeliveryRecord->type = PlayerDeliveryRecord::TYPE_PROFIT;
$playerDeliveryRecord->source = 'profit';
$playerDeliveryRecord->amount = $settlement;
$playerDeliveryRecord->amount_before = $amountBefore;
$playerDeliveryRecord->amount_after = $amountAfter;
$playerDeliveryRecord->tradeno = $promoterProfitSettlementRecord->tradeno ?? '';
$playerDeliveryRecord->remark = '';
$playerDeliveryRecord->save();
$playerPromoter->player->wallet->money = $amountAfter;
}
$playerPromoter->push();
DB::commit();
} catch (\Exception $e) {
DB::rollback();
throw new Exception($e->getMessage());
}
}