order('id', 'desc') ->find(); // 如果没有设置,返回默认值 if (!$setting) { $setting = [ 'default_rate' => 0.10, // 10% 'min_withdrawal' => 10.00, 'max_withdrawal' => 10000.00, 'withdrawal_fee_rate' => 0.01, // 1% ]; } return $setting; } /** * 计算佣金 */ public function calculateCommission($orderAmount, $distributorId = 0) { if ($distributorId <= 0) { return [ 'has_commission' => false, 'commission_rate' => 0, 'commission_amount' => 0 ]; } $setting = $this->getDistributionSetting(); $commissionRate = ($setting['default_rate']/100) ?? 0.10; // 计算佣金金额 $commissionAmount = bcmul($orderAmount, $commissionRate, 2); return [ 'has_commission' => true, 'commission_rate' => $commissionRate, 'commission_amount' => $commissionAmount, 'setting' => $setting ]; } /** * 创建分销记录 */ public function createDistributionRecord($data) { $recordData = [ 'order_id' => $data['order_id'] ?? 0, 'product_id' => $data['product_id'] ?? 0, 'buyer_id' => $data['buyer_id'] ?? 0, 'distributor_id' => $data['distributor_id'] ?? 0, 'commission_rate' => $data['commission_rate'] ?? 0, 'commission_amount' => $data['commission_amount'] ?? 0, 'status' => 1, // 1=待结算 'create_time' => date('Y-m-d H:i:s') ]; return Db::table('ba_distribution_record')->insertGetId($recordData); } /** * 更新分销记录状态 */ public function updateDistributionRecord($orderId, $status, $settleTime = null) { $updateData = [ 'status' => $status, 'update_time' => date('Y-m-d H:i:s') ]; if ($settleTime) { $updateData['settle_time'] = $settleTime; } return Db::table('ba_distribution_record') ->where('order_id', $orderId) ->update($updateData); } /** * 获取用户佣金统计 */ public function getUserCommissionSummary($userId) { $summary = Db::table('ba_distribution_record') ->where('distributor_id', $userId) ->field(' COUNT(*) as total_orders, SUM(CASE WHEN status = 1 THEN commission_amount ELSE 0 END) as pending_amount, SUM(CASE WHEN status = 2 THEN commission_amount ELSE 0 END) as settled_amount, SUM(CASE WHEN status = 3 THEN commission_amount ELSE 0 END) as canceled_amount ') ->find(); return $summary ?: [ 'total_orders' => 0, 'pending_amount' => 0, 'settled_amount' => 0, 'canceled_amount' => 0 ]; } /** * 更新用户佣金表 */ public function updateUserCommission($userId) { $summary = $this->getUserCommissionSummary($userId); // 已结算的佣金可以作为当前佣金(可提现) $currentCommission = $summary['settled_amount'] ?? 0; $totalCommission = $summary['settled_amount'] + $summary['pending_amount']; // 检查用户佣金表是否有记录 $userCommission = Db::table('ba_user_commission') ->where('user_id', $userId) ->find(); $data = [ 'total_commission' => $totalCommission, 'current_commission' => $currentCommission, 'update_time' => date('Y-m-d H:i:s') ]; if ($userCommission) { // 更新 Db::table('ba_user_commission') ->where('user_id', $userId) ->update($data); } else { // 创建 $data['user_id'] = $userId; $data['promotion_link'] = $this->generatePromotionLink($userId); Db::table('ba_user_commission')->insert($data); } } /** * 处理订单佣金 */ public function processOrderCommission(int $orderId): bool { try { // 获取订单信息 $order = Db::name('order') ->where('id', $orderId) ->where('pay_status', 1) // 已支付 ->where('order_status', 'IN', [1, 3]) // 已确认或已完成 ->where('is_commission', 0) // 未处理佣金 ->find(); if (!$order) { Log::info("订单不满足佣金处理条件: {$orderId}"); return false; } // 如果有分销人,处理佣金 if (!empty($order['distributor_id']) && $order['commission_amount'] > 0) { $distributorId = $order['distributor_id']; $commissionAmount = $order['commission_amount']; // 更新分销人佣金 $this->addCommission($distributorId, $commissionAmount, [ 'type' => 2, // 订单佣金 'order_id' => $orderId, 'from_user_id' => $order['user_id'], 'remark' => '订单佣金:' . $order['order_no'] . ',金额:¥' . $commissionAmount ]); // 标记订单佣金已处理 Db::name('order') ->where('id', $orderId) ->update([ 'is_commission' => 1, 'update_time' => date('Y-m-d H:i:s') ]); Log::info("订单佣金处理成功: 订单ID={$orderId}, 分销人ID={$distributorId}, 佣金={$commissionAmount}"); } return true; } catch (\Throwable $e) { Log::error("处理订单佣金失败: " . $e->getMessage()); return false; } } /** * 增加佣金 */ public function addCommission(int $userId, float $amount, array $extra = []): bool { try { if ($amount <= 0) { return false; } Db::startTrans(); // 获取当前佣金 $commission = Db::name('user_commission') ->where('user_id', $userId) ->lock(true) ->find(); $balanceBefore = $commission ? $commission['current_commission'] : 0; $balanceAfter = $balanceBefore + $amount; if ($commission) { // 更新现有记录 Db::name('user_commission') ->where('user_id', $userId) ->update([ 'total_commission' => Db::raw('total_commission + ' . $amount), 'current_commission' => Db::raw('current_commission + ' . $amount), 'update_time' => date('Y-m-d H:i:s') ]); } else { // 创建新记录 $promotionLink = $this->generatePromotionLink($userId); Db::name('user_commission')->insert([ 'user_id' => $userId, 'total_commission' => $amount, 'current_commission' => $amount, 'withdrawn_commission' => 0.00, 'frozen_commission' => 0.00, 'promotion_link' => $promotionLink, 'invitation_count' => 0, 'total_invitation' => 0, 'update_time' => date('Y-m-d H:i:s') ]); } // 记录佣金流水 Db::name('commission_flow')->insert([ 'user_id' => $userId, 'order_id' => $extra['order_id'] ?? null, 'from_user_id' => $extra['from_user_id'] ?? null, 'type' => $extra['type'] ?? 1, 'amount' => $amount, 'balance_before' => $balanceBefore, 'balance_after' => $balanceAfter, 'remark' => $extra['remark'] ?? ('佣金增加:¥' . $amount), 'create_time' => date('Y-m-d H:i:s') ]); Db::commit(); return true; } catch (\Throwable $e) { Db::rollback(); Log::error("增加佣金失败: " . $e->getMessage()); return false; } } /** * 处理提现 */ public function processWithdrawal(int $withdrawalId): bool { try { $withdrawal = Db::name('withdrawal_record') ->where('id', $withdrawalId) ->where('status', 0) // 待审核 ->lock(true) ->find(); if (!$withdrawal) { Log::warning("提现记录不存在或状态不符: {$withdrawalId}"); return false; } $userId = $withdrawal['user_id']; $amount = $withdrawal['amount']; // 检查用户佣金是否足够 $commission = Db::name('user_commission') ->where('user_id', $userId) ->find(); if (!$commission || $commission['current_commission'] < $amount) { Log::warning("用户佣金不足: 用户ID={$userId}, 需要={$amount}, 当前={$commission['current_commission']}"); return false; } Db::startTrans(); // 扣除佣金 $newCurrent = $commission['current_commission'] - $amount; $newWithdrawn = $commission['withdrawn_commission'] + $amount; Db::name('user_commission') ->where('user_id', $userId) ->update([ 'current_commission' => $newCurrent, 'withdrawn_commission' => $newWithdrawn, 'update_time' => date('Y-m-d H:i:s') ]); // 记录佣金流水 Db::name('commission_flow')->insert([ 'user_id' => $userId, 'type' => 3, // 提现扣除 'amount' => -$amount, 'balance_before' => $commission['current_commission'], 'balance_after' => $newCurrent, 'remark' => '提现扣除:' . $withdrawal['withdrawal_no'] . ',金额:¥' . $amount, 'create_time' => date('Y-m-d H:i:s') ]); // 更新提现记录状态为审核通过(实际打款需要另外处理) Db::name('withdrawal_record') ->where('id', $withdrawalId) ->update([ 'status' => 1, // 审核通过 'audit_time' => date('Y-m-d H:i:s'), 'current_balance' => $commission['current_commission'], 'balance_after' => $newCurrent, 'update_time' => date('Y-m-d H:i:s') ]); Db::commit(); Log::info("提现处理成功: 提现ID={$withdrawalId}, 用户ID={$userId}, 金额={$amount}"); return true; } catch (\Throwable $e) { Db::rollback(); Log::error("处理提现失败: " . $e->getMessage()); return false; } } /** * 获取用户佣金详情 */ public function getUserCommissionDetail(int $userId): array { try { // 佣金信息 $commission = Db::name('user_commission') ->where('user_id', $userId) ->find(); if (!$commission) { $commission = [ 'total_commission' => 0.00, 'current_commission' => 0.00, 'withdrawn_commission' => 0.00, 'frozen_commission' => 0.00, 'promotion_link' => $this->generatePromotionLink($userId), 'invitation_count' => 0, 'total_invitation' => 0 ]; } // 最近佣金流水 $flows = Db::name('commission_flow') ->where('user_id', $userId) ->order('create_time', 'desc') ->limit(50) ->select() ->toArray(); // 统计今日/本月佣金 $todayStart = date('Y-m-d 00:00:00'); $monthStart = date('Y-m-01 00:00:00'); $todayIncome = Db::name('commission_flow') ->where('user_id', $userId) ->where('amount', '>', 0) ->where('create_time', '>=', $todayStart) ->sum('amount'); $monthIncome = Db::name('commission_flow') ->where('user_id', $userId) ->where('amount', '>', 0) ->where('create_time', '>=', $monthStart) ->sum('amount'); return [ 'commission' => $commission, 'flows' => $flows, 'stats' => [ 'today_income' => $todayIncome ?: 0, 'month_income' => $monthIncome ?: 0 ] ]; } catch (\Throwable $e) { Log::error("获取用户佣金详情失败: " . $e->getMessage()); return [ 'commission' => [ 'total_commission' => 0.00, 'current_commission' => 0.00, 'withdrawn_commission' => 0.00, 'frozen_commission' => 0.00, 'promotion_link' => '', 'invitation_count' => 0, 'total_invitation' => 0 ], 'flows' => [], 'stats' => [ 'today_income' => 0, 'month_income' => 0 ] ]; } } /** * 生成唯一邀请码 */ public function generateInvitationCode(): string { $maxAttempts = 10; $attempts = 0; while ($attempts < $maxAttempts) { // 方法1:使用数字+字母组合 $chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'; // 去掉容易混淆的字符 $code = ''; for ($i = 0; $i < 6; $i++) { $code .= $chars[mt_rand(0, strlen($chars) - 1)]; } // 方法2:或者使用更短的邀请码 // $code = strtoupper(substr(md5(uniqid()), 0, 6)); // 检查邀请码是否已存在 $exists = Db::table('ba_user') ->where('invitation_code', $code) ->count(); if (!$exists) { return $code; } $attempts++; // 如果冲突,尝试不同的算法 if ($attempts >= 5) { $code = 'INV' . mt_rand(1000, 9999); $exists = Db::table('ba_user') ->where('invitation_code', $code) ->count(); if (!$exists) { return $code; } } } // 如果还是冲突,使用时间戳+随机数 return 'INV' . time() . mt_rand(10, 99); } /** * 生成推广链接 */ private function generatePromotionLink(int $userId): string { // 获取用户的邀请码 $user = Db::table('ba_user') ->where('id', $userId) ->field('invitation_code') ->find(); $invitationCode = $user['invitation_code'] ?? ''; if (empty($invitationCode)) { // 如果用户还没有邀请码,先生成一个 $invitationCode = $this->generateInvitationCode(); Db::table('ba_user') ->where('id', $userId) ->update(['invitation_code' => $invitationCode]); } $domain = request()->domain(); return $domain . '/#/user/register?invite=' . $invitationCode; } }