'平台奖金', 2=>'直推奖金', 3=>'间推奖金', 4=>'团队奖金', 5=>'公排池', 6=>'沉淀奖', 7=>'代币奖', 8=>'公排出局', ]; /** * @return string[] */ public function getDistributionArr(): array { return $this->distributionArr; } /** * 获取清分类型 * @param $type * @return string */ public function getDistributionArrStr($type) { return empty($this->distributionArr[$type])?'无':$this->distributionArr[$type]; } private function __construct() { } /** * 创建对象 * @return ContractServer */ static function creatServer() { if (empty(self::$server)) { self::$server = new ContractServer(); } return self::$server; } /** * 报单信息检测 */ function broadcastDetection(){ //检测报单信息 $contractList=Contract::where('status',1)->limit(50)->get(); $sysAddress=CommonServer::creatServer()->getConfigValue('sys_address'); $sysAddress=strtolower($sysAddress); foreach ($contractList as $contract){ $contractNum=Contract::where('hash',$contract->{'hash'})->count(); if($contractNum>0){ $broadcastData=BanRPC::creatServer()->getTransactionReceipt($contract->{'hash'}); $memberAddress=Member::where('id',$contract->{'m_id'})->value('address'); $memberAddress=strtolower($memberAddress); if (empty($broadcastData)) { //交易正在广播中,下次继续查询 continue; } else { //交易已完成 返回数据格式数据 ,将数据json保存 $updateInfo['broadcast_data'] = json_encode($broadcastData); if ($broadcastData['status'] == '0x1') { if($sysAddress!=strtolower($broadcastData['to'])){ $updateInfo['status'] = 3; $updateInfo['error_msg'] = '收款地址不匹配'; }elseif ($memberAddress!=strtolower($broadcastData['from'])){ $updateInfo['status'] = 3; $updateInfo['error_msg'] = '转出地址不匹配'; }else{ $updateInfo['status'] = 2; } } else { $updateInfo['status'] = 3; $updateInfo['error_msg'] = '广播失败'; } } }else{ $updateInfo['status'] = 3; $updateInfo['error_msg'] = '当前哈希被重复使用'; } //检测是否有更新细腻 if($updateInfo){ DB::beginTransaction(); $ret= $contract->update($updateInfo); if(empty($ret)){ CommonServer::creatServer()->addErrorRecord('保单信息更新失败',$contract,0); DB::rollBack(); } if($updateInfo['status']==2){ //报单成功,就进行清分 $memberTeam=MemberClan::where('m_id',$contract->{'m_id'})->select(['id','m_id','p_ids','one_m_id','two_m_id'])->first(); $pIds=array_reverse(array_filter(explode(',',$memberTeam->{'p_ids'}))); //平台清分 $this->platformDistribution($contract,$pIds); //直推及间推发放 $this->directProportion($contract,$memberTeam); //团队清分 $this->teamProportion($contract,$pIds); //公排分账 $this->commonProportion($contract); //沉淀账户分账 $this->sedimentProportion($contract); //代币清分 $this->agencyProportion($contract); //触发会员升级 JobServer::creatServer()->verificationLevelJob($pIds); } DB::commit(); } } return $contractList->count(); } /** * 系统分账功能 * @param Contract $contract * @param $pIds */ private function platformDistribution(Contract $contract,$pIds){ $platformMoney=$contract->{'platform_money'}; if(empty($platformMoney)){ $this->addContractLog($contract,'平台清分金额为0,停止平台清分'); }else{ //验证平台分红 $receiveLevelId=CommonServer::creatServer()->getConfigValue('receive_level_id'); //用户分红金额 if(empty($receiveLevelId)){ $this->addContractLog($contract,'未设置平台分红等级,跳出分红'); }else{ $pMember=Member::whereIn('id',$pIds)->where('level_id','>=',$receiveLevelId)->orderBy('id','desc')->select(['id','address','is_auto'])->first(); if($pMember){ $receiveUserMax=CommonServer::creatServer()->getConfigValue('receive_user_max'); $teamContractNum=$this->getTeamContractNum($pMember->{'id'}); if($teamContractNum>=$receiveUserMax){ //最大比例 $receiveProportion=CommonServer::creatServer()->getConfigValue('receive_max'); $this->addContractLog($contract,$teamContractNum.'团队数量满足条件,执行最大分红比例'); }else{ //最小比例 $receiveProportion=CommonServer::creatServer()->getConfigValue('receive_mix'); $this->addContractLog($contract,$teamContractNum.'团队数量满不足条件,执行最小分红比例'); } if(empty($receiveProportion)){ $this->addContractLog($contract,$teamContractNum.'平台分红比例不存在,跳出分红'); }else{ $receiveMoney=round($platformMoney*$receiveProportion/100,6); if($receiveMoney<=0){ $this->addContractLog($contract,$receiveProportion.'分红比例金额小于0,跳出分红'); }else{ //计算推荐分红数量及平台收益数量 if($pMember->{'is_auto'}==0){ $this->addContractLog($contract,'后台升级用户,跳出分红'); }else{ $this->addDistribution($contract->{'id'},$contract->{'m_id'},0,$receiveMoney,1,$pMember->{'id'},$pMember->{'address'},$receiveProportion,1,'平台用户分红'); $platformMoney-=$receiveMoney; } } } }else{ $this->addContractLog($contract,$receiveLevelId.'及以上的父级不存在,跳出分红'); } } $openSys=CommonServer::creatServer()->getConfigValue('open_sys'); if($openSys){ $receiveAddress=CommonServer::creatServer()->getConfigValue('receive_address'); if(empty($receiveAddress)){ $this->addDistribution($contract->{'id'},$contract->{'m_id'},0,$platformMoney,1,0,'',$contract->{'platform_money'},0,'平台分红至系统账户'); }else{ $this->addDistribution($contract->{'id'},$contract->{'m_id'},0,$platformMoney,1,0,$receiveAddress,$contract->{'platform_money'},1,'平台分红至系统账户'); } }else{ $this->addDistribution($contract->{'id'},$contract->{'m_id'},0,$platformMoney,1,0,'',$contract->{'platform_money'},0,'平台关闭转账至系统账户,不进行划拨分账'); } } } /** * 直推及间推 * @param Contract $contract * @param MemberClan $memberTeam */ private function directProportion(Contract $contract,MemberClan $memberTeam){ $directMember=Member::where('id',$memberTeam->{'one_m_id'})->select(['id','address','is_boss'])->first(); if(empty($directMember)){ $this->addContractLog($contract,'直推人信息异常,停止清分'); }else{ if($directMember->{'is_boss'}){ $this->addContractLog($contract,'直推人是boss,直与间都划分为直推人'); $directProportion=($contract->{'direct_proportion'}+$contract->{'indirect_proportion'}); $directMoney=round(($contract->{'money'}-$contract->{'platform_money'})*$directProportion/100,6); $this->addDistribution($contract->{'id'},$contract->{'m_id'},0,$directMoney,2,$directMember->{'id'},$directMember->{'address'},$directProportion,1,'直推BOSS分红'); }else{ $directMoney=round(($contract->{'money'}-$contract->{'platform_money'})*$contract->{'direct_proportion'}/100,6); $this->addDistribution($contract->{'id'},$contract->{'m_id'},0,$directMoney,2,$directMember->{'id'},$directMember->{'address'},$contract->{'direct_proportion'},1,'直推分红'); $indirectMember=Member::where('id',$memberTeam->{'two_m_id'})->select(['id','address','is_boss'])->first(); $indirectMoney=round(($contract->{'money'}-$contract->{'platform_money'})*$contract->{'indirect_proportion'}/100,6); if(empty($indirectMember)){ $this->addContractLog($contract,'间推人信息不存在,停止清分'); $this->addDistribution($contract->{'id'},$contract->{'m_id'},0,$indirectMoney,3,$directMember->{'id'},$directMember->{'address'},$contract->{'indirect_proportion'},0,'间推推分红,间推人不存在,未划分'); }else{ $this->addDistribution($contract->{'id'},$contract->{'m_id'},0,$indirectMoney,3,$directMember->{'id'},$directMember->{'address'},$contract->{'indirect_proportion'},1,'间推推分红'); } } } } /** * 团队清分 * @param Contract $contract * @param $pIds */ private function teamProportion(Contract $contract,$pIds){ $levels=Level::select(['direct_num','id','lateral_num'])->get()->toArray(); $levelArr=[]; foreach ($levels as $level){ $levelArr[$level['id']]=$level; } $totalMoney=$contract->{'money'}-$contract->{'platform_money'}; $teamTotalMoney=round($totalMoney*$contract->{'team_proportion'}/100,6); $startId=1; $isLateral=false; //已经使用过的比例 $useProportion=0; //已经使用金额 $userMoney=0; //使用金额 $grantMoney=0; foreach ($pIds as $pId){ $pMember=Member::where('id',$pId)->select(['id','address','level_id'])->first(); if(empty($pMember)){ $this->addContractLog($contract,$pId.',无当前父及信息,停止清分'); }else{ $levelData=empty($levelArr[$pMember->{'level_id'}])?0:$levelArr[$pMember->{'level_id'}]; if(empty($levelData)){ $this->addContractLog($contract,$pMember->{'id'}.'ID,'.$pMember->{'level_id'}.',无当前等级配置信息,停止清分'); }else{ if($pMember->{'level_id'}>$startId || ($pMember->{'level_id'}==$startId &&!$isLateral)){ //等级大于等于当前等级 $isLateral=true; //等级比例 $levelProportion=$levelData['direct_num']; //等级比例-减去已经使用比例,获取到可用比列 $grantProportion=$levelProportion-$useProportion; //累计已经使用的比例 $useProportion+=$grantProportion; $grantMoney=round($grantProportion*$totalMoney/100,6); if($userMoney+$grantMoney>$teamTotalMoney){ $grantMoney=$teamTotalMoney-$userMoney; if($grantMoney<=0){ $this->addContractLog($contract,$pMember->{'level_id'}.'层级,资金已不足,停止团队奖金清分'); } } $userMoney+=$grantMoney; $this->addDistribution($contract->{'id'},$contract->{'m_id'},0,$grantMoney,4,$pMember->{'id'},$pMember->{'address'},$grantProportion,1,$pMember->{'level_id'}.'级别团队分红'); }elseif($pMember->{'level_id'}==$startId && $isLateral){ //平级奖金发放 $isLateral=false; $startId=$pMember->{'level_id'}+1; $lateralMoney=round($grantMoney*$levelData['lateral_num']/100,6); if($lateralMoney>0){ if($userMoney+$lateralMoney>$teamTotalMoney){ $lateralMoney=$teamTotalMoney-$userMoney; if($lateralMoney<=0){ $this->addContractLog($contract,$pMember->{'level_id'}.'层级,资金已不足,停止团队平级奖金清分'); } } $userMoney+=$lateralMoney; $this->addDistribution($contract->{'id'},$contract->{'m_id'},0,$lateralMoney,4,$pMember->{'id'},$pMember->{'address'},$levelData['lateral_num'],1,$pMember->{'level_id'}.'级别团队平级分红'); }else{ $this->addContractLog($contract,$pMember->{'level_id'}.'层级,平级奖金小于等于0,停止团队平级奖金清分'); } if($startId>count($levels)){ //清分完成,跳出循环 break; } } } } } } /** * 公排分账 * @param Contract $contract */ private function commonProportion(Contract $contract){ $commonMoney=round(($contract->{'money'}-$contract->{'platform_money'})*$contract->{'common_proportion'}/100,6); $openSys=CommonServer::creatServer()->getConfigValue('open_sys'); if($openSys && $commonMoney>0){ $commonAddress=CommonServer::creatServer()->getConfigValue('common_address'); if(empty($commonAddress)){ $this->addDistribution($contract->{'id'},$contract->{'m_id'},0,$commonMoney,5,0,'',$contract->{'common_proportion'},0,'公排分账,无收款地址信息。系统关闭'); }else{ $this->addDistribution($contract->{'id'},$contract->{'m_id'},0,$commonMoney,5,0,$commonAddress,$contract->{'common_proportion'},1,'公排分账'); } }else{ $this->addDistribution($contract->{'id'},$contract->{'m_id'},0,$commonMoney,5,0,'',$contract->{'common_proportion'},0,'平台关闭转账至系统账户,不进行划拨分账'); } //公排触发清算队列 JobServer::creatServer()->contractCommonJob(); } /** * 沉淀账户收款地址 * @param Contract $contract */ private function sedimentProportion(Contract $contract){ $sedimentMoney=round(($contract->{'money'}-$contract->{'platform_money'})*$contract->{'sediment_proportion'}/100,6); $openSys=CommonServer::creatServer()->getConfigValue('open_sys'); if($openSys && $sedimentMoney>0){ $sedimentAddress=CommonServer::creatServer()->getConfigValue('sediment_address'); if(empty($sedimentAddress)){ $this->addDistribution($contract->{'id'},$contract->{'m_id'},0,$sedimentMoney,6,0,'',$contract->{'sediment_proportion'},0,'沉淀分账,无收款地址信息。系统关闭'); }else{ $this->addDistribution($contract->{'id'},$contract->{'m_id'},0,$sedimentMoney,6,0,$sedimentAddress,$contract->{'sediment_proportion'},1,'沉淀分账'); } }else{ $this->addDistribution($contract->{'id'},$contract->{'m_id'},0,$sedimentMoney,6,0,'',$contract->{'sediment_proportion'},0,'平台关闭转账至系统账户,不进行划拨分账'); } } /** * 代币比例 * @param Contract $contract */ private function agencyProportion(Contract $contract){ $agencyMoney=round(($contract->{'money'}-$contract->{'platform_money'})*$contract->{'agency_proportion'}/100,6); $exchangeMoney=CommonServer::creatServer()->getConfigValue('exchange_money'); $dbMoney=$agencyMoney*$exchangeMoney; if($exchangeMoney >0){ $member=Member::where('id',$contract->{'m_id'})->select(['id','address','is_boss'])->first(); $this->addDistribution($contract->{'id'},$contract->{'m_id'},$dbMoney,0,7,$member->{'id'},$member->{'address'},$contract->{'agency_proportion'},1,'代币分账'); MoneyDetailServer::creatServer()->write(1,1,$dbMoney,1,$member->{'id'},'报单代币清分',$contract->{'id'}); }else{ $sedimentAddress=CommonServer::creatServer()->getConfigValue('sediment_address'); $this->addDistribution($contract->{'id'},$contract->{'m_id'},0,$agencyMoney,7,0,$sedimentAddress,$contract->{'agency_proportion'},1,'代币价格为0,转入沉淀分账'); $this->addContractLog($contract,'代币价格为0,不分发'); } } /** * 添加清分记录 * @param $contractId * @param $mId * @param $nbnMoney * @param $dbMoney * @param $type * @param $toMid * @param $toAddress * @param $proportion * @param $status * @param string $remark */ function addDistribution($contractId,$mId,$dbMoney,$nbnMoney,$type,$toMid,$toAddress,$proportion,$status,$remark='奖金发放'){ $serviceMoney=0; if($toMid>0 && $nbnMoney>0){ $serviceMoney=CommonServer::creatServer()->getConfigValue('service_money')?:0; } ContractDistribution::create([ 'contract_id' => $contractId, 'broadcast_id' => 0, 'm_id' => $mId, 'db_money' => $dbMoney, 'nbn_money' => $nbnMoney, 'type' => $type, 'to_m_id' => $toMid, 'to_address' => $toAddress, 'status' => $status, 'proportion' => $proportion, 'service_money' => $serviceMoney, 'remark' => $remark ]); } /** * 获取团队合约数量 * @param $mId * @return int */ function getTeamContractNum($mId){ $contractNum=0; $teamIds=MemberClan::where('id',$mId)->value('m_ids'); $teamIds=array_filter(explode(',',$teamIds)); $teamIds[]=$mId; if($teamIds){ $contractNum=Contract::whereIn('m_id',$teamIds)->whereIn('status',[2,4])->count(); } return $contractNum; } /** * 公排出局检测 * @throws \Exception */ function verifyContractCommon(){ $commonNum=CommonServer::creatServer()->getConfigValue('common_num'); $contractIds=Contract::where('status',2)->where('is_out',0)->orderBy('id','asc')->limit($commonNum)->pluck('id')->toArray(); if(count($contractIds)>=$commonNum){ //选择第一个单子排队出公排 $contract=Contract::where('status',2)->orderBy('id','asc')->first(); DB::beginTransaction(); Contract::whereIn('id',$contractIds)->update(['is_out'=>1]); $commonBnb=CommonServer::creatServer()->getConfigValue('common_bnb'); $commonDb=CommonServer::creatServer()->getConfigValue('common_db'); $exchangeMoney=CommonServer::creatServer()->getConfigValue('exchange_money'); $member=Member::where('id',$contract->{'m_id'})->select(['id','address','is_boss'])->first(); $this->addDistribution($contract->{'id'},$contract->{'m_id'},0,$commonBnb,9,$member->{'id'},$member->{'address'},$commonBnb,1,'bsn公排出局'); $dbMoney=1*$exchangeMoney*$commonDb; $this->addDistribution($contract->{'id'},$contract->{'m_id'},$dbMoney,0,9,$member->{'id'},$member->{'address'},$commonBnb,1,'代币公排出局'); MoneyDetailServer::creatServer()->write(1,2,$dbMoney,1,$member->{'id'},'公排池代币出局',$contract->{'id'}); $contract->update(['status' => 4]); DB::commit(); } } /** * 合约日志记录 * @param Contract $contract * @param $msg * @param array $data */ function addContractLog(Contract $contract,$msg,$data=[]){ ContractLog::create([ 'contract_id'=> $contract->{'id'}, 'm_id'=> $contract->{'m_id'}, 'msg'=> $msg, 'contract_data'=> json_encode($contract), 'data'=> json_encode($data), ]); } }