用户奖励方法UserRewardService
<?php
declare(strict_types=1);
namespace app\services\user;
use app\services\BaseServices;
use app\services\order\StoreOrderCartInfoServices;
use app\services\order\StoreOrderServices;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\facade\Log;
/**
* 会员与分销奖励服务
* Class UserRewardService
*/
class UserRewardService extends BaseServices
{
// 报单产品ID
const PRODUCT_REPORT_ID = 1;
// 奖励类型常量
const REWARD_TYPE_DIRECT_CASH = 'direct_cash'; // 直接分享现金奖励
const REWARD_TYPE_DIRECT_COUPON = 'direct_coupon'; // 直接分享消费券奖励
const REWARD_TYPE_SERVICE_CENTER_FEE = 'service_center_fee'; // 服务中心服务费
const REWARD_TYPE_SERVICE_POINT_FEE = 'service_point_fee'; // 服务点服务费(新增)
const REWARD_TYPE_SERVICE_POINT_PEER = 'service_point_peer'; // 服务点平级奖励
const REWARD_TYPE_REPURCHASE_DIRECT = 'repurchase_direct'; // 复购直接推荐人
const REWARD_TYPE_REPURCHASE_CENTER = 'repurchase_center'; // 复购服务中心
const REWARD_TYPE_REPURCHASE_POINT = 'repurchase_point'; // 复购服务点
/**
* 处理订单奖励(收货后调用)
* @param array $order 订单信息
* @param int $uid 收货用户UID
* @return bool
*/
public function handleOrderReward(array $order, int $uid): bool
{
// 检查是否已发放奖励
if ($order['reward_status'] == 1) {
return true;
}
// 获取订单商品信息
$cartInfo = $this->getOrderCartInfo($order['id']);
if (!$cartInfo) {
return true;
}
// 判断是否为报单产品(商品ID=1)
$isReportProduct = $this->checkIsReportProduct($cartInfo);
try {
$this->transaction(function () use ($order, $uid, $isReportProduct, $cartInfo) {
if ($isReportProduct) {
// 报单产品:发放直接分享奖励
$this->handleReportProductReward($order, $uid);
// 发放服务中心服务费(每笔订单100元)
$this->handleServiceCenterFee($order, $uid);
// ===== 新增:发放服务点服务费(每笔订单100元) =====
$this->handleServicePointFee($order, $uid);
// 发放服务点平级奖励(3%)
$this->handleServicePointPeerReward($order, $uid, $cartInfo);
} else {
// 复购产品:发放复购奖励
$this->handleRepurchaseReward($order, $uid, $cartInfo);
// 复购也发放服务中心服务费
$this->handleServiceCenterFee($order, $uid);
// 复购也发放服务点平级奖励
$this->handleServicePointPeerReward($order, $uid, $cartInfo);
}
// 标记订单奖励已发放
app()->make(StoreOrderServices::class)->update($order['id'], ['reward_status' => 1]);
});
return true;
} catch (\Exception $e) {
Log::error('订单奖励发放失败:订单ID-' . $order['id'] . ',错误:' . $e->getMessage());
return false;
}
}
/**
* 处理报单产品奖励
* @param array $order
* @param int $uid
* @return void
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
protected function handleReportProductReward(array $order, int $uid): void
{
// 获取上级推荐人
$spreadUid = $this->getSpreadUid($uid);
if (!$spreadUid) {
return;
}
/** @var UserServices $userService */
$userService = app()->make(UserServices::class);
$spreadUser = $userService->getUserInfo($spreadUid);
if (!$spreadUser) {
return;
}
// 奖励金额配置
$cashReward = 650; // 现金奖励650元
$couponReward = 650; // 消费券650积分
// 1. 发放现金奖励到推荐人的佣金账户
$currentBrokerage = $spreadUser['brokerage_price'];
$newBrokerage = bcadd((string)$currentBrokerage, (string)$cashReward, 2);
/** @var UserBrokerageServices $brokerageService */
$brokerageService = app()->make(UserBrokerageServices::class);
$brokerageService->income(
'direct_cash',
$spreadUid,
[
'nickname' => $userService->value($uid, 'nickname'),
'pay_price' => $order['pay_price'],
'number' => $cashReward,
'frozen_time' => time() + intval(sys_config('extract_time', 30)) * 86400
],
$newBrokerage,
$order['id']
);
// 更新用户佣金余额
$userService->update($spreadUid, ['brokerage_price' => $newBrokerage], 'uid');
// 2. 发放消费券(积分)到推荐人
$currentIntegral = $spreadUser['integral'];
$newIntegral = $currentIntegral + $couponReward;
/** @var UserBillServices $billService */
$billService = app()->make(UserBillServices::class);
$billService->income(
'direct_reward_coupon',
$spreadUid,
[
'nickname' => $userService->value($uid, 'nickname'),
'pay_price' => $order['pay_price'],
'number' => $couponReward,
],
$newIntegral,
$order['id']
);
// 更新用户积分
$userService->update($spreadUid, ['integral' => $newIntegral], 'uid');
$userInfo = $userService->getUserInfo($uid);
$userService->update($userInfo['uid'], ['first_order' => 1]);
// 发送消息通知
event('CustomNoticeListener', [$spreadUid, [
'uid' => $spreadUid,
'cash' => $cashReward,
'coupon' => $couponReward,
'time' => date('Y-m-d H:i:s')
], 'direct_reward']);
}
/**
* 处理服务中心服务费(每笔订单100元)
* @param array $order
* @param int $uid
* @return void
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
protected function handleServiceCenterFee(array $order, int $uid): void
{
/** @var UserServices $userService */
$userService = app()->make(UserServices::class);
// 获取消费者的所属服务中心
$userInfo = $userService->getUserInfo($uid);
if (!$userInfo || $userInfo['service_center_uid'] == 0) {
return;
}
$centerUid = $userInfo['service_center_uid'];
$centerUser = $userService->getUserInfo($centerUid);
if (!$centerUser || $centerUser['is_service_center'] != 1) {
return;
}
$feeAmount = 100; // 每笔订单100元服务费
$currentBrokerage = $centerUser['brokerage_price'];
$newBrokerage = bcadd((string)$currentBrokerage, (string)$feeAmount, 2);
/** @var UserBrokerageServices $brokerageService */
$brokerageService = app()->make(UserBrokerageServices::class);
$brokerageService->income(
'get_center_brokerage',
$centerUid,
[
'nickname' => $userInfo['nickname'],
'order_id' => $order['order_id'],
'number' => $feeAmount,
'frozen_time' => time() + intval(sys_config('extract_time', 30)) * 86400
],
$newBrokerage,
$order['id']
);
$userService->update($centerUid, ['brokerage_price' => $newBrokerage], 'uid');
}
// ===== 新增:处理服务点服务费(每笔订单100元) =====
/**
* 处理服务点服务费(每笔订单100元)
* @param array $order
* @param int $uid
* @return void
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
protected function handleServicePointFee(array $order, int $uid): void
{
/** @var UserServices $userService */
$userService = app()->make(UserServices::class);
// 获取消费者的所属服务点
$userInfo = $userService->getUserInfo($uid);
if (!$userInfo || $userInfo['service_point_uid'] == 0) {
return;
}
$pointUid = $userInfo['service_point_uid'];
$pointUser = $userService->getUserInfo($pointUid);
if (!$pointUser || $pointUser['is_service_point'] != 1) {
return;
}
$feeAmount = 100; // 每笔订单100元服务费
$currentBrokerage = $pointUser['brokerage_price'];
$newBrokerage = bcadd((string)$currentBrokerage, (string)$feeAmount, 2);
/** @var UserBrokerageServices $brokerageService */
$brokerageService = app()->make(UserBrokerageServices::class);
$brokerageService->income(
'get_point_brokerage', // 类型标识
$pointUid,
[
'nickname' => $userInfo['nickname'],
'order_id' => $order['order_id'],
'number' => $feeAmount,
'frozen_time' => time() + intval(sys_config('extract_time', 30)) * 86400
],
$newBrokerage,
$order['id']
);
$userService->update($pointUid, ['brokerage_price' => $newBrokerage], 'uid');
}
// ===== 新增结束 =====
/**
* 处理服务点平级奖励(3%+3%)
* @param array $order
* @param int $uid
* @param array $cartInfo
* @return void
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
protected function handleServicePointPeerReward(array $order, int $uid, array $cartInfo): void
{
/** @var UserServices $userService */
$userService = app()->make(UserServices::class);
// 获取消费者的所属服务点
$userInfo = $userService->getUserInfo($uid);
if (!$userInfo || $userInfo['service_point_uid'] == 0) {
return;
}
$pointUid = $userInfo['service_point_uid'];
$pointUser = $userService->getUserInfo($pointUid);
if (!$pointUser || $pointUser['is_service_point'] != 1) {
return;
}
// 检查是否存在父级服务点(平级条件)
$parentPointUid = $pointUser['parent_service_point_uid'];
if ($parentPointUid == 0) {
return; // 没有父级服务点,不发放平级奖励
}
$parentPointUser = $userService->getUserInfo($parentPointUid);
if (!$parentPointUser || $parentPointUser['is_service_point'] != 1) {
return;
}
// 计算奖励金额:订单金额的3%
$orderAmount = $order['pay_price'];
$rewardAmount = bcmul((string)$orderAmount, '0.03', 2);
if ($rewardAmount <= 0) {
return;
}
// 发放给所属服务点3%
$this->addBrokerageToUser($pointUid, (float)$rewardAmount, $order['id'], 'point_peer_self', [
'nickname' => $userInfo['nickname'],
'order_id' => $order['order_id'],
'number' => $rewardAmount,
'level' => 'self'
]);
// 发放给父级服务点3%
$this->addBrokerageToUser($parentPointUid, (float)$rewardAmount, $order['id'], 'point_peer_parent', [
'nickname' => $userInfo['nickname'],
'order_id' => $order['order_id'],
'number' => $rewardAmount,
'level' => 'parent'
]);
}
/**
* 处理复购奖励
* @param array $order
* @param int $uid
* @param array $cartInfo
* @return void
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
protected function handleRepurchaseReward(array $order, int $uid, array $cartInfo): void
{
$orderAmount = $order['pay_price'];
// 1. 直接推荐人获得30%
$directReward = bcmul((string)$orderAmount, '0.30', 2);
$spreadUid = $this->getSpreadUid($uid);
if ($spreadUid && $directReward > 0) {
$this->addBrokerageToUser($spreadUid, (float)$directReward, $order['id'], 'repurchase_direct', [
'nickname' => app()->make(UserServices::class)->value($uid, 'nickname'),
'order_id' => $order['order_id'],
'number' => $directReward
]);
}
// 2. 服务中心获得5%
/** @var UserServices $userService */
$userService = app()->make(UserServices::class);
$userInfo = $userService->getUserInfo($uid);
if ($userInfo && $userInfo['service_center_uid'] > 0) {
$centerReward = bcmul((string)$orderAmount, '0.05', 2);
if ($centerReward > 0) {
$this->addBrokerageToUser($userInfo['service_center_uid'], (float)$centerReward, $order['id'], 'repurchase_center', [
'nickname' => $userInfo['nickname'],
'order_id' => $order['order_id'],
'number' => $centerReward
]);
}
}
// 3. 服务点获得5%
if ($userInfo && $userInfo['service_point_uid'] > 0) {
$pointReward = bcmul((string)$orderAmount, '0.05', 2);
if ($pointReward > 0) {
$this->addBrokerageToUser($userInfo['service_point_uid'], (float)$pointReward, $order['id'], 'repurchase_point', [
'nickname' => $userInfo['nickname'],
'order_id' => $order['order_id'],
'number' => $pointReward
]);
}
}
}
/**
* 添加佣金到用户
* @param int $targetUid
* @param float $amount
* @param int $orderId
* @param string $type
* @param array $extra
* @return void
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
protected function addBrokerageToUser(int $targetUid, float $amount, int $orderId, string $type, array $extra = []): void
{
if ($amount <= 0 || $targetUid <= 0) {
return;
}
/** @var UserServices $userService */
$userService = app()->make(UserServices::class);
$targetUser = $userService->getUserInfo($targetUid);
if (!$targetUser) {
return;
}
$currentBrokerage = $targetUser['brokerage_price'];
$newBrokerage = bcadd((string)$currentBrokerage, (string)$amount, 2);
/** @var UserBrokerageServices $brokerageService */
$brokerageService = app()->make(UserBrokerageServices::class);
$titleMap = [
'point_peer_self' => '服务点平级奖励(本级)',
'point_peer_parent' => '服务点平级奖励(上级)',
'repurchase_direct' => '复购直接推荐奖励',
'repurchase_center' => '复购服务中心奖励',
'repurchase_point' => '复购服务点奖励',
'center_fee' => '服务中心服务费',
'point_fee' => '服务点服务费' // 新增
];
$brokerageService->income(
$type,
$targetUid,
[
'number' => $amount,
'frozen_time' => time() + intval(sys_config('extract_time', 30)) * 86400,
'title' => $titleMap[$type] ?? '佣金奖励',
'order_id' => $extra['order_id'] ?? '',
'nickname' => $extra['nickname'] ?? ''
],
$newBrokerage,
$orderId
);
$userService->update($targetUid, ['brokerage_price' => $newBrokerage], 'uid');
}
/**
* 检查订单是否为报单产品
* @param array $cartInfo
* @return bool
*/
protected function checkIsReportProduct(array $cartInfo): bool
{
foreach ($cartInfo as $cart) {
$cartData = is_string($cart['cart_info']) ? json_decode($cart['cart_info'], true) : $cart['cart_info'];
if (isset($cartData['product_id']) && $cartData['product_id'] == self::PRODUCT_REPORT_ID) {
return true;
}
}
return false;
}
/**
* 获取订单商品信息
* @param int $orderId
* @return array
*/
protected function getOrderCartInfo(int $orderId): array
{
/** @var StoreOrderCartInfoServices $cartService */
$cartService = app()->make(StoreOrderCartInfoServices::class);
return $cartService->getCartColunm(['oid' => $orderId], 'cart_info,unique', 'id');
}
/**
* 获取上级推荐人UID
* @param int $uid
* @return int
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
protected function getSpreadUid(int $uid): int
{
/** @var UserServices $userService */
$userService = app()->make(UserServices::class);
$userInfo = $userService->getUserInfo($uid);
return $userInfo['spread_uid'] ?? 0;
}
/**
* 检查并升级服务点
* @param int $uid 用户UID
* @param array $order 订单信息
* @return void
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
public function checkAndUpgradeToServicePoint(int $uid, array $order): void
{
/** @var UserServices $userService */
$userService = app()->make(UserServices::class);
$userInfo = $userService->getUserInfo($uid);
// 已经是服务点则跳过
if ($userInfo['is_service_point'] == 1) {
return;
}
$isUpgrade = false;
$triggerType = '';
$recommendCount = 0;
$purchaseCount = 0;
$upgradeReason = '';
$servicePointUid = 0;
$parentPointUid = 0;
if($userInfo['spread_uid'] != 0){
// 条件1:直接推荐10名会员(推荐的下级中完成报单的人数)
$spreadInfo = $userService->getUserInfo($userInfo['spread_uid']);
$recommendCount = $this->getDirectRecommendReportCount($spreadInfo['uid']);
if ($recommendCount >= 10) {
// 获取父级服务点(当前用户的所属服务点)
$parentPointUid = $spreadInfo['service_point_uid'] ?? 0;
$isUpgrade = true;
$servicePointUid = $spreadInfo['uid'];
$triggerType = 'auto_recommend';
$upgradeReason = '直接推荐10名会员';
}
}
// 条件2:一次性购买10单会酒(商品ID=1的订单累计收货数量>=10)
if (!$isUpgrade) {
$purchaseCount = $this->getUserReportOrderCount($uid);
if ($purchaseCount >= 10) {
// 获取父级服务点(当前用户的所属服务点)
$parentPointUid = $userInfo['service_point_uid'] ?? 0;
$isUpgrade = true;
$servicePointUid = $uid;
$triggerType = 'auto_purchase';
$upgradeReason = '购买10单会酒';
}
}
if ($isUpgrade) {
// 升级为服务点
$updateData = [
'is_service_point' => 1,
'service_point_uid' => $servicePointUid,
'service_point_time' => time(),
'parent_service_point_uid' => $parentPointUid
];
$userService->update($uid, $updateData, 'uid');
// ========== 新增:添加升级记录 ==========
try {
/** @var UserUpgradeLogServices $upgradeLogService */
$upgradeLogService = app()->make(UserUpgradeLogServices::class);
$upgradeLogService->addUpgradeLog($uid, 'service_point', $triggerType, [
'recommend_count' => $recommendCount,
'purchase_count' => $purchaseCount,
'parent_service_point_uid' => $parentPointUid,
'remark' => $upgradeReason
]);
} catch (\Exception $e) {
Log::error('添加服务点升级记录失败:' . $e->getMessage());
}
// ========== 新增结束 ==========
// 记录升级日志
Log::info("用户{$uid}升级为服务点,原因:{$upgradeReason},父级服务点:{$parentPointUid}");
// 发送升级通知
event('CustomNoticeListener', [$uid, [
'uid' => $uid,
'reason' => $upgradeReason,
'time' => date('Y-m-d H:i:s')
], 'upgrade_service_point']);
}
}
/**
* 获取用户直接推荐的完成报单人数
* @param int $uid
* @return int
*/
protected function getDirectRecommendReportCount(int $uid): int
{
/** @var UserServices $userService */
$userService = app()->make(UserServices::class);
// 获取所有下级
$subUsers = $userService->getColumn(['spread_uid' => $uid], 'uid');
if (empty($subUsers)) {
return 0;
}
// 统计下级中完成报单订单的人数
/** @var StoreOrderServices $orderService */
$orderService = app()->make(StoreOrderServices::class);
$count = 0;
foreach ($subUsers as $subUid) {
// 查询该下级是否有已完成收货的报单订单
$hasReportOrder = $orderService->count([
'uid' => $subUid,
'paid' => 1,
'status' => 2,
'reward_status' => 1
]);
if ($hasReportOrder > 0) {
$count++;
}
}
return $count;
}
/**
* 获取用户报单产品累计收货数量
* @param int $uid
* @return int
*/
protected function getUserReportOrderCount(int $uid): int
{
/** @var StoreOrderServices $orderService */
$orderService = app()->make(StoreOrderServices::class);
// 获取用户所有已完成收货的订单
$orders = $orderService->getList([
'uid' => $uid,
'paid' => 1,
'status' => 2,
'reward_status' => 1
], ['id']);
if (empty($orders)) {
return 0;
}
$totalCount = 0;
$orderIds = array_column($orders, 'id');
/** @var StoreOrderCartInfoServices $cartService */
$cartService = app()->make(StoreOrderCartInfoServices::class);
foreach ($orderIds as $orderId) {
$cartList = $cartService->getCartColunm(['oid' => $orderId], 'cart_info', 'id');
foreach ($cartList as $cart) {
$cartData = is_string($cart) ? json_decode($cart, true) : $cart;
if (isset($cartData['product_id']) && $cartData['product_id'] == self::PRODUCT_REPORT_ID) {
$totalCount += $cartData['cart_num'] ?? 1;
}
}
}
return $totalCount;
}
/**
* 设置用户的所属服务点和服务中心(收货时调用)
* @param int $uid 消费者UID
* @param int $spreadUid 推荐人UID
* @return void
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
public function setUserServiceRelation(int $uid, int $spreadUid): void
{
if ($spreadUid <= 0) {
return;
}
/** @var UserServices $userService */
$userService = app()->make(UserServices::class);
$spreadUser = $userService->getUserInfo($spreadUid);
if (!$spreadUser) {
return;
}
$updateData = [];
// 设置所属服务点
if ($spreadUser['is_service_point'] == 1 && $spreadUser['service_point_uid'] == 0) {
$updateData['service_point_uid'] = $spreadUid;
} elseif ($spreadUser['service_point_uid'] > 0) {
$updateData['service_point_uid'] = $spreadUser['service_point_uid'];
}
// 设置所属服务中心
if ($spreadUser['is_service_center'] == 1 && $spreadUser['service_center_uid'] == 0) {
$updateData['service_center_uid'] = $spreadUid;
} elseif ($spreadUser['service_center_uid'] > 0) {
$updateData['service_center_uid'] = $spreadUser['service_center_uid'];
}
if (!empty($updateData)) {
$userService->update($uid, $updateData, 'uid');
}
}
}<?php
declare(strict_types=1);
namespace app\services\user;
use app\services\BaseServices;
use app\services\order\StoreOrderCartInfoServices;
use app\services\order\StoreOrderServices;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\facade\Log;
/**
* 会员与分销奖励服务
* Class UserRewardService
*/
class UserRewardService extends BaseServices
{
// 报单产品ID
const PRODUCT_REPORT_ID = 1;
// 奖励类型常量
const REWARD_TYPE_DIRECT_CASH = 'direct_cash'; // 直接分享现金奖励
const REWARD_TYPE_DIRECT_COUPON = 'direct_coupon'; // 直接分享消费券奖励
const REWARD_TYPE_SERVICE_CENTER_FEE = 'service_center_fee'; // 服务中心服务费
const REWARD_TYPE_SERVICE_POINT_FEE = 'service_point_fee'; // 服务点服务费(新增)
const REWARD_TYPE_SERVICE_POINT_PEER = 'service_point_peer'; // 服务点平级奖励
const REWARD_TYPE_REPURCHASE_DIRECT = 'repurchase_direct'; // 复购直接推荐人
const REWARD_TYPE_REPURCHASE_CENTER = 'repurchase_center'; // 复购服务中心
const REWARD_TYPE_REPURCHASE_POINT = 'repurchase_point'; // 复购服务点
/**
* 处理订单奖励(收货后调用)
* @param array $order 订单信息
* @param int $uid 收货用户UID
* @return bool
*/
public function handleOrderReward(array $order, int $uid): bool
{
// 检查是否已发放奖励
if ($order['reward_status'] == 1) {
return true;
}
// 获取订单商品信息
$cartInfo = $this->getOrderCartInfo($order['id']);
if (!$cartInfo) {
return true;
}
// 判断是否为报单产品(商品ID=1)
$isReportProduct = $this->checkIsReportProduct($cartInfo);
try {
$this->transaction(function () use ($order, $uid, $isReportProduct, $cartInfo) {
if ($isReportProduct) {
// 报单产品:发放直接分享奖励
$this->handleReportProductReward($order, $uid);
// 发放服务中心服务费(每笔订单100元)
$this->handleServiceCenterFee($order, $uid);
// ===== 新增:发放服务点服务费(每笔订单100元) =====
$this->handleServicePointFee($order, $uid);
// 发放服务点平级奖励(3%)
$this->handleServicePointPeerReward($order, $uid, $cartInfo);
} else {
// 复购产品:发放复购奖励
$this->handleRepurchaseReward($order, $uid, $cartInfo);
// 复购也发放服务中心服务费
$this->handleServiceCenterFee($order, $uid);
// 复购也发放服务点平级奖励
$this->handleServicePointPeerReward($order, $uid, $cartInfo);
}
// 标记订单奖励已发放
app()->make(StoreOrderServices::class)->update($order['id'], ['reward_status' => 1]);
});
return true;
} catch (\Exception $e) {
Log::error('订单奖励发放失败:订单ID-' . $order['id'] . ',错误:' . $e->getMessage());
return false;
}
}
/**
* 处理报单产品奖励
* @param array $order
* @param int $uid
* @return void
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
protected function handleReportProductReward(array $order, int $uid): void
{
// 获取上级推荐人
$spreadUid = $this->getSpreadUid($uid);
if (!$spreadUid) {
return;
}
/** @var UserServices $userService */
$userService = app()->make(UserServices::class);
$spreadUser = $userService->getUserInfo($spreadUid);
if (!$spreadUser) {
return;
}
// 奖励金额配置
$cashReward = 650; // 现金奖励650元
$couponReward = 650; // 消费券650积分
// 1. 发放现金奖励到推荐人的佣金账户
$currentBrokerage = $spreadUser['brokerage_price'];
$newBrokerage = bcadd((string)$currentBrokerage, (string)$cashReward, 2);
/** @var UserBrokerageServices $brokerageService */
$brokerageService = app()->make(UserBrokerageServices::class);
$brokerageService->income(
'direct_cash',
$spreadUid,
[
'nickname' => $userService->value($uid, 'nickname'),
'pay_price' => $order['pay_price'],
'number' => $cashReward,
'frozen_time' => time() + intval(sys_config('extract_time', 30)) * 86400
],
$newBrokerage,
$order['id']
);
// 更新用户佣金余额
$userService->update($spreadUid, ['brokerage_price' => $newBrokerage], 'uid');
// 2. 发放消费券(积分)到推荐人
$currentIntegral = $spreadUser['integral'];
$newIntegral = $currentIntegral + $couponReward;
/** @var UserBillServices $billService */
$billService = app()->make(UserBillServices::class);
$billService->income(
'direct_reward_coupon',
$spreadUid,
[
'nickname' => $userService->value($uid, 'nickname'),
'pay_price' => $order['pay_price'],
'number' => $couponReward,
],
$newIntegral,
$order['id']
);
// 更新用户积分
$userService->update($spreadUid, ['integral' => $newIntegral], 'uid');
$userInfo = $userService->getUserInfo($uid);
$userService->update($userInfo['uid'], ['first_order' => 1]);
// 发送消息通知
event('CustomNoticeListener', [$spreadUid, [
'uid' => $spreadUid,
'cash' => $cashReward,
'coupon' => $couponReward,
'time' => date('Y-m-d H:i:s')
], 'direct_reward']);
}
/**
* 处理服务中心服务费(每笔订单100元)
* @param array $order
* @param int $uid
* @return void
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
protected function handleServiceCenterFee(array $order, int $uid): void
{
/** @var UserServices $userService */
$userService = app()->make(UserServices::class);
// 获取消费者的所属服务中心
$userInfo = $userService->getUserInfo($uid);
if (!$userInfo || $userInfo['service_center_uid'] == 0) {
return;
}
$centerUid = $userInfo['service_center_uid'];
$centerUser = $userService->getUserInfo($centerUid);
if (!$centerUser || $centerUser['is_service_center'] != 1) {
return;
}
$feeAmount = 100; // 每笔订单100元服务费
$currentBrokerage = $centerUser['brokerage_price'];
$newBrokerage = bcadd((string)$currentBrokerage, (string)$feeAmount, 2);
/** @var UserBrokerageServices $brokerageService */
$brokerageService = app()->make(UserBrokerageServices::class);
$brokerageService->income(
'get_center_brokerage',
$centerUid,
[
'nickname' => $userInfo['nickname'],
'order_id' => $order['order_id'],
'number' => $feeAmount,
'frozen_time' => time() + intval(sys_config('extract_time', 30)) * 86400
],
$newBrokerage,
$order['id']
);
$userService->update($centerUid, ['brokerage_price' => $newBrokerage], 'uid');
}
// ===== 新增:处理服务点服务费(每笔订单100元) =====
/**
* 处理服务点服务费(每笔订单100元)
* @param array $order
* @param int $uid
* @return void
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
protected function handleServicePointFee(array $order, int $uid): void
{
/** @var UserServices $userService */
$userService = app()->make(UserServices::class);
// 获取消费者的所属服务点
$userInfo = $userService->getUserInfo($uid);
if (!$userInfo || $userInfo['service_point_uid'] == 0) {
return;
}
$pointUid = $userInfo['service_point_uid'];
$pointUser = $userService->getUserInfo($pointUid);
if (!$pointUser || $pointUser['is_service_point'] != 1) {
return;
}
$feeAmount = 100; // 每笔订单100元服务费
$currentBrokerage = $pointUser['brokerage_price'];
$newBrokerage = bcadd((string)$currentBrokerage, (string)$feeAmount, 2);
/** @var UserBrokerageServices $brokerageService */
$brokerageService = app()->make(UserBrokerageServices::class);
$brokerageService->income(
'get_point_brokerage', // 类型标识
$pointUid,
[
'nickname' => $userInfo['nickname'],
'order_id' => $order['order_id'],
'number' => $feeAmount,
'frozen_time' => time() + intval(sys_config('extract_time', 30)) * 86400
],
$newBrokerage,
$order['id']
);
$userService->update($pointUid, ['brokerage_price' => $newBrokerage], 'uid');
}
// ===== 新增结束 =====
/**
* 处理服务点平级奖励(3%+3%)
* @param array $order
* @param int $uid
* @param array $cartInfo
* @return void
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
protected function handleServicePointPeerReward(array $order, int $uid, array $cartInfo): void
{
/** @var UserServices $userService */
$userService = app()->make(UserServices::class);
// 获取消费者的所属服务点
$userInfo = $userService->getUserInfo($uid);
if (!$userInfo || $userInfo['service_point_uid'] == 0) {
return;
}
$pointUid = $userInfo['service_point_uid'];
$pointUser = $userService->getUserInfo($pointUid);
if (!$pointUser || $pointUser['is_service_point'] != 1) {
return;
}
// 检查是否存在父级服务点(平级条件)
$parentPointUid = $pointUser['parent_service_point_uid'];
if ($parentPointUid == 0) {
return; // 没有父级服务点,不发放平级奖励
}
$parentPointUser = $userService->getUserInfo($parentPointUid);
if (!$parentPointUser || $parentPointUser['is_service_point'] != 1) {
return;
}
// 计算奖励金额:订单金额的3%
$orderAmount = $order['pay_price'];
$rewardAmount = bcmul((string)$orderAmount, '0.03', 2);
if ($rewardAmount <= 0) {
return;
}
// 发放给所属服务点3%
$this->addBrokerageToUser($pointUid, (float)$rewardAmount, $order['id'], 'point_peer_self', [
'nickname' => $userInfo['nickname'],
'order_id' => $order['order_id'],
'number' => $rewardAmount,
'level' => 'self'
]);
// 发放给父级服务点3%
$this->addBrokerageToUser($parentPointUid, (float)$rewardAmount, $order['id'], 'point_peer_parent', [
'nickname' => $userInfo['nickname'],
'order_id' => $order['order_id'],
'number' => $rewardAmount,
'level' => 'parent'
]);
}
/**
* 处理复购奖励
* @param array $order
* @param int $uid
* @param array $cartInfo
* @return void
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
protected function handleRepurchaseReward(array $order, int $uid, array $cartInfo): void
{
$orderAmount = $order['pay_price'];
// 1. 直接推荐人获得30%
$directReward = bcmul((string)$orderAmount, '0.30', 2);
$spreadUid = $this->getSpreadUid($uid);
if ($spreadUid && $directReward > 0) {
$this->addBrokerageToUser($spreadUid, (float)$directReward, $order['id'], 'repurchase_direct', [
'nickname' => app()->make(UserServices::class)->value($uid, 'nickname'),
'order_id' => $order['order_id'],
'number' => $directReward
]);
}
// 2. 服务中心获得5%
/** @var UserServices $userService */
$userService = app()->make(UserServices::class);
$userInfo = $userService->getUserInfo($uid);
if ($userInfo && $userInfo['service_center_uid'] > 0) {
$centerReward = bcmul((string)$orderAmount, '0.05', 2);
if ($centerReward > 0) {
$this->addBrokerageToUser($userInfo['service_center_uid'], (float)$centerReward, $order['id'], 'repurchase_center', [
'nickname' => $userInfo['nickname'],
'order_id' => $order['order_id'],
'number' => $centerReward
]);
}
}
// 3. 服务点获得5%
if ($userInfo && $userInfo['service_point_uid'] > 0) {
$pointReward = bcmul((string)$orderAmount, '0.05', 2);
if ($pointReward > 0) {
$this->addBrokerageToUser($userInfo['service_point_uid'], (float)$pointReward, $order['id'], 'repurchase_point', [
'nickname' => $userInfo['nickname'],
'order_id' => $order['order_id'],
'number' => $pointReward
]);
}
}
}
/**
* 添加佣金到用户
* @param int $targetUid
* @param float $amount
* @param int $orderId
* @param string $type
* @param array $extra
* @return void
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
protected function addBrokerageToUser(int $targetUid, float $amount, int $orderId, string $type, array $extra = []): void
{
if ($amount <= 0 || $targetUid <= 0) {
return;
}
/** @var UserServices $userService */
$userService = app()->make(UserServices::class);
$targetUser = $userService->getUserInfo($targetUid);
if (!$targetUser) {
return;
}
$currentBrokerage = $targetUser['brokerage_price'];
$newBrokerage = bcadd((string)$currentBrokerage, (string)$amount, 2);
/** @var UserBrokerageServices $brokerageService */
$brokerageService = app()->make(UserBrokerageServices::class);
$titleMap = [
'point_peer_self' => '服务点平级奖励(本级)',
'point_peer_parent' => '服务点平级奖励(上级)',
'repurchase_direct' => '复购直接推荐奖励',
'repurchase_center' => '复购服务中心奖励',
'repurchase_point' => '复购服务点奖励',
'center_fee' => '服务中心服务费',
'point_fee' => '服务点服务费' // 新增
];
$brokerageService->income(
$type,
$targetUid,
[
'number' => $amount,
'frozen_time' => time() + intval(sys_config('extract_time', 30)) * 86400,
'title' => $titleMap[$type] ?? '佣金奖励',
'order_id' => $extra['order_id'] ?? '',
'nickname' => $extra['nickname'] ?? ''
],
$newBrokerage,
$orderId
);
$userService->update($targetUid, ['brokerage_price' => $newBrokerage], 'uid');
}
/**
* 检查订单是否为报单产品
* @param array $cartInfo
* @return bool
*/
protected function checkIsReportProduct(array $cartInfo): bool
{
foreach ($cartInfo as $cart) {
$cartData = is_string($cart['cart_info']) ? json_decode($cart['cart_info'], true) : $cart['cart_info'];
if (isset($cartData['product_id']) && $cartData['product_id'] == self::PRODUCT_REPORT_ID) {
return true;
}
}
return false;
}
/**
* 获取订单商品信息
* @param int $orderId
* @return array
*/
protected function getOrderCartInfo(int $orderId): array
{
/** @var StoreOrderCartInfoServices $cartService */
$cartService = app()->make(StoreOrderCartInfoServices::class);
return $cartService->getCartColunm(['oid' => $orderId], 'cart_info,unique', 'id');
}
/**
* 获取上级推荐人UID
* @param int $uid
* @return int
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
protected function getSpreadUid(int $uid): int
{
/** @var UserServices $userService */
$userService = app()->make(UserServices::class);
$userInfo = $userService->getUserInfo($uid);
return $userInfo['spread_uid'] ?? 0;
}
/**
* 检查并升级服务点
* @param int $uid 用户UID
* @param array $order 订单信息
* @return void
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
public function checkAndUpgradeToServicePoint(int $uid, array $order): void
{
/** @var UserServices $userService */
$userService = app()->make(UserServices::class);
$userInfo = $userService->getUserInfo($uid);
// 已经是服务点则跳过
if ($userInfo['is_service_point'] == 1) {
return;
}
$isUpgrade = false;
$triggerType = '';
$recommendCount = 0;
$purchaseCount = 0;
$upgradeReason = '';
$servicePointUid = 0;
$parentPointUid = 0;
if($userInfo['spread_uid'] != 0){
// 条件1:直接推荐10名会员(推荐的下级中完成报单的人数)
$spreadInfo = $userService->getUserInfo($userInfo['spread_uid']);
$recommendCount = $this->getDirectRecommendReportCount($spreadInfo['uid']);
if ($recommendCount >= 10) {
// 获取父级服务点(当前用户的所属服务点)
$parentPointUid = $spreadInfo['service_point_uid'] ?? 0;
$isUpgrade = true;
$servicePointUid = $spreadInfo['uid'];
$triggerType = 'auto_recommend';
$upgradeReason = '直接推荐10名会员';
}
}
// 条件2:一次性购买10单会酒(商品ID=1的订单累计收货数量>=10)
if (!$isUpgrade) {
$purchaseCount = $this->getUserReportOrderCount($uid);
if ($purchaseCount >= 10) {
// 获取父级服务点(当前用户的所属服务点)
$parentPointUid = $userInfo['service_point_uid'] ?? 0;
$isUpgrade = true;
$servicePointUid = $uid;
$triggerType = 'auto_purchase';
$upgradeReason = '购买10单会酒';
}
}
if ($isUpgrade) {
// 升级为服务点
$updateData = [
'is_service_point' => 1,
'service_point_uid' => $servicePointUid,
'service_point_time' => time(),
'parent_service_point_uid' => $parentPointUid
];
$userService->update($uid, $updateData, 'uid');
// ========== 新增:添加升级记录 ==========
try {
/** @var UserUpgradeLogServices $upgradeLogService */
$upgradeLogService = app()->make(UserUpgradeLogServices::class);
$upgradeLogService->addUpgradeLog($uid, 'service_point', $triggerType, [
'recommend_count' => $recommendCount,
'purchase_count' => $purchaseCount,
'parent_service_point_uid' => $parentPointUid,
'remark' => $upgradeReason
]);
} catch (\Exception $e) {
Log::error('添加服务点升级记录失败:' . $e->getMessage());
}
// ========== 新增结束 ==========
// 记录升级日志
Log::info("用户{$uid}升级为服务点,原因:{$upgradeReason},父级服务点:{$parentPointUid}");
// 发送升级通知
event('CustomNoticeListener', [$uid, [
'uid' => $uid,
'reason' => $upgradeReason,
'time' => date('Y-m-d H:i:s')
], 'upgrade_service_point']);
}
}
/**
* 获取用户直接推荐的完成报单人数
* @param int $uid
* @return int
*/
protected function getDirectRecommendReportCount(int $uid): int
{
/** @var UserServices $userService */
$userService = app()->make(UserServices::class);
// 获取所有下级
$subUsers = $userService->getColumn(['spread_uid' => $uid], 'uid');
if (empty($subUsers)) {
return 0;
}
// 统计下级中完成报单订单的人数
/** @var StoreOrderServices $orderService */
$orderService = app()->make(StoreOrderServices::class);
$count = 0;
foreach ($subUsers as $subUid) {
// 查询该下级是否有已完成收货的报单订单
$hasReportOrder = $orderService->count([
'uid' => $subUid,
'paid' => 1,
'status' => 2,
'reward_status' => 1
]);
if ($hasReportOrder > 0) {
$count++;
}
}
return $count;
}
/**
* 获取用户报单产品累计收货数量
* @param int $uid
* @return int
*/
protected function getUserReportOrderCount(int $uid): int
{
/** @var StoreOrderServices $orderService */
$orderService = app()->make(StoreOrderServices::class);
// 获取用户所有已完成收货的订单
$orders = $orderService->getList([
'uid' => $uid,
'paid' => 1,
'status' => 2,
'reward_status' => 1
], ['id']);
if (empty($orders)) {
return 0;
}
$totalCount = 0;
$orderIds = array_column($orders, 'id');
/** @var StoreOrderCartInfoServices $cartService */
$cartService = app()->make(StoreOrderCartInfoServices::class);
foreach ($orderIds as $orderId) {
$cartList = $cartService->getCartColunm(['oid' => $orderId], 'cart_info', 'id');
foreach ($cartList as $cart) {
$cartData = is_string($cart) ? json_decode($cart, true) : $cart;
if (isset($cartData['product_id']) && $cartData['product_id'] == self::PRODUCT_REPORT_ID) {
$totalCount += $cartData['cart_num'] ?? 1;
}
}
}
return $totalCount;
}
/**
* 设置用户的所属服务点和服务中心(收货时调用)
* @param int $uid 消费者UID
* @param int $spreadUid 推荐人UID
* @return void
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
public function setUserServiceRelation(int $uid, int $spreadUid): void
{
if ($spreadUid <= 0) {
return;
}
/** @var UserServices $userService */
$userService = app()->make(UserServices::class);
$spreadUser = $userService->getUserInfo($spreadUid);
if (!$spreadUser) {
return;
}
$updateData = [];
// 设置所属服务点
if ($spreadUser['is_service_point'] == 1 && $spreadUser['service_point_uid'] == 0) {
$updateData['service_point_uid'] = $spreadUid;
} elseif ($spreadUser['service_point_uid'] > 0) {
$updateData['service_point_uid'] = $spreadUser['service_point_uid'];
}
// 设置所属服务中心
if ($spreadUser['is_service_center'] == 1 && $spreadUser['service_center_uid'] == 0) {
$updateData['service_center_uid'] = $spreadUid;
} elseif ($spreadUser['service_center_uid'] > 0) {
$updateData['service_center_uid'] = $spreadUser['service_center_uid'];
}
if (!empty($updateData)) {
$userService->update($uid, $updateData, 'uid');
}
}
}<?php
declare(strict_types=1);
namespace app\services\user;
use app\services\BaseServices;
use app\services\order\StoreOrderCartInfoServices;
use app\services\order\StoreOrderServices;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\facade\Log;
/**
* 会员与分销奖励服务
* Class UserRewardService
*/
class UserRewardService extends BaseServices
{
// 报单产品ID
const PRODUCT_REPORT_ID = 1;
// 奖励类型常量
const REWARD_TYPE_DIRECT_CASH = 'direct_cash'; // 直接分享现金奖励
const REWARD_TYPE_DIRECT_COUPON = 'direct_coupon'; // 直接分享消费券奖励
const REWARD_TYPE_SERVICE_CENTER_FEE = 'service_center_fee'; // 服务中心服务费
const REWARD_TYPE_SERVICE_POINT_FEE = 'service_point_fee'; // 服务点服务费(新增)
const REWARD_TYPE_SERVICE_POINT_PEER = 'service_point_peer'; // 服务点平级奖励
const REWARD_TYPE_REPURCHASE_DIRECT = 'repurchase_direct'; // 复购直接推荐人
const REWARD_TYPE_REPURCHASE_CENTER = 'repurchase_center'; // 复购服务中心
const REWARD_TYPE_REPURCHASE_POINT = 'repurchase_point'; // 复购服务点
/**
* 处理订单奖励(收货后调用)
* @param array $order 订单信息
* @param int $uid 收货用户UID
* @return bool
*/
public function handleOrderReward(array $order, int $uid): bool
{
// 检查是否已发放奖励
if ($order['reward_status'] == 1) {
return true;
}
// 获取订单商品信息
$cartInfo = $this->getOrderCartInfo($order['id']);
if (!$cartInfo) {
return true;
}
// 判断是否为报单产品(商品ID=1)
$isReportProduct = $this->checkIsReportProduct($cartInfo);
try {
$this->transaction(function () use ($order, $uid, $isReportProduct, $cartInfo) {
if ($isReportProduct) {
// 报单产品:发放直接分享奖励
$this->handleReportProductReward($order, $uid);
// 发放服务中心服务费(每笔订单100元)
$this->handleServiceCenterFee($order, $uid);
// ===== 新增:发放服务点服务费(每笔订单100元) =====
$this->handleServicePointFee($order, $uid);
// 发放服务点平级奖励(3%)
$this->handleServicePointPeerReward($order, $uid, $cartInfo);
} else {
// 复购产品:发放复购奖励
$this->handleRepurchaseReward($order, $uid, $cartInfo);
// 复购也发放服务中心服务费
$this->handleServiceCenterFee($order, $uid);
// 复购也发放服务点平级奖励
$this->handleServicePointPeerReward($order, $uid, $cartInfo);
}
// 标记订单奖励已发放
app()->make(StoreOrderServices::class)->update($order['id'], ['reward_status' => 1]);
});
return true;
} catch (\Exception $e) {
Log::error('订单奖励发放失败:订单ID-' . $order['id'] . ',错误:' . $e->getMessage());
return false;
}
}
/**
* 处理报单产品奖励
* @param array $order
* @param int $uid
* @return void
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
protected function handleReportProductReward(array $order, int $uid): void
{
// 获取上级推荐人
$spreadUid = $this->getSpreadUid($uid);
if (!$spreadUid) {
return;
}
/** @var UserServices $userService */
$userService = app()->make(UserServices::class);
$spreadUser = $userService->getUserInfo($spreadUid);
if (!$spreadUser) {
return;
}
// 奖励金额配置
$cashReward = 650; // 现金奖励650元
$couponReward = 650; // 消费券650积分
// 1. 发放现金奖励到推荐人的佣金账户
$currentBrokerage = $spreadUser['brokerage_price'];
$newBrokerage = bcadd((string)$currentBrokerage, (string)$cashReward, 2);
/** @var UserBrokerageServices $brokerageService */
$brokerageService = app()->make(UserBrokerageServices::class);
$brokerageService->income(
'direct_cash',
$spreadUid,
[
'nickname' => $userService->value($uid, 'nickname'),
'pay_price' => $order['pay_price'],
'number' => $cashReward,
'frozen_time' => time() + intval(sys_config('extract_time', 30)) * 86400
],
$newBrokerage,
$order['id']
);
// 更新用户佣金余额
$userService->update($spreadUid, ['brokerage_price' => $newBrokerage], 'uid');
// 2. 发放消费券(积分)到推荐人
$currentIntegral = $spreadUser['integral'];
$newIntegral = $currentIntegral + $couponReward;
/** @var UserBillServices $billService */
$billService = app()->make(UserBillServices::class);
$billService->income(
'direct_reward_coupon',
$spreadUid,
[
'nickname' => $userService->value($uid, 'nickname'),
'pay_price' => $order['pay_price'],
'number' => $couponReward,
],
$newIntegral,
$order['id']
);
// 更新用户积分
$userService->update($spreadUid, ['integral' => $newIntegral], 'uid');
$userInfo = $userService->getUserInfo($uid);
$userService->update($userInfo['uid'], ['first_order' => 1]);
// 发送消息通知
event('CustomNoticeListener', [$spreadUid, [
'uid' => $spreadUid,
'cash' => $cashReward,
'coupon' => $couponReward,
'time' => date('Y-m-d H:i:s')
], 'direct_reward']);
}
/**
* 处理服务中心服务费(每笔订单100元)
* @param array $order
* @param int $uid
* @return void
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
protected function handleServiceCenterFee(array $order, int $uid): void
{
/** @var UserServices $userService */
$userService = app()->make(UserServices::class);
// 获取消费者的所属服务中心
$userInfo = $userService->getUserInfo($uid);
if (!$userInfo || $userInfo['service_center_uid'] == 0) {
return;
}
$centerUid = $userInfo['service_center_uid'];
$centerUser = $userService->getUserInfo($centerUid);
if (!$centerUser || $centerUser['is_service_center'] != 1) {
return;
}
$feeAmount = 100; // 每笔订单100元服务费
$currentBrokerage = $centerUser['brokerage_price'];
$newBrokerage = bcadd((string)$currentBrokerage, (string)$feeAmount, 2);
/** @var UserBrokerageServices $brokerageService */
$brokerageService = app()->make(UserBrokerageServices::class);
$brokerageService->income(
'get_center_brokerage',
$centerUid,
[
'nickname' => $userInfo['nickname'],
'order_id' => $order['order_id'],
'number' => $feeAmount,
'frozen_time' => time() + intval(sys_config('extract_time', 30)) * 86400
],
$newBrokerage,
$order['id']
);
$userService->update($centerUid, ['brokerage_price' => $newBrokerage], 'uid');
}
// ===== 新增:处理服务点服务费(每笔订单100元) =====
/**
* 处理服务点服务费(每笔订单100元)
* @param array $order
* @param int $uid
* @return void
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
protected function handleServicePointFee(array $order, int $uid): void
{
/** @var UserServices $userService */
$userService = app()->make(UserServices::class);
// 获取消费者的所属服务点
$userInfo = $userService->getUserInfo($uid);
if (!$userInfo || $userInfo['service_point_uid'] == 0) {
return;
}
$pointUid = $userInfo['service_point_uid'];
$pointUser = $userService->getUserInfo($pointUid);
if (!$pointUser || $pointUser['is_service_point'] != 1) {
return;
}
$feeAmount = 100; // 每笔订单100元服务费
$currentBrokerage = $pointUser['brokerage_price'];
$newBrokerage = bcadd((string)$currentBrokerage, (string)$feeAmount, 2);
/** @var UserBrokerageServices $brokerageService */
$brokerageService = app()->make(UserBrokerageServices::class);
$brokerageService->income(
'get_point_brokerage', // 类型标识
$pointUid,
[
'nickname' => $userInfo['nickname'],
'order_id' => $order['order_id'],
'number' => $feeAmount,
'frozen_time' => time() + intval(sys_config('extract_time', 30)) * 86400
],
$newBrokerage,
$order['id']
);
$userService->update($pointUid, ['brokerage_price' => $newBrokerage], 'uid');
}
// ===== 新增结束 =====
/**
* 处理服务点平级奖励(3%+3%)
* @param array $order
* @param int $uid
* @param array $cartInfo
* @return void
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
protected function handleServicePointPeerReward(array $order, int $uid, array $cartInfo): void
{
/** @var UserServices $userService */
$userService = app()->make(UserServices::class);
// 获取消费者的所属服务点
$userInfo = $userService->getUserInfo($uid);
if (!$userInfo || $userInfo['service_point_uid'] == 0) {
return;
}
$pointUid = $userInfo['service_point_uid'];
$pointUser = $userService->getUserInfo($pointUid);
if (!$pointUser || $pointUser['is_service_point'] != 1) {
return;
}
// 检查是否存在父级服务点(平级条件)
$parentPointUid = $pointUser['parent_service_point_uid'];
if ($parentPointUid == 0) {
return; // 没有父级服务点,不发放平级奖励
}
$parentPointUser = $userService->getUserInfo($parentPointUid);
if (!$parentPointUser || $parentPointUser['is_service_point'] != 1) {
return;
}
// 计算奖励金额:订单金额的3%
$orderAmount = $order['pay_price'];
$rewardAmount = bcmul((string)$orderAmount, '0.03', 2);
if ($rewardAmount <= 0) {
return;
}
// 发放给所属服务点3%
$this->addBrokerageToUser($pointUid, (float)$rewardAmount, $order['id'], 'point_peer_self', [
'nickname' => $userInfo['nickname'],
'order_id' => $order['order_id'],
'number' => $rewardAmount,
'level' => 'self'
]);
// 发放给父级服务点3%
$this->addBrokerageToUser($parentPointUid, (float)$rewardAmount, $order['id'], 'point_peer_parent', [
'nickname' => $userInfo['nickname'],
'order_id' => $order['order_id'],
'number' => $rewardAmount,
'level' => 'parent'
]);
}
/**
* 处理复购奖励
* @param array $order
* @param int $uid
* @param array $cartInfo
* @return void
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
protected function handleRepurchaseReward(array $order, int $uid, array $cartInfo): void
{
$orderAmount = $order['pay_price'];
// 1. 直接推荐人获得30%
$directReward = bcmul((string)$orderAmount, '0.30', 2);
$spreadUid = $this->getSpreadUid($uid);
if ($spreadUid && $directReward > 0) {
$this->addBrokerageToUser($spreadUid, (float)$directReward, $order['id'], 'repurchase_direct', [
'nickname' => app()->make(UserServices::class)->value($uid, 'nickname'),
'order_id' => $order['order_id'],
'number' => $directReward
]);
}
// 2. 服务中心获得5%
/** @var UserServices $userService */
$userService = app()->make(UserServices::class);
$userInfo = $userService->getUserInfo($uid);
if ($userInfo && $userInfo['service_center_uid'] > 0) {
$centerReward = bcmul((string)$orderAmount, '0.05', 2);
if ($centerReward > 0) {
$this->addBrokerageToUser($userInfo['service_center_uid'], (float)$centerReward, $order['id'], 'repurchase_center', [
'nickname' => $userInfo['nickname'],
'order_id' => $order['order_id'],
'number' => $centerReward
]);
}
}
// 3. 服务点获得5%
if ($userInfo && $userInfo['service_point_uid'] > 0) {
$pointReward = bcmul((string)$orderAmount, '0.05', 2);
if ($pointReward > 0) {
$this->addBrokerageToUser($userInfo['service_point_uid'], (float)$pointReward, $order['id'], 'repurchase_point', [
'nickname' => $userInfo['nickname'],
'order_id' => $order['order_id'],
'number' => $pointReward
]);
}
}
}
/**
* 添加佣金到用户
* @param int $targetUid
* @param float $amount
* @param int $orderId
* @param string $type
* @param array $extra
* @return void
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
protected function addBrokerageToUser(int $targetUid, float $amount, int $orderId, string $type, array $extra = []): void
{
if ($amount <= 0 || $targetUid <= 0) {
return;
}
/** @var UserServices $userService */
$userService = app()->make(UserServices::class);
$targetUser = $userService->getUserInfo($targetUid);
if (!$targetUser) {
return;
}
$currentBrokerage = $targetUser['brokerage_price'];
$newBrokerage = bcadd((string)$currentBrokerage, (string)$amount, 2);
/** @var UserBrokerageServices $brokerageService */
$brokerageService = app()->make(UserBrokerageServices::class);
$titleMap = [
'point_peer_self' => '服务点平级奖励(本级)',
'point_peer_parent' => '服务点平级奖励(上级)',
'repurchase_direct' => '复购直接推荐奖励',
'repurchase_center' => '复购服务中心奖励',
'repurchase_point' => '复购服务点奖励',
'center_fee' => '服务中心服务费',
'point_fee' => '服务点服务费' // 新增
];
$brokerageService->income(
$type,
$targetUid,
[
'number' => $amount,
'frozen_time' => time() + intval(sys_config('extract_time', 30)) * 86400,
'title' => $titleMap[$type] ?? '佣金奖励',
'order_id' => $extra['order_id'] ?? '',
'nickname' => $extra['nickname'] ?? ''
],
$newBrokerage,
$orderId
);
$userService->update($targetUid, ['brokerage_price' => $newBrokerage], 'uid');
}
/**
* 检查订单是否为报单产品
* @param array $cartInfo
* @return bool
*/
protected function checkIsReportProduct(array $cartInfo): bool
{
foreach ($cartInfo as $cart) {
$cartData = is_string($cart['cart_info']) ? json_decode($cart['cart_info'], true) : $cart['cart_info'];
if (isset($cartData['product_id']) && $cartData['product_id'] == self::PRODUCT_REPORT_ID) {
return true;
}
}
return false;
}
/**
* 获取订单商品信息
* @param int $orderId
* @return array
*/
protected function getOrderCartInfo(int $orderId): array
{
/** @var StoreOrderCartInfoServices $cartService */
$cartService = app()->make(StoreOrderCartInfoServices::class);
return $cartService->getCartColunm(['oid' => $orderId], 'cart_info,unique', 'id');
}
/**
* 获取上级推荐人UID
* @param int $uid
* @return int
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
protected function getSpreadUid(int $uid): int
{
/** @var UserServices $userService */
$userService = app()->make(UserServices::class);
$userInfo = $userService->getUserInfo($uid);
return $userInfo['spread_uid'] ?? 0;
}
/**
* 检查并升级服务点
* @param int $uid 用户UID
* @param array $order 订单信息
* @return void
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
public function checkAndUpgradeToServicePoint(int $uid, array $order): void
{
/** @var UserServices $userService */
$userService = app()->make(UserServices::class);
$userInfo = $userService->getUserInfo($uid);
// 已经是服务点则跳过
if ($userInfo['is_service_point'] == 1) {
return;
}
$isUpgrade = false;
$triggerType = '';
$recommendCount = 0;
$purchaseCount = 0;
$upgradeReason = '';
$servicePointUid = 0;
$parentPointUid = 0;
if($userInfo['spread_uid'] != 0){
// 条件1:直接推荐10名会员(推荐的下级中完成报单的人数)
$spreadInfo = $userService->getUserInfo($userInfo['spread_uid']);
$recommendCount = $this->getDirectRecommendReportCount($spreadInfo['uid']);
if ($recommendCount >= 10) {
// 获取父级服务点(当前用户的所属服务点)
$parentPointUid = $spreadInfo['service_point_uid'] ?? 0;
$isUpgrade = true;
$servicePointUid = $spreadInfo['uid'];
$triggerType = 'auto_recommend';
$upgradeReason = '直接推荐10名会员';
}
}
// 条件2:一次性购买10单会酒(商品ID=1的订单累计收货数量>=10)
if (!$isUpgrade) {
$purchaseCount = $this->getUserReportOrderCount($uid);
if ($purchaseCount >= 10) {
// 获取父级服务点(当前用户的所属服务点)
$parentPointUid = $userInfo['service_point_uid'] ?? 0;
$isUpgrade = true;
$servicePointUid = $uid;
$triggerType = 'auto_purchase';
$upgradeReason = '购买10单会酒';
}
}
if ($isUpgrade) {
// 升级为服务点
$updateData = [
'is_service_point' => 1,
'service_point_uid' => $servicePointUid,
'service_point_time' => time(),
'parent_service_point_uid' => $parentPointUid
];
$userService->update($uid, $updateData, 'uid');
// ========== 新增:添加升级记录 ==========
try {
/** @var UserUpgradeLogServices $upgradeLogService */
$upgradeLogService = app()->make(UserUpgradeLogServices::class);
$upgradeLogService->addUpgradeLog($uid, 'service_point', $triggerType, [
'recommend_count' => $recommendCount,
'purchase_count' => $purchaseCount,
'parent_service_point_uid' => $parentPointUid,
'remark' => $upgradeReason
]);
} catch (\Exception $e) {
Log::error('添加服务点升级记录失败:' . $e->getMessage());
}
// ========== 新增结束 ==========
// 记录升级日志
Log::info("用户{$uid}升级为服务点,原因:{$upgradeReason},父级服务点:{$parentPointUid}");
// 发送升级通知
event('CustomNoticeListener', [$uid, [
'uid' => $uid,
'reason' => $upgradeReason,
'time' => date('Y-m-d H:i:s')
], 'upgrade_service_point']);
}
}
/**
* 获取用户直接推荐的完成报单人数
* @param int $uid
* @return int
*/
protected function getDirectRecommendReportCount(int $uid): int
{
/** @var UserServices $userService */
$userService = app()->make(UserServices::class);
// 获取所有下级
$subUsers = $userService->getColumn(['spread_uid' => $uid], 'uid');
if (empty($subUsers)) {
return 0;
}
// 统计下级中完成报单订单的人数
/** @var StoreOrderServices $orderService */
$orderService = app()->make(StoreOrderServices::class);
$count = 0;
foreach ($subUsers as $subUid) {
// 查询该下级是否有已完成收货的报单订单
$hasReportOrder = $orderService->count([
'uid' => $subUid,
'paid' => 1,
'status' => 2,
'reward_status' => 1
]);
if ($hasReportOrder > 0) {
$count++;
}
}
return $count;
}
/**
* 获取用户报单产品累计收货数量
* @param int $uid
* @return int
*/
protected function getUserReportOrderCount(int $uid): int
{
/** @var StoreOrderServices $orderService */
$orderService = app()->make(StoreOrderServices::class);
// 获取用户所有已完成收货的订单
$orders = $orderService->getList([
'uid' => $uid,
'paid' => 1,
'status' => 2,
'reward_status' => 1
], ['id']);
if (empty($orders)) {
return 0;
}
$totalCount = 0;
$orderIds = array_column($orders, 'id');
/** @var StoreOrderCartInfoServices $cartService */
$cartService = app()->make(StoreOrderCartInfoServices::class);
foreach ($orderIds as $orderId) {
$cartList = $cartService->getCartColunm(['oid' => $orderId], 'cart_info', 'id');
foreach ($cartList as $cart) {
$cartData = is_string($cart) ? json_decode($cart, true) : $cart;
if (isset($cartData['product_id']) && $cartData['product_id'] == self::PRODUCT_REPORT_ID) {
$totalCount += $cartData['cart_num'] ?? 1;
}
}
}
return $totalCount;
}
/**
* 设置用户的所属服务点和服务中心(收货时调用)
* @param int $uid 消费者UID
* @param int $spreadUid 推荐人UID
* @return void
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
public function setUserServiceRelation(int $uid, int $spreadUid): void
{
if ($spreadUid <= 0) {
return;
}
/** @var UserServices $userService */
$userService = app()->make(UserServices::class);
$spreadUser = $userService->getUserInfo($spreadUid);
if (!$spreadUser) {
return;
}
$updateData = [];
// 设置所属服务点
if ($spreadUser['is_service_point'] == 1 && $spreadUser['service_point_uid'] == 0) {
$updateData['service_point_uid'] = $spreadUid;
} elseif ($spreadUser['service_point_uid'] > 0) {
$updateData['service_point_uid'] = $spreadUser['service_point_uid'];
}
// 设置所属服务中心
if ($spreadUser['is_service_center'] == 1 && $spreadUser['service_center_uid'] == 0) {
$updateData['service_center_uid'] = $spreadUid;
} elseif ($spreadUser['service_center_uid'] > 0) {
$updateData['service_center_uid'] = $spreadUser['service_center_uid'];
}
if (!empty($updateData)) {
$userService->update($uid, $updateData, 'uid');
}
}
} 评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果