getCommissionEvent(); if ($commissionEvent !== $event && $event !== 'admin') { return false; } return self::shouldDeferWalletUntilGatewaySplitResolves($order); } public static function shouldDeferRegionalWallet($order, $event) { $regionalEvent = (new RegionalConfig())->getCommissionEvent(); if ($regionalEvent !== $event && $event !== 'admin') { return false; } return self::shouldDeferWalletUntilGatewaySplitResolves($order); } /** * 分销钩子是否应把待发佣金写入余额(false = 等分账 finalize 或已走通道,避免与汇付/微信分账重复) */ public static function shouldSettleCommissionViaWalletHook($order, $event) { $commissionEvent = (new CommissionConfig())->getCommissionEvent(); if ($commissionEvent !== $event && $event !== 'admin') { return false; } if (self::shouldDeferWalletUntilGatewaySplitResolves($order)) { return false; } return true; } /** * 区域代理钩子是否应把待发佣金写入余额 */ public static function shouldSettleRegionalViaWalletHook($order, $event) { $regionalEvent = (new RegionalConfig())->getCommissionEvent(); if ($regionalEvent !== $event && $event !== 'admin') { return false; } if (self::shouldDeferWalletUntilGatewaySplitResolves($order)) { return false; } return true; } /** * 分销/区域结算事件(如 payed)早于 split_timing(如 confirm)时,仍应等分账结束再入钱包 */ protected static function shouldDeferWalletUntilGatewaySplitResolves($order) { if (is_numeric($order)) { $order = Order::get($order); } if (!$order) { return false; } $config = new Config(); if (!$config->isEnable() || !$config->shouldSkipWallet()) { return false; } // 分账已成功:佣金应由 finalizeAfterSplitAttempt 处理(或已标记通道到账),钩子不得再入余额 if (self::isSplitSuccessful($order['id'])) { return true; } if (class_exists('\\addons\\shopro_huifu\\library\\Bridge') && \addons\shopro_huifu\library\Bridge::shouldHandleSplit($order)) { return true; } if (in_array($config->getMode(), ['wechat', 'both'], true) && $order['pay_type'] === 'wechat') { return true; } return false; } /** * 当前订单是否应等分账结果再决定钱包入账 */ public static function shouldDeferForGatewaySplit($order, $event) { if (is_numeric($order)) { $order = Order::get($order); } if (!$order) { return false; } $config = new Config(); if (!$config->isEnable() || !$config->shouldSkipWallet()) { return false; } if ($config->getTiming() !== $event) { return false; } if (class_exists('\\addons\\shopro_huifu\\library\\Bridge') && \addons\shopro_huifu\library\Bridge::shouldHandleSplit($order)) { return true; } if (in_array($config->getMode(), ['wechat', 'both'], true) && $order['pay_type'] === 'wechat') { return true; } return false; } public static function isSplitSuccessful($orderId) { return SplitOrder::where('order_id', $orderId) ->where('status', 'in', [2, 3]) ->count() > 0; } /** * 分账尝试结束后结算佣金(汇付成功=按人混合;其它成功=整单不入钱包;失败=整单入钱包) */ public static function finalizeAfterSplitAttempt($orderId, $event, $splitExecutedOk = false) { if (!self::shouldDeferForGatewaySplit($orderId, $event)) { return; } if (self::isSplitSuccessful($orderId)) { if (self::shouldSettleHuifuPerReceiver($orderId)) { self::settleOrderHybridHuifuGatewayAndWallet($orderId, $event); } else { self::settleOrderWithoutWallet($orderId, $event); } } else { self::settleOrderToWallet($orderId, $event); } } /** * 汇付延时分账:仅出现在分账明细中的推广员/区域公司视为通道已分,其余佣金进钱包 */ public static function settleOrderHybridHuifuGatewayAndWallet($orderId, $event) { $gateway = self::collectGatewaySplitUserIds($orderId); $commissionLib = new CommissionRewardLibrary(); $commissionOrders = CommissionOrderModel::where('order_id', $orderId) ->where('commission_reward_status', CommissionRewardLibrary::COMMISSION_REWARD_STATUS_WAITING) ->select(); foreach ($commissionOrders as $commissionOrder) { if ($commissionOrder['commission_event'] !== $event && $event !== 'admin') { continue; } $rewards = CommissionRewardModel::where('commission_order_id', $commissionOrder['id']) ->where('status', CommissionRewardLibrary::COMMISSION_REWARD_STATUS_WAITING) ->select(); foreach ($rewards as $reward) { $userId = (int) $reward['agent_id']; if ($userId > 0 && in_array($userId, $gateway['promoter'], true)) { $commissionLib->runCommissionRewardWithoutWallet($event, $reward); } else { $commissionLib->runCommissionReward($event, $reward); } } self::markCommissionOrderSettledIfDone($commissionOrder); } $regionalLib = new RegionalRewardLibrary(); $regionalOrders = RegionalOrderModel::where('order_id', $orderId) ->where('commission_reward_status', RegionalRewardLibrary::STATUS_WAITING) ->select(); foreach ($regionalOrders as $regionalOrder) { if ($regionalOrder['commission_event'] !== $event) { continue; } $rewards = RegionalRewardModel::where('regional_order_id', $regionalOrder['id']) ->where('status', RegionalRewardLibrary::STATUS_WAITING) ->select(); foreach ($rewards as $reward) { $userId = (int) $reward['agent_user_id']; if ($userId > 0 && in_array($userId, $gateway['regional_agent'], true)) { $regionalLib->settleRewardWithoutWallet($reward, $event); } else { $regionalLib->settleReward($reward, $event); } } self::markRegionalOrderSettledIfDone($regionalOrder); } } protected static function shouldSettleHuifuPerReceiver($orderId) { $order = Order::get($orderId); if (!$order) { return false; } return class_exists('\\addons\\shopro_huifu\\library\\Bridge') && \addons\shopro_huifu\library\Bridge::shouldHandleSplit($order); } /** * @return array{promoter:int[],regional_agent:int[]} */ protected static function collectGatewaySplitUserIds($orderId) { $promoter = []; $regional = []; $splitOrder = SplitOrder::where('order_id', $orderId) ->where('status', 'in', [2, 3]) ->order('id', 'desc') ->find(); if (!$splitOrder) { return ['promoter' => [], 'regional_agent' => []]; } $rows = SplitOrderReceiver::where('split_order_id', $splitOrder['id'])->select(); foreach ($rows as $row) { $roleType = (string) ($row['role_type'] ?? ''); if (!in_array($roleType, ['promoter', 'regional_agent'], true)) { continue; } $receiverId = (int) ($row['receiver_id'] ?? 0); if ($receiverId <= 0) { continue; } $receiver = Receiver::get($receiverId); if (!$receiver) { continue; } $roleUserId = (int) ($receiver['role_id'] ?? 0); if ($roleUserId <= 0) { continue; } if ($roleType === 'promoter') { $promoter[$roleUserId] = $roleUserId; } else { $regional[$roleUserId] = $roleUserId; } } return [ 'promoter' => array_values($promoter), 'regional_agent' => array_values($regional), ]; } protected static function markCommissionOrderSettledIfDone($commissionOrder) { $waiting = CommissionRewardModel::where('commission_order_id', $commissionOrder['id']) ->where('status', CommissionRewardLibrary::COMMISSION_REWARD_STATUS_WAITING) ->count(); if ($waiting > 0) { return; } if ($commissionOrder['commission_reward_status'] !== CommissionRewardLibrary::COMMISSION_REWARD_STATUS_WAITING) { return; } $commissionOrder->commission_reward_status = CommissionRewardLibrary::COMMISSION_REWARD_STATUS_ACCOUNTED; $commissionOrder->commission_time = time(); $commissionOrder->save(); } protected static function markRegionalOrderSettledIfDone($regionalOrder) { $waiting = RegionalRewardModel::where('regional_order_id', $regionalOrder['id']) ->where('status', RegionalRewardLibrary::STATUS_WAITING) ->count(); if ($waiting > 0) { return; } if ($regionalOrder['commission_reward_status'] !== RegionalRewardLibrary::STATUS_WAITING) { return; } $regionalOrder->commission_reward_status = RegionalRewardLibrary::STATUS_ACCOUNTED; $regionalOrder->commission_time = time(); $regionalOrder->save(); } public static function settleOrderWithoutWallet($orderId, $event) { $commissionLib = new CommissionRewardLibrary(); $commissionOrders = CommissionOrderModel::where('order_id', $orderId) ->where('commission_reward_status', CommissionRewardLibrary::COMMISSION_REWARD_STATUS_WAITING) ->select(); foreach ($commissionOrders as $commissionOrder) { if ($commissionOrder['commission_event'] === $event || $event === 'admin') { $commissionLib->runCommissionRewardByOrderWithoutWallet($event, $commissionOrder); } } $regionalLib = new RegionalRewardLibrary(); $regionalOrders = RegionalOrderModel::where('order_id', $orderId) ->where('commission_reward_status', RegionalRewardLibrary::STATUS_WAITING) ->select(); foreach ($regionalOrders as $regionalOrder) { if ($regionalOrder['commission_event'] === $event) { $regionalLib->settleByRegionalOrderWithoutWallet($regionalOrder->id, $event); } } } public static function settleOrderToWallet($orderId, $event) { $commissionLib = new CommissionRewardLibrary(); $commissionOrders = CommissionOrderModel::where('order_id', $orderId) ->where('commission_reward_status', CommissionRewardLibrary::COMMISSION_REWARD_STATUS_WAITING) ->select(); foreach ($commissionOrders as $commissionOrder) { if ($commissionOrder['commission_event'] === $event || $event === 'admin') { $commissionLib->runCommissionRewardByOrder($event, $commissionOrder); } } $regionalLib = new RegionalRewardLibrary(); $regionalOrders = RegionalOrderModel::where('order_id', $orderId) ->where('commission_reward_status', RegionalRewardLibrary::STATUS_WAITING) ->select(); foreach ($regionalOrders as $regionalOrder) { if ($regionalOrder['commission_event'] === $event) { $regionalLib->settleByRegionalOrder($regionalOrder->id, $event); } } } }