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

1379 lines
53 KiB
PHP
Raw Permalink Blame History

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