Parcourir la source

后台URS用户推荐关系列表增加农场用户信息列

- 修改UrsUserReferral模型,添加与农场用户的关联关系
- 修改UrsUserReferralRepository,添加JOIN查询获取农场用户信息
- 修改UrsUserReferralController,在列表页面增加农场用户名和昵称列
- 在详情页面增加农场用户信息展示,使用分隔符分组
- 在筛选功能中增加农场用户信息的筛选条件
- 对未进入农场的用户显示友好提示信息
notfff il y a 6 mois
Parent
commit
c9530b95

+ 204 - 0
AiWork/202506/152000-修复URS login4u认证凭证获取bug.md

@@ -0,0 +1,204 @@
+# 修复URS login4u认证凭证获取bug
+
+**任务时间**: 2025年06月15日 20:00-20:15  
+**任务类型**: Bug修复  
+**模块**: ThirdParty、AppGame、URS  
+
+## 问题描述
+
+用户反馈URS login4u功能存在认证凭证获取问题,系统提示"服务 urs 没有可用的认证凭证",但实际数据库中存在有效的认证凭证。
+
+## 问题分析
+
+通过日志分析发现以下问题:
+
+1. **环境匹配问题**:系统默认查找 `production` 环境的认证凭证,但数据库中只有 `testing` 环境的凭证
+2. **凭证获取逻辑错误**:URS请求类从 `service.config` 获取凭证,但应该从 `credential` 获取
+3. **数据库字段限制**:`thirdparty_logs` 表的 `method` 字段长度不够存储 `PACKAGE_CALL`
+4. **模型配置缺失**:`ThirdPartyCredential` 模型缺少 `$fillable` 属性定义
+5. **命名空间错误**:`System\Services\User` 类命名空间不匹配
+6. **方法签名不兼容**:URS请求类的 `handler` 方法签名与基类不兼容
+7. **Protobuf方法名错误**:使用了不存在的 `setLoginTime()` 方法
+
+## 修复方案
+
+### 1. 智能凭证获取机制
+
+修改 `BaseRequest::getSmartCredential()` 方法,实现智能环境匹配:
+
+```php
+protected function getSmartCredential(): ?ThirdPartyCredential
+{
+    $appEnv = app()->environment();
+    
+    // 环境映射:将Laravel环境映射到凭证环境
+    $envMapping = [
+        'local' => 'testing',
+        'development' => 'testing', 
+        'testing' => 'testing',
+        'staging' => 'staging',
+        'production' => 'production',
+    ];
+    
+    $preferredEnv = $envMapping[$appEnv] ?? 'production';
+    
+    // 按优先级尝试获取凭证
+    $environments = [$preferredEnv, 'testing', 'production'];
+    $environments = array_unique($environments);
+    
+    foreach ($environments as $env) {
+        $credential = $this->service->getActiveCredential($env);
+        if ($credential) {
+            return $credential;
+        }
+    }
+    
+    // 如果以上都没找到,尝试获取任何可用的激活凭证
+    return $this->service->credentials()
+        ->where('is_active', true)
+        ->where(function ($query) {
+            $query->whereNull('expires_at')
+                ->orWhere('expires_at', '>', now());
+        })
+        ->first();
+}
+```
+
+### 2. 修复URS凭证获取逻辑
+
+修改 `URS\Request\BaseRequest::getUrsCredential()` 方法:
+
+```php
+protected function getUrsCredential(): \ThirdParty\Urs\Dto\Credential
+{
+    // 从认证凭证中获取凭证信息,而不是从服务配置
+    $credentials = $this->getCredential()->getDecryptedCredentials();
+    return \ThirdParty\Urs\Dto\Credential::fromArray($credentials);
+}
+```
+
+### 3. 数据库结构修复
+
+```sql
+ALTER TABLE kku_thirdparty_logs MODIFY COLUMN method VARCHAR(20) NOT NULL;
+```
+
+### 4. 模型配置完善
+
+为 `ThirdPartyCredential` 模型添加 `$fillable` 属性:
+
+```php
+// attrlist start 
+protected $fillable = [
+    'service_id',
+    'name',
+    'type',
+    'credentials',
+    'environment',
+    'is_active',
+    'expires_at',
+    'last_used_at',
+    'usage_count',
+];
+// attrlist end
+```
+
+### 5. 修复配额服务调用
+
+修正 `BaseRequest` 中的配额检查方法:
+
+```php
+protected function checkQuota(): bool
+{
+    return QuotaService::canUse($this->service->id);
+}
+
+protected function updateQuota(): void
+{
+    QuotaService::use($this->service->id);
+}
+```
+
+### 6. 修复命名空间和方法签名
+
+- 修正 `System\Services\User` 类命名空间
+- 统一URS请求类的 `handler` 方法签名
+- 修正Protobuf方法名称
+
+## 测试结果
+
+使用测试命令验证修复效果:
+
+```bash
+php artisan test:login4u '$2y$10$i.h97m13olfIaU.ZTYiyeeXFl8xqn48w2bFiAhcoQsJdU6K3w.Lgu'
+```
+
+**测试结果**:
+```
+=== 测试URS Login4u功能 ===
+1. 检查Handler类...
+✓ Login4uHandler类存在
+2. 检查Protobuf类...
+✓ RequestPublicLogin4u类存在
+✓ ResponsePublicLogin4u类存在
+3. 检查URS服务...
+✓ UrsService类存在
+4. 检查UrsUserMappingService...
+✓ UrsUserMappingService类存在
+5. 创建测试请求...
+✓ 测试请求创建成功,keylogin: $2y$10$i.h97m13olfIaU.ZTYiyeeXFl8xqn48w2bFiAhcoQsJdU6K3w.Lgu
+6. 测试Handler处理...
+开始处理登录请求...
+7. 检查响应结果...
+✓ 登录成功!
+Token: 76fd26e5eb718a9d0c504fbf5c0bdb3a
+IsProhibit: false
+最后登录时间: 2025-06-15 20:12:35
+=== 测试完成 ===
+```
+
+## 功能验证
+
+### 1. URS API调用成功
+- ✅ 成功获取URS用户信息(用户ID: 10096)
+- ✅ 认证凭证正确获取和使用
+- ✅ 凭证使用统计正常更新
+
+### 2. 用户创建和映射
+- ✅ 自动创建农场用户(用户ID: 38902,用户名: urs-10096)
+- ✅ 建立URS用户ID和农场用户ID的映射关系
+- ✅ 用户信息正确初始化
+
+### 3. 登录流程完整
+- ✅ 生成有效的session token
+- ✅ 触发登录成功事件
+- ✅ 更新用户登录时间和活动时间
+- ✅ 返回正确的Protobuf响应
+
+### 4. 推荐关系同步
+- ✅ 查询用户推荐关系映射
+- ✅ 推荐关系同步逻辑正常(虽然当前测试用户无上级关系)
+
+## 涉及文件
+
+1. **app/Module/ThirdParty/Services/BaseRequest.php** - 智能凭证获取机制
+2. **app/Module/ThirdParty/Models/ThirdPartyCredential.php** - 添加fillable属性
+3. **ThirdParty/Urs/Request/BaseRequest.php** - 修复凭证获取逻辑
+4. **ThirdParty/Urs/Request/UrsGetUserInfoRequest.php** - 修复配置获取和方法签名
+5. **ThirdParty/Urs/Request/UrsGetUserTeamRequest.php** - 修复方法签名
+6. **ThirdParty/Urs/Request/UrsGetUserLevelCountRequest.php** - 修复方法签名
+7. **app/Module/System/Services/User.php** - 修复命名空间
+8. **app/Module/User/Services/UserService.php** - 更新类引用
+9. **app/Module/AppGame/Handler/Public/Login4uHandler.php** - 修复Protobuf方法名
+10. **app/Module/AppGame/Commands/TestLogin4uCommand.php** - 修复测试命令
+
+## 总结
+
+本次修复解决了URS login4u功能的核心认证问题,实现了:
+
+1. **智能环境匹配**:系统能够根据当前环境自动选择合适的认证凭证
+2. **完整登录流程**:从URS用户验证到农场用户创建、登录状态设置的完整流程
+3. **健壮的错误处理**:完善的异常处理和日志记录机制
+4. **兼容性改进**:修复了多个模块间的兼容性问题
+
+修复后的系统能够稳定处理URS login4u登录请求,为用户提供无缝的登录体验。

+ 3 - 3
app/Module/AppGame/Commands/TestLogin4uCommand.php

@@ -37,7 +37,7 @@ class TestLogin4uCommand extends Command
 
         // 获取测试用的keylogin
         $keylogin = $this->argument('keylogin') ?: $this->ask('请输入URS登录密钥(keylogin)');
-        
+
         if (empty($keylogin)) {
             $this->error('登录密钥不能为空');
             return Command::FAILURE;
@@ -92,7 +92,7 @@ class TestLogin4uCommand extends Command
             $this->info('6. 测试Handler处理...');
             $response = new Response();
             $handler = new Login4uHandler($response);
-            
+
             $this->line('开始处理登录请求...');
             $result = $handler->handle($request);
 
@@ -102,7 +102,7 @@ class TestLogin4uCommand extends Command
                 $this->error('响应类型错误,期望ResponsePublicLogin4u');
                 return Command::FAILURE;
             }
-
+            dump($result->serializeToJsonString());
             $token = $result->getToken();
             $isProhibit = $result->getIsProhibit();
 

+ 43 - 0
app/Module/UrsPromotion/AdminControllers/UrsUserReferralController.php

@@ -43,6 +43,25 @@ class UrsUserReferralController extends AdminController
             $grid->column('id', 'ID')->sortable();
             $grid->column('urs_user_id', 'URS用户ID')->sortable();
             $grid->column('urs_referrer_id', 'URS推荐人ID')->sortable();
+
+            // 农场用户信息列
+            $grid->column('farm_username', '农场用户名')->display(function ($value) {
+                return $value ?: '<span class="label label-warning">未进入农场</span>';
+            });
+
+            $grid->column('farm_nickname', '农场用户昵称')->display(function ($value) {
+                return $value ?: '<span class="text-muted">无昵称</span>';
+            });
+
+            // 推荐人农场用户信息列
+            $grid->column('referrer_farm_username', '推荐人农场用户名')->display(function ($value) {
+                return $value ?: '<span class="label label-warning">未进入农场</span>';
+            });
+
+            $grid->column('referrer_farm_nickname', '推荐人农场昵称')->display(function ($value) {
+                return $value ?: '<span class="text-muted">无昵称</span>';
+            });
+
             $grid->column('referral_time', '推荐时间')->sortable();
             $grid->column('status', '状态')->using([
                 UrsUserReferral::STATUS_INVALID => '无效',
@@ -68,6 +87,10 @@ class UrsUserReferralController extends AdminController
             $grid->filter(function (Grid\Filter $filter) {
                 $filter->equal('urs_user_id', 'URS用户ID');
                 $filter->equal('urs_referrer_id', 'URS推荐人ID');
+                $filter->like('farm_username', '农场用户名');
+                $filter->like('farm_nickname', '农场用户昵称');
+                $filter->like('referrer_farm_username', '推荐人农场用户名');
+                $filter->like('referrer_farm_nickname', '推荐人农场昵称');
                 $filter->equal('status', '状态')->select([
                     UrsUserReferral::STATUS_INVALID => '无效',
                     UrsUserReferral::STATUS_VALID => '有效',
@@ -86,6 +109,26 @@ class UrsUserReferralController extends AdminController
             $show->field('id', 'ID');
             $show->field('urs_user_id', 'URS用户ID');
             $show->field('urs_referrer_id', 'URS推荐人ID');
+
+            // 农场用户信息
+            $show->divider('农场用户信息');
+            $show->field('farm_username', '农场用户名')->as(function ($value) {
+                return $value ?: '未进入农场';
+            });
+            $show->field('farm_nickname', '农场用户昵称')->as(function ($value) {
+                return $value ?: '无昵称';
+            });
+
+            // 推荐人农场用户信息
+            $show->divider('推荐人农场用户信息');
+            $show->field('referrer_farm_username', '推荐人农场用户名')->as(function ($value) {
+                return $value ?: '未进入农场';
+            });
+            $show->field('referrer_farm_nickname', '推荐人农场用户昵称')->as(function ($value) {
+                return $value ?: '无昵称';
+            });
+
+            $show->divider('基本信息');
             $show->field('referral_time', '推荐时间');
             $show->field('status', '状态')->using([
                 UrsUserReferral::STATUS_INVALID => '无效',

+ 22 - 0
app/Module/UrsPromotion/Models/UrsUserReferral.php

@@ -74,6 +74,28 @@ class UrsUserReferral extends ModelCore
         return $this->belongsTo(UrsUserMapping::class, 'urs_referrer_id', 'urs_user_id');
     }
 
+    /**
+     * 获取农场用户信息(通过映射关系)
+     */
+    public function farmUser(): BelongsTo
+    {
+        return $this->belongsTo(\App\Module\User\Models\User::class, 'urs_user_id', 'id')
+            ->join('urs_promotion_user_mappings', 'users.id', '=', 'urs_promotion_user_mappings.user_id')
+            ->where('urs_promotion_user_mappings.urs_user_id', '=', $this->urs_user_id)
+            ->where('urs_promotion_user_mappings.status', '=', UrsUserMapping::STATUS_VALID);
+    }
+
+    /**
+     * 获取推荐人农场用户信息(通过映射关系)
+     */
+    public function referrerFarmUser(): BelongsTo
+    {
+        return $this->belongsTo(\App\Module\User\Models\User::class, 'urs_referrer_id', 'id')
+            ->join('urs_promotion_user_mappings', 'users.id', '=', 'urs_promotion_user_mappings.user_id')
+            ->where('urs_promotion_user_mappings.urs_user_id', '=', $this->urs_referrer_id)
+            ->where('urs_promotion_user_mappings.status', '=', UrsUserMapping::STATUS_VALID);
+    }
+
     /**
      * 检查推荐关系是否有效
      */

+ 28 - 0
app/Module/UrsPromotion/Repositorys/UrsUserReferralRepository.php

@@ -3,6 +3,7 @@
 namespace App\Module\UrsPromotion\Repositorys;
 
 use App\Module\UrsPromotion\Models\UrsUserReferral;
+use App\Module\UrsPromotion\Models\UrsUserMapping;
 use Dcat\Admin\Repositories\EloquentRepository;
 
 /**
@@ -16,4 +17,31 @@ class UrsUserReferralRepository extends EloquentRepository
      * 模型类名
      */
     protected $eloquentClass = UrsUserReferral::class;
+
+    /**
+     * 自定义查询构建器
+     */
+    public function query()
+    {
+        return $this->model()
+            ->leftJoin('urs_promotion_user_mappings as user_mapping', function($join) {
+                $join->on('urs_promotion_user_referrals.urs_user_id', '=', 'user_mapping.urs_user_id')
+                     ->where('user_mapping.status', '=', UrsUserMapping::STATUS_VALID);
+            })
+            ->leftJoin('users as farm_user', 'user_mapping.user_id', '=', 'farm_user.id')
+            ->leftJoin('user_infos as farm_user_info', 'farm_user.id', '=', 'farm_user_info.user_id')
+            ->leftJoin('urs_promotion_user_mappings as referrer_mapping', function($join) {
+                $join->on('urs_promotion_user_referrals.urs_referrer_id', '=', 'referrer_mapping.urs_user_id')
+                     ->where('referrer_mapping.status', '=', UrsUserMapping::STATUS_VALID);
+            })
+            ->leftJoin('users as referrer_farm_user', 'referrer_mapping.user_id', '=', 'referrer_farm_user.id')
+            ->leftJoin('user_infos as referrer_farm_user_info', 'referrer_farm_user.id', '=', 'referrer_farm_user_info.user_id')
+            ->select([
+                'urs_promotion_user_referrals.*',
+                'farm_user.username as farm_username',
+                'farm_user_info.nickname as farm_nickname',
+                'referrer_farm_user.username as referrer_farm_username',
+                'referrer_farm_user_info.nickname as referrer_farm_nickname',
+            ]);
+    }
 }