| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309 |
- <?php
- namespace App\Module\Promotion\Logics;
- use App\Module\Promotion\Enums\REFERRAL_CODE_STATUS;
- use App\Module\Promotion\Models\PromotionReferralCode;
- use App\Module\Promotion\Models\PromotionReferralCodeUsage;
- use Illuminate\Support\Facades\Log;
- use Illuminate\Support\Str;
- /**
- * 推荐码逻辑类
- *
- * 处理推荐码的核心业务逻辑,包括生成推荐码、验证推荐码、
- * 使用推荐码等功能。该类仅供内部使用,不对外提供服务。
- */
- class ReferralCodeLogic
- {
- /**
- * @var ReferralLogic
- */
- protected $referralLogic;
- /**
- * 构造函数
- *
- * @param ReferralLogic $referralLogic
- */
- public function __construct(ReferralLogic $referralLogic)
- {
- $this->referralLogic = $referralLogic;
- }
- /**
- * 生成推荐码
- *
- * @param int $userId 用户ID
- * @param \DateTime|null $expireTime 过期时间
- * @return string|null
- */
- public function generateReferralCode(int $userId, ?\DateTime $expireTime = null): ?string
- {
- try {
- // 检查用户是否已有有效的推荐码
- $existingCode = $this->getUserActiveCode($userId);
- if ($existingCode) {
- return $existingCode->code;
- }
- // 生成唯一的推荐码
- $code = $this->generateUniqueCode();
- // 创建推荐码记录
- $referralCode = new PromotionReferralCode();
- $referralCode->user_id = $userId;
- $referralCode->code = $code;
- $referralCode->usage_count = 0;
- $referralCode->status = REFERRAL_CODE_STATUS::ACTIVE;
- $referralCode->expire_time = $expireTime;
- if ($referralCode->save()) {
- return $code;
- }
- return null;
- } catch (\Exception $e) {
- Log::error("生成推荐码失败: " . $e->getMessage());
- return null;
- }
- }
- /**
- * 生成唯一的推荐码
- *
- * @param int $length 推荐码长度
- * @return string
- */
- private function generateUniqueCode(int $length = 8): string
- {
- $attempts = 0;
- $maxAttempts = 10;
- do {
- // 生成随机字符串
- $code = strtoupper(Str::random($length));
- // 检查是否已存在
- $exists = PromotionReferralCode::where('code', $code)->exists();
- $attempts++;
- } while ($exists && $attempts < $maxAttempts);
- // 如果多次尝试后仍然存在冲突,添加时间戳确保唯一性
- if ($exists) {
- $code = strtoupper(substr(Str::random($length - 4), 0, $length - 4) . substr(time(), -4));
- }
- return $code;
- }
- /**
- * 获取用户的有效推荐码
- *
- * @param int $userId 用户ID
- * @return PromotionReferralCode|null
- */
- public function getUserActiveCode(int $userId): ?PromotionReferralCode
- {
- $code = PromotionReferralCode::where('user_id', $userId)
- ->where('status', REFERRAL_CODE_STATUS::ACTIVE)
- ->where(function ($query) {
- $query->whereNull('expire_time')
- ->orWhere('expire_time', '>', now());
- })
- ->first();
- return $code;
- }
- /**
- * 验证推荐码
- *
- * @param string $code 推荐码
- * @return array 包含验证结果和推荐码信息
- */
- public function validateReferralCode(string $code): array
- {
- try {
- // 查找推荐码
- $referralCode = PromotionReferralCode::where('code', $code)->first();
- if (!$referralCode) {
- return [
- 'valid' => false,
- 'message' => '推荐码不存在',
- 'code' => null
- ];
- }
- // 检查状态
- if ($referralCode->status != REFERRAL_CODE_STATUS::ACTIVE) {
- return [
- 'valid' => false,
- 'message' => '推荐码已禁用',
- 'code' => $referralCode
- ];
- }
- // 检查过期时间
- if ($referralCode->expire_time && $referralCode->expire_time->isPast()) {
- return [
- 'valid' => false,
- 'message' => '推荐码已过期',
- 'code' => $referralCode
- ];
- }
- return [
- 'valid' => true,
- 'message' => '推荐码有效',
- 'code' => $referralCode
- ];
- } catch (\Exception $e) {
- Log::error("验证推荐码失败: " . $e->getMessage());
- return [
- 'valid' => false,
- 'message' => '验证推荐码时发生错误',
- 'code' => null
- ];
- }
- }
- /**
- * 使用推荐码
- *
- * @param string $code 推荐码
- * @param int $userId 使用者ID
- * @param string $ipAddress IP地址
- * @param string $userAgent 用户代理
- * @return array 包含使用结果和信息
- */
- public function useReferralCode(string $code, int $userId, string $ipAddress, string $userAgent): array
- {
- try {
- // 验证推荐码
- $validation = $this->validateReferralCode($code);
- if (!$validation['valid']) {
- return [
- 'success' => false,
- 'message' => $validation['message']
- ];
- }
- $referralCode = $validation['code'];
- // 检查用户是否使用自己的推荐码
- if ($referralCode->user_id == $userId) {
- return [
- 'success' => false,
- 'message' => '不能使用自己的推荐码'
- ];
- }
- // 检查用户是否已有推荐人
- if ($this->referralLogic->hasReferrer($userId)) {
- return [
- 'success' => false,
- 'message' => '用户已有推荐人,不能使用推荐码'
- ];
- }
- // 检查是否形成循环推荐
- if ($this->referralLogic->checkCircularReferral($userId, $referralCode->user_id)) {
- return [
- 'success' => false,
- 'message' => '使用此推荐码会形成循环推荐关系'
- ];
- }
- // 检查事务是否已开启
- \UCore\Db\Helper::check_tr();
- // 记录使用记录
- $usage = new PromotionReferralCodeUsage();
- $usage->code = $code;
- $usage->code_owner_id = $referralCode->user_id;
- $usage->user_id = $userId;
- $usage->ip_address = $ipAddress;
- $usage->user_agent = $userAgent;
- $usage->status = PromotionReferralCodeUsage::STATUS_SUCCESS;
- $usage->result = '成功使用推荐码';
- $usage->save();
- // 更新推荐码使用次数
- $referralCode->usage_count += 1;
- $referralCode->save();
- // 建立推荐关系
- $result = $this->referralLogic->createReferralRelation($userId, $referralCode->user_id);
- if (!$result) {
- // 如果建立推荐关系失败,更新使用记录状态
- $usage->status = PromotionReferralCodeUsage::STATUS_FAILED;
- $usage->result = '建立推荐关系失败';
- $usage->save();
- return [
- 'success' => false,
- 'message' => '建立推荐关系失败'
- ];
- }
- return [
- 'success' => true,
- 'message' => '成功使用推荐码并建立推荐关系',
- 'referrer_id' => $referralCode->user_id
- ];
- } catch (\Exception $e) {
- Log::error("使用推荐码失败: " . $e->getMessage());
- return [
- 'success' => false,
- 'message' => '使用推荐码时发生错误'
- ];
- }
- }
- /**
- * 禁用推荐码
- *
- * @param string $code 推荐码
- * @return bool
- */
- public function disableReferralCode(string $code): bool
- {
- try {
- $referralCode = PromotionReferralCode::where('code', $code)->first();
- if (!$referralCode) {
- return false;
- }
- $referralCode->status = REFERRAL_CODE_STATUS::DISABLED;
- return $referralCode->save();
- } catch (\Exception $e) {
- Log::error("禁用推荐码失败: " . $e->getMessage());
- return false;
- }
- }
- /**
- * 清理过期的推荐码
- *
- * @return int 清理的数量
- */
- public function cleanExpiredReferralCodes(): int
- {
- try {
- return PromotionReferralCode::where('status', REFERRAL_CODE_STATUS::ACTIVE)
- ->whereNotNull('expire_time')
- ->where('expire_time', '<', now())
- ->update(['status' => REFERRAL_CODE_STATUS::DISABLED]);
- } catch (\Exception $e) {
- Log::error("清理过期推荐码失败: " . $e->getMessage());
- return 0;
- }
- }
- }
|