// +---------------------------------------------------------------------- namespace app\services\order; use app\adminapi\controller\v1\marketing\StoreCouponUser; use app\dao\order\StoreOrderDao; use app\model\user\User; use app\services\activity\coupon\StoreCouponIssueServices; use app\services\activity\lottery\LuckLotteryServices; use app\services\activity\combination\StorePinkServices; use app\services\BaseServices; use app\services\pay\PayServices; use app\services\user\UserBrokerageServices; use app\services\user\UserServices; use crmeb\exceptions\ApiException; /** * Class StoreOrderSuccessServices * @package app\services\order * @method getOne(array $where, ?string $field = '*', array $with = []) 获取去一条数据 */ class StoreOrderSuccessServices extends BaseServices { /** * * StoreOrderSuccessServices constructor. * @param StoreOrderDao $dao */ public function __construct(StoreOrderDao $dao) { $this->dao = $dao; } /** * 0元支付 * @param array $orderInfo * @param int $uid * @return bool * @throws \think\Exception * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException */ public function zeroYuanPayment(array $orderInfo, int $uid, string $payType = PayServices::YUE_PAY) { if ($orderInfo['paid']) { throw new ApiException(410265); } return $this->paySuccess($orderInfo, $payType);//余额支付成功 } /** * 支付成功 * @param array $orderInfo * @param string $paytype * @param array $other * @return bool * @throws \Psr\SimpleCache\InvalidArgumentException * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function paySuccess(array $orderInfo, string $paytype = PayServices::WEIXIN_PAY, array $other = []) { $updata = ['paid' => 1, 'pay_type' => $paytype, 'pay_time' => time()]; $orderInfo['pay_time'] = $updata['pay_time']; $orderInfo['pay_type'] = $paytype; if ($other && isset($other['trade_no'])) { $updata['trade_no'] = $other['trade_no']; } /** @var StoreOrderCartInfoServices $orderInfoServices */ $orderInfoServices = app()->make(StoreOrderCartInfoServices::class); $orderInfo['storeName'] = $orderInfoServices->getCarIdByProductTitle((int)$orderInfo['id']); $res1 = $this->dao->update($orderInfo['id'], $updata); $resPink = true; if ($orderInfo['combination_id'] && $res1 && !$orderInfo['refund_status']) { /** @var StorePinkServices $pinkServices */ $pinkServices = app()->make(StorePinkServices::class); /** @var StoreOrderServices $orderServices */ $orderServices = app()->make(StoreOrderServices::class); $resPink = $pinkServices->createPink($orderServices->tidyOrder($orderInfo, true));//创建拼团 } //缓存抽奖次数 除过线下支付 if (isset($orderInfo['pay_type']) && $orderInfo['pay_type'] != 'offline') { /** @var LuckLotteryServices $luckLotteryServices */ $luckLotteryServices = app()->make(LuckLotteryServices::class); $luckLotteryServices->setCacheLotteryNum((int)$orderInfo['uid'], 'order'); } $orderInfo['send_name'] = $orderInfo['real_name']; //订单支付成功后置事件 event('OrderPaySuccessListener', [$orderInfo]); //用户推送消息事件 event('NoticeListener', [$orderInfo, 'order_pay_success']); //支付成功给客服发送消息 event('NoticeListener', [$orderInfo, 'admin_pay_success_code']); // 推送订单 event('OutPushListener', ['order_pay_push', ['order_id' => (int)$orderInfo['id']]]); // 小程序订单管理 (自提商品) if ($orderInfo['shipping_type'] == 2) { event('OrderShipping', ['product', $orderInfo, 4, '', '']); } $res = $res1 && $resPink; if ($orderInfo['order_type']==1){ //礼包商品订单赠送复购商品优惠卷 $grantNum = sys_config('repeat_discount_num',0); @file_put_contents("quanju.txt", json_encode(['uid'=>$orderInfo['uid'],'grantNum'=>$grantNum])."-礼包订单赠送复购折扣次数\r\n", 8); if ($grantNum > 0){ /** @var UserServices $userServices */ $userServices = app()->make(UserServices::class); $userServices->bcInc($orderInfo['uid'], 'repeat_discount_num', $grantNum, 'uid'); @file_put_contents("quanju.txt", json_encode(['uid'=>$orderInfo['uid'],'grantNum'=>$grantNum])."-礼包订单赠送复购折扣次数\r\n", 8); } } $spread_id = User::where('uid',$orderInfo['uid'])->value('spread_uid'); if ($spread_id>0){ //上级分销奖励 self::spreadReward($spread_id,$orderInfo); self::issueServiceFee($orderInfo['uid'],$orderInfo); } return false !== $res; } /** * 发放优惠券到指定个人 * @return mixed */ public function grantUser($id,$uid) { $data['id'] = $id; $data['uid'] = $uid; if (!$data['id']) return app('json')->fail(100100); /** @var StoreCouponIssueServices $issueService */ $issueService = app()->make(StoreCouponIssueServices::class); $coupon = $issueService->get($data['id']); if (!$coupon) { return app('json')->fail(100026); } else { $coupon = $coupon->toArray(); } $user = explode(',', $data['uid']); $issueService->setCoupon($coupon, $user); return true; } // 发放分销奖励() public function spreadReward($spread_uid, $orderInfo){ try { // 获取上级的分销等级 $agent_level = User::where('uid', $spread_uid)->value('agent_level'); if (!$agent_level) { return false; } // 获取分销等级详细信息 $agentLevelInfo = \app\model\agent\AgentLevel::where('id', $agent_level)->find(); if (!$agentLevelInfo) { return false; } $agentLevelInfo = $agentLevelInfo->toArray(); // 发放优惠券奖励 if ($agentLevelInfo['free_issue'] > 0) { $this->grantUser($agentLevelInfo['free_issue'], $spread_uid); } // 发放佣金奖励 if ($agentLevelInfo['spread_brokerage'] > 0) { // 计算佣金金额:订单价格 * spread_brokerage / 100 $brokerageAmount = bcmul((string)$orderInfo['total_price'], (string)($agentLevelInfo['spread_brokerage'] / 100), 2); if ($brokerageAmount > 0) { /** @var UserServices $userServices */ $userServices = app()->make(UserServices::class); /** @var UserBrokerageServices $userBrokerageServices */ $userBrokerageServices = app()->make(UserBrokerageServices::class); $balance = $userServices->value(['uid' => $spread_uid], 'brokerage_price'); $nickname = User::where('uid',$orderInfo['uid'])->value('nickname'); $userBrokerageServices->income('get_brokerage', $spread_uid, [ 'nickname' => $nickname, 'pay_price' => $orderInfo['total_price'], 'number' => $brokerageAmount, ], bcadd((string)$balance, (string)$brokerageAmount, 2), $orderInfo['id'] ?? 0); $userServices->bcInc($spread_uid, 'brokerage_price', $brokerageAmount, 'uid'); // 发放平级奖励 $this->issueSameLevelReward($spread_uid, $brokerageAmount); } } return true; } catch (\Exception $e) { @file_put_contents("quanju.txt", json_encode($e->getMessage())."-spreadReward报错内容\r\n", 8); @file_put_contents("quanju.txt", json_encode($e->getLine())."-spreadReward报错位置\r\n", 8); @file_put_contents("quanju.txt", json_encode($e->getFile())."-spreadReward报错文件\r\n", 8); throw $e; } } /** * 发放礼包/复购服务费 * 下级用户购买礼包或复购商品后,向上查找分销等级为V2或大于V2的用户,发放服务费 * @param int $uid 购买用户的UID * @param array $orderInfo 订单信息 * @return bool */ public function issueServiceFee($uid, $orderInfo){ try { // 根据订单类型获取服务费金额 $orderType = isset($orderInfo['order_type']) ? (int)$orderInfo['order_type'] : 0; $serviceAmount = 0; if ($orderType === 1) { // 礼包订单:使用系统配置的服务费金额 $serviceAmount = floatval(sys_config('service_gift', 0)); } else { // 复购订单:根据订单金额计算服务费(订单金额 ÷ 50) $orderPrice = isset($orderInfo['total_price']) ? floatval($orderInfo['total_price']) : 0; if ($orderPrice > 0) { $basePrice = floatval(sys_config('service_repeat', 5)); // 单个50元对应的服务费,默认5元 $units = intval($orderPrice / 50); // 计算包含多少个50元 $serviceAmount = $units * $basePrice; @file_put_contents("quanju.txt", json_encode(['orderPrice'=>$orderPrice,'units'=>$units,'basePrice'=>$basePrice,'serviceAmount'=>$serviceAmount])."-复购服务费计算\r\n", 8); } } if ($serviceAmount <= 0) { return false; } // 获取购买用户的昵称 $nickname = User::where('uid', $uid)->value('nickname'); // 获取分销等级表中grade >= 2的等级ID(V2及以上) $qualifiedLevels = \app\model\agent\AgentLevel::where('grade', '>=', 3) ->where('is_del', 0) ->where('status', 1) ->column('id'); // 调试日志:记录符合条件的等级ID @file_put_contents("quanju.txt", json_encode($qualifiedLevels)."-issueServiceFee符合条件等级ID列表\r\n", 8); if (empty($qualifiedLevels)) { return false; } // 从购买用户开始,向上查找第一个V2或以上等级的用户 $currentUid = $uid; while ($currentUid > 0) { $spreadUid = User::where('uid', $currentUid)->value('spread_uid'); if (!$spreadUid || $spreadUid <= 0) { break; } $spreadAgentLevelId = User::where('uid', $spreadUid)->value('agent_level'); // 调试日志:记录检查的用户和等级 @file_put_contents("quanju.txt", json_encode(['spreadUid'=>$spreadUid,'agent_level'=>$spreadAgentLevelId])."-issueServiceFee检查用户等级\r\n", 8); if (!$spreadAgentLevelId) { $currentUid = $spreadUid; continue; } // 检查上级的分销等级是否在V2及以上 if (in_array($spreadAgentLevelId, $qualifiedLevels)) { // 找到了,发放服务费 @file_put_contents("quanju.txt", json_encode(['spreadUid'=>$spreadUid,'agent_level'=>$spreadAgentLevelId,'amount'=>$serviceAmount])."-issueServiceFee发放服务费\r\n", 8); /** @var UserServices $userServices */ $userServices = app()->make(UserServices::class); /** @var UserBrokerageServices $userBrokerageServices */ $userBrokerageServices = app()->make(UserBrokerageServices::class); $incomeType = $orderType === 1 ? 'service_gift' : 'service_repeat'; $balance = $userServices->value(['uid' => $spreadUid], 'brokerage_price'); $userBrokerageServices->income($incomeType, $spreadUid, [ 'nickname' => $nickname, 'pay_price' => $orderInfo['total_price'] ?? 0, 'number' => $serviceAmount, ], bcadd((string)$balance, (string)$serviceAmount, 2), $orderInfo['id'] ?? 0); $userServices->bcInc($spreadUid, 'brokerage_price', $serviceAmount, 'uid'); // 找到后停止查找 break; } $currentUid = $spreadUid; } return true; } catch (\Exception $e) { @file_put_contents("quanju.txt", json_encode($e->getMessage())."-issueServiceFee报错内容\r\n", 8); @file_put_contents("quanju.txt", json_encode($e->getLine())."-issueServiceFee报错位置\r\n", 8); @file_put_contents("quanju.txt", json_encode($e->getFile())."-issueServiceFee报错文件\r\n", 8); throw $e; } } /** * 发放核销订单线路奖励 定时任务 * 针对分销等级为4的用户,统计其直推下级团队中门店核销订单数量 * 当两条线都达到200单时,奖励verific_reward金额 * 当第三条线达到200单时,再奖励more_reward金额 * 第四条及以后达到200单,每次奖励more_reward金额 * @param int $spread_uid 分销等级为4的用户UID * @return bool */ public function verifyLineReward($spread_uid){ try { // 获取用户的分销等级ID $agent_level_id = User::where('uid', $spread_uid)->value('agent_level'); if (!$agent_level_id) { return false; } // 获取分销等级的grade字段 $agentLevelInfo = \app\model\agent\AgentLevel::where('id', $agent_level_id)->find(); if (!$agentLevelInfo) { return false; } $agentGrade = $agentLevelInfo->grade; // 只处理分销等级为4的用户 if ($agentGrade != 4) { return false; } // 获取该用户的所有直推下级 $directUsers = User::where('spread_uid', $spread_uid) ->column('uid'); if (empty($directUsers)) { return false; } // 收集所有需要统计的用户(包括直推下级及其所有下级) $allLineUsers = []; foreach ($directUsers as $directUid) { // 包含直推下级本人及其所有下级 $lineUsers = array_merge([$directUid], $this->getAllTeamUsers($directUid)); $allLineUsers[] = $lineUsers; } @file_put_contents("quanju.txt", json_encode($allLineUsers) . "下级团队统计\r\n", 8); if (empty($allLineUsers)) { return false; } // 统计每条线的核销订单数量 $lineVerifyCounts = []; foreach ($allLineUsers as $lineUsers) { if (empty($lineUsers)) { $lineVerifyCounts[] = 0; continue; } // 查询这些用户拥有的门店的核销订单总量 $totalVerifyNum = \app\model\system\store\SystemStore::whereIn('uid', $lineUsers) ->sum('verify_num'); $lineVerifyCounts[] = (int)$totalVerifyNum; } @file_put_contents("quanju.txt", json_encode($lineVerifyCounts) . "统计达到200单的线路数量\r\n", 8); // 统计达到200单的线路数量 $qualifiedLines = 0; foreach ($lineVerifyCounts as $count) { if ($count >= 200) { $qualifiedLines++; } } if ($qualifiedLines < 2) { return false; } // 获取奖励配置 $verificReward = sys_config('verific_reward', 0); $moreReward = sys_config('more_reward', 0); if ($verificReward <= 0 && $moreReward <= 0) { return false; } // 查询已发放的 verific_reward 次数(line_two_reward) $issuedVerificCount = \app\model\user\UserBrokerage::where('uid', $spread_uid) ->where('type', 'line_two_reward') ->count(); // 查询已发放的 more_reward 次数(line_more_reward) $issuedMoreCount = \app\model\user\UserBrokerage::where('uid', $spread_uid) ->where('type', 'line_more_reward') ->count(); // 计算应该发放的奖励 $verificRewardCount = 0; // verific_reward应该发放的次数(最多1次) $moreRewardCount = 0; // more_reward应该发放的次数 if ($qualifiedLines >= 2) { $verificRewardCount = 1; // 超过2条线,每多一条线发放一次more_reward $moreRewardCount = $qualifiedLines - 2; } // 判断是否需要发放奖励 $needVerificReward = $verificRewardCount > $issuedVerificCount; $needMoreReward = $moreRewardCount > $issuedMoreCount; if (!$needVerificReward && !$needMoreReward) { return false; } /** @var UserServices $userServices */ $userServices = app()->make(UserServices::class); /** @var UserBrokerageServices $userBrokerageServices */ $userBrokerageServices = app()->make(UserBrokerageServices::class); $balance = $userServices->value(['uid' => $spread_uid], 'brokerage_price'); // 发放verific_reward(两条线达标奖励) if ($needVerificReward && $verificReward > 0) { $userBrokerageServices->income('line_two_reward', $spread_uid, [ // 'pay_price' => 0, 'number' => $verificReward, ], bcadd((string)$balance, (string)$verificReward, 2), 0); $userServices->bcInc($spread_uid, 'brokerage_price', $verificReward, 'uid'); $balance = bcadd((string)$balance, (string)$verificReward, 2); // 发放平级奖励 $this->issueSameLevelReward($spread_uid, $verificReward); } // 发放more_reward(第三条及以上线达标,可能多次) if ($needMoreReward && $moreReward > 0) { $needIssueMoreCount = $moreRewardCount - $issuedMoreCount; for ($i = 0; $i < $needIssueMoreCount; $i++) { $userBrokerageServices->income('line_more_reward', $spread_uid, [ // 'pay_price' => 0, 'number' => $moreReward, ], bcadd((string)$balance, (string)$moreReward, 2), 0); $userServices->bcInc($spread_uid, 'brokerage_price', $moreReward, 'uid'); $balance = bcadd((string)$balance, (string)$moreReward, 2); // 发放平级奖励 $this->issueSameLevelReward($spread_uid, $moreReward); } } return true; } catch (\Exception $e) { @file_put_contents("quanju.txt", json_encode($e->getMessage())."-verifyLineReward报错内容\r\n", 8); @file_put_contents("quanju.txt", json_encode($e->getLine())."-verifyLineReward报错位置\r\n", 8); @file_put_contents("quanju.txt", json_encode($e->getFile())."-verifyLineReward报错文件\r\n", 8); throw $e; } } /** * 获取用户的所有下级(递归查询团队) * @param int $uid 用户UID * @return array 所有下级UID数组 */ private function getAllTeamUsers($uid){ $allUsers = []; $this->getTeamUsersRecursive($uid, $allUsers); return $allUsers; } /** * 递归获取用户的所有下级 * @param int $uid 当前用户UID * @param array &$allUsers 已收集的用户数组(引用传递) */ private function getTeamUsersRecursive($uid, &$allUsers){ // 查询该用户的直接下级 $directUsers = User::where('spread_uid', $uid) ->column('uid'); if (empty($directUsers)) { return; } foreach ($directUsers as $userUid) { $allUsers[] = $userUid; // 递归查询该用户的下级 $this->getTeamUsersRecursive($userUid, $allUsers); } } /** * 发放平级奖励 * 只查找第一级上级,如果上级的分销等级等于指定等级,发放平级奖励 * @param int $rewardUid 获得奖励的用户UID * @param float $rewardAmount 奖励金额 * @param int $agentLevelId 分销等级ID * @param float $sameLevelRatio 平级奖励比例 * @return bool */ public function sameLevelReward($rewardUid, $rewardAmount, $agentLevelId, $sameLevelRatio){ try { if ($rewardAmount <= 0 || $sameLevelRatio <= 0) { return false; } // 只查找第一级上级 $spreadUid = User::where('uid', $rewardUid)->value('spread_uid'); if (!$spreadUid || $spreadUid <= 0) { return false; } // 查询上级的分销等级 $spreadAgentLevelId = User::where('uid', $spreadUid)->value('agent_level'); if (!$spreadAgentLevelId || $spreadAgentLevelId != $agentLevelId) { return false; } /** @var UserServices $userServices */ $userServices = app()->make(UserServices::class); /** @var UserBrokerageServices $userBrokerageServices */ $userBrokerageServices = app()->make(UserBrokerageServices::class); // 计算平级奖励金额:奖励金额 * 平级比例 / 100 $sameLevelAmount = bcmul((string)$rewardAmount, (string)($sameLevelRatio / 100), 2); if ($sameLevelAmount <= 0) { return false; } // 发放平级奖励 $balance = $userServices->value(['uid' => $spreadUid], 'brokerage_price'); $userBrokerageServices->income('get_same_level_reward', $spreadUid, [ 'pay_price' => 0, 'number' => $sameLevelAmount, ], bcadd((string)$balance, (string)$sameLevelAmount, 2), 0); $userServices->bcInc($spreadUid, 'brokerage_price', $sameLevelAmount, 'uid'); return true; } catch (\Exception $e) { @file_put_contents("quanju.txt", json_encode($e->getMessage())."-sameLevelReward报错内容\r\n", 8); @file_put_contents("quanju.txt", json_encode($e->getLine())."-sameLevelReward报错位置\r\n", 8); @file_put_contents("quanju.txt", json_encode($e->getFile())."-sameLevelReward报错文件\r\n", 8); throw $e; } } /** * 发放平级奖励(内部调用方法) * 查询所有设置平级奖的等级并发放奖励 * @param int $rewardUid 获得奖励的用户UID * @param float $rewardAmount 奖励金额 * @return bool */ private function issueSameLevelReward($rewardUid, $rewardAmount){ try { // 查询所有设置了平级奖的分销等级(equal_award > 0) $agentLevelsWithAward = \app\model\agent\AgentLevel::where('equal_award', '>', 0) ->column('equal_award', 'id'); if (empty($agentLevelsWithAward)) { return false; } // 获取奖励用户的分销等级 $rewardAgentLevelId = \app\model\user\User::where('uid', $rewardUid)->value('agent_level'); if (!$rewardAgentLevelId || !isset($agentLevelsWithAward[$rewardAgentLevelId])) { return false; } // 只发一次:只查询奖励用户上级中分销等级相同的,发放平级奖 $this->sameLevelReward($rewardUid, $rewardAmount, $rewardAgentLevelId, $agentLevelsWithAward[$rewardAgentLevelId]); return true; } catch (\Exception $e) { @file_put_contents("quanju.txt", json_encode($e->getMessage())."-issueSameLevelReward报错内容\r\n", 8); @file_put_contents("quanju.txt", json_encode($e->getLine())."-issueSameLevelReward报错位置\r\n", 8); @file_put_contents("quanju.txt", json_encode($e->getFile())."-issueSameLevelReward报错文件\r\n", 8); throw $e; } } }