Browse Source

实现URS login4u对接功能

- 创建Login4uHandler处理URS userKey登录请求
- 实现完整的登录流程:URS用户验证、农场用户映射、推荐关系同步
- 支持自动创建农场用户并建立URS用户映射关系
- 同步上下级推荐关系到UrsPromotion模块
- 添加详细的错误处理和日志记录
- 创建TestLogin4uCommand测试命令验证功能
- 修复ThirdParty BaseRequest类方法重复定义问题
- 修复URS BaseRequest类方法签名兼容性问题
notfff 7 months ago
parent
commit
3d673aa8ad

+ 7 - 2
AiWork/WORK.md

@@ -2,8 +2,13 @@
 
 ## 当前任务
 
-暂无待处理任务
-
+对接 login4u ,使用urs的userKey登陆
+ 新增 RequestPublicLogin4u ,编写对应的 Handler
+逻辑为:
+1. 使用 UrsGetUserInfoRequest 和 RequestPublicLogin4u.keylogin 的登陆密钥获取到 urs.user_id
+2. 使用 \App\Module\UrsPromotion\Services\UrsUserMappingService::getFarmUserId 获取农场用户ID
+3. 拉去上下级关系,同步到 UrsPromotion 模块
+4. 完成登陆,返回response
 
 
 ## 已完成任务(保留最新的10条,多余的删除)

+ 12 - 2
ThirdParty/Urs/Request/BaseRequest.php

@@ -17,12 +17,22 @@ abstract class BaseRequest extends \App\Module\ThirdParty\Services\BaseRequest
         parent::__construct('urs');
     }
 
-    protected function getConfig(string $c = ''): \ThirdParty\Urs\Dto\Config
+    /**
+     * 获取URS配置对象
+     *
+     * @return \ThirdParty\Urs\Dto\Config
+     */
+    protected function getUrsConfig(): \ThirdParty\Urs\Dto\Config
     {
         return Config::fromArray($this->service->config);
     }
 
-    protected function getCredential(string $c = ''): \ThirdParty\Urs\Dto\Credential
+    /**
+     * 获取URS凭证对象
+     *
+     * @return \ThirdParty\Urs\Dto\Credential
+     */
+    protected function getUrsCredential(): \ThirdParty\Urs\Dto\Credential
     {
         return \ThirdParty\Urs\Dto\Credential::fromArray($this->service->config);
     }

+ 2 - 3
ThirdParty/Urs/Request/UrsGetUserInfoRequest.php

@@ -2,7 +2,6 @@
 
 namespace ThirdParty\Urs\Request;
 
-use App\Module\ThirdParty\Services\BaseRequest;
 use ThirdParty\Urs\Util\CryptoService;
 
 /**
@@ -11,7 +10,7 @@ use ThirdParty\Urs\Util\CryptoService;
  * 专门处理获取用户信息请求,遵循"一个Request类只完成一种请求"的原则
  * 根据用户密钥获取用户ID
  */
-class UrsGetUserInfoRequest extends \ThirdParty\Urs\Request\BaseRequest
+class UrsGetUserInfoRequest extends BaseRequest
 {
 
 
@@ -30,7 +29,7 @@ class UrsGetUserInfoRequest extends \ThirdParty\Urs\Request\BaseRequest
         }
 
         // 获取URS配置
-        $c = $this->getCredential();
+        $c = $this->getUrsCredential();
 
         $apiUrl = $this->getService()->getApiUrl();
         $appKey = $c->getApiKey() ;

+ 135 - 0
app/Module/AppGame/Commands/TestLogin4uCommand.php

@@ -0,0 +1,135 @@
+<?php
+
+namespace App\Module\AppGame\Commands;
+
+use App\Module\AppGame\Handler\Public\Login4uHandler;
+use Illuminate\Console\Command;
+use Uraus\Kku\Request\RequestPublicLogin4u;
+use Uraus\Kku\Response;
+
+/**
+ * 测试Login4u功能的命令
+ */
+class TestLogin4uCommand extends Command
+{
+    /**
+     * 命令签名
+     *
+     * @var string
+     */
+    protected $signature = 'test:login4u {keylogin? : URS登录密钥}';
+
+    /**
+     * 命令描述
+     *
+     * @var string
+     */
+    protected $description = '测试URS login4u登录功能';
+
+    /**
+     * 执行命令
+     *
+     * @return int
+     */
+    public function handle(): int
+    {
+        $this->info('=== 测试URS Login4u功能 ===');
+
+        // 获取测试用的keylogin
+        $keylogin = $this->argument('keylogin') ?: $this->ask('请输入URS登录密钥(keylogin)');
+        
+        if (empty($keylogin)) {
+            $this->error('登录密钥不能为空');
+            return Command::FAILURE;
+        }
+
+        try {
+            // 1. 测试Handler类是否存在
+            $this->info('1. 检查Handler类...');
+            if (!class_exists(\App\Module\AppGame\Handler\Public\Login4uHandler::class)) {
+                $this->error('Login4uHandler类不存在');
+                return Command::FAILURE;
+            }
+            $this->line('✓ Login4uHandler类存在');
+
+            // 2. 测试Request和Response类是否存在
+            $this->info('2. 检查Protobuf类...');
+            if (!class_exists(\Uraus\Kku\Request\RequestPublicLogin4u::class)) {
+                $this->error('RequestPublicLogin4u类不存在');
+                return Command::FAILURE;
+            }
+            $this->line('✓ RequestPublicLogin4u类存在');
+
+            if (!class_exists(\Uraus\Kku\Response\ResponsePublicLogin4u::class)) {
+                $this->error('ResponsePublicLogin4u类不存在');
+                return Command::FAILURE;
+            }
+            $this->line('✓ ResponsePublicLogin4u类存在');
+
+            // 3. 测试URS服务是否可用
+            $this->info('3. 检查URS服务...');
+            if (!class_exists(\ThirdParty\Urs\Services\UrsService::class)) {
+                $this->error('UrsService类不存在');
+                return Command::FAILURE;
+            }
+            $this->line('✓ UrsService类存在');
+
+            // 4. 测试UrsUserMappingService是否可用
+            $this->info('4. 检查UrsUserMappingService...');
+            if (!class_exists(\App\Module\UrsPromotion\Services\UrsUserMappingService::class)) {
+                $this->error('UrsUserMappingService类不存在');
+                return Command::FAILURE;
+            }
+            $this->line('✓ UrsUserMappingService类存在');
+
+            // 5. 创建测试请求
+            $this->info('5. 创建测试请求...');
+            $request = new RequestPublicLogin4u();
+            $request->setKeylogin($keylogin);
+            $this->line("✓ 测试请求创建成功,keylogin: {$keylogin}");
+
+            // 6. 创建Handler实例并测试
+            $this->info('6. 测试Handler处理...');
+            $response = new Response();
+            $handler = new Login4uHandler($response);
+            
+            $this->line('开始处理登录请求...');
+            $result = $handler->handle($request);
+
+            // 7. 检查响应
+            $this->info('7. 检查响应结果...');
+            if (!$result instanceof \Uraus\Kku\Response\ResponsePublicLogin4u) {
+                $this->error('响应类型错误,期望ResponsePublicLogin4u');
+                return Command::FAILURE;
+            }
+
+            $token = $result->getToken();
+            $isProhibit = $result->getIsProhibit();
+
+            if (empty($token) || $isProhibit) {
+                $this->error('登录失败');
+                $this->line("Token: {$token}");
+                $this->line("IsProhibit: " . ($isProhibit ? 'true' : 'false'));
+                return Command::FAILURE;
+            }
+
+            $this->info('✓ 登录成功!');
+            $this->line("Token: {$token}");
+            $this->line("IsProhibit: " . ($isProhibit ? 'true' : 'false'));
+
+            // 8. 检查最后登录信息
+            if ($result->hasLastLoginInfo()) {
+                $lastLoginInfo = $result->getLastLoginInfo();
+                $this->line("最后登录时间: " . date('Y-m-d H:i:s', $lastLoginInfo->getLoginTime()));
+            }
+
+            $this->info('=== 测试完成 ===');
+            return Command::SUCCESS;
+
+        } catch (\Exception $e) {
+            $this->error('测试失败: ' . $e->getMessage());
+            $this->line('错误详情: ' . $e->getTraceAsString());
+            return Command::FAILURE;
+        }
+    }
+}

+ 195 - 0
app/Module/AppGame/Handler/Public/Login4uHandler.php

@@ -0,0 +1,195 @@
+<?php
+
+namespace App\Module\AppGame\Handler\Public;
+
+use App\Module\AppGame\Events\LoginSuccessEvent;
+use App\Module\AppGame\Handler\BaseHandler;
+use App\Module\AppGame\SessionApp;
+use App\Module\UrsPromotion\Services\UrsUserMappingService;
+use App\Module\UrsPromotion\Services\UrsReferralService;
+use App\Module\User\Services\UserService;
+use Google\Protobuf\Internal\Message;
+use Illuminate\Support\Facades\Event;
+use Illuminate\Support\Facades\Log;
+use ThirdParty\Urs\Services\UrsService;
+use Uraus\Kku\Request\RequestPublicLogin4u;
+use Uraus\Kku\Response\ResponsePublicLogin4u;
+use Uraus\Kku\Response\LastLoginInfo;
+
+/**
+ * 处理URS login4u登录请求
+ * 
+ * 使用URS的userKey进行登录,自动创建用户并同步推荐关系
+ */
+class Login4uHandler extends BaseHandler
+{
+    /**
+     * 是否需要登录
+     *
+     * @var bool
+     */
+    protected bool $need_login = false;
+
+    /**
+     * 处理login4u登录请求
+     *
+     * @param RequestPublicLogin4u $data 登录请求数据
+     * @return ResponsePublicLogin4u 登录响应
+     */
+    public function handle(Message $data): Message
+    {
+        try {
+            // 1. 验证登录密钥
+            $keylogin = $data->getKeylogin();
+            if (empty($keylogin)) {
+                throw new \Exception('登录密钥不能为空');
+            }
+
+            // 2. 使用URS获取用户信息
+            $ursUserInfo = $this->getUrsUserInfo($keylogin);
+            $ursUserId = $ursUserInfo['userId'];
+
+            // 3. 获取或创建农场用户ID
+            $farmUserId = UrsUserMappingService::getFarmUserId($ursUserId);
+            if (!$farmUserId) {
+                throw new \Exception('获取农场用户ID失败');
+            }
+
+            // 4. 获取农场用户信息
+            $userDto = UserService::info($farmUserId);
+            if (!$userDto) {
+                throw new \Exception('农场用户不存在');
+            }
+
+            // 5. 同步上下级关系
+            $this->syncReferralRelations($ursUserId);
+
+            // 6. 设置用户登录状态
+            $user = \App\Module\User\Models\User::find($farmUserId);
+            if (!$user) {
+                throw new \Exception('用户模型获取失败');
+            }
+
+            SessionApp::setLogin($user);
+            $sessionId = SessionApp::getSessionId();
+
+            // 7. 触发登录成功事件
+            Event::dispatch(new LoginSuccessEvent($user, $sessionId));
+
+            // 8. 记录登录日志
+            Log::info('URS login4u登录成功', [
+                'urs_user_id' => $ursUserId,
+                'farm_user_id' => $farmUserId,
+                'username' => $user->username,
+                'session_id' => $sessionId
+            ]);
+
+            // 9. 创建响应对象
+            $response = new ResponsePublicLogin4u();
+            $response->setToken($sessionId);
+            $response->setIsProhibit(false); // 根据用户状态设置
+
+            // 设置最后登录信息(可选)
+            $lastLoginInfo = new LastLoginInfo();
+            $lastLoginInfo->setLoginTime(time());
+            $response->setLastLoginInfo($lastLoginInfo);
+
+            return $response;
+
+        } catch (\Exception $e) {
+            Log::error('URS login4u登录失败', [
+                'keylogin' => $keylogin ?? '',
+                'error' => $e->getMessage(),
+                'trace' => $e->getTraceAsString()
+            ]);
+
+            // 返回失败响应
+            $response = new ResponsePublicLogin4u();
+            $response->setToken('');
+            $response->setIsProhibit(true);
+            
+            return $response;
+        }
+    }
+
+    /**
+     * 获取URS用户信息
+     *
+     * @param string $keylogin 登录密钥
+     * @return array URS用户信息
+     * @throws \Exception
+     */
+    private function getUrsUserInfo(string $keylogin): array
+    {
+        try {
+            $result = UrsService::getUserInfo($keylogin);
+            
+            if (!$result['success'] || empty($result['data']['userId'])) {
+                throw new \Exception('URS用户信息获取失败: ' . ($result['message'] ?? '未知错误'));
+            }
+
+            return $result['data'];
+
+        } catch (\Exception $e) {
+            Log::error('获取URS用户信息失败', [
+                'keylogin' => $keylogin,
+                'error' => $e->getMessage()
+            ]);
+            throw new \Exception('URS用户验证失败: ' . $e->getMessage());
+        }
+    }
+
+    /**
+     * 同步上下级关系到UrsPromotion模块
+     *
+     * @param int $ursUserId URS用户ID
+     * @return void
+     */
+    private function syncReferralRelations(int $ursUserId): void
+    {
+        try {
+            // 获取用户的上级关系链
+            $teamResult = UrsService::getUserTeam($ursUserId);
+            
+            if (!$teamResult['success'] || empty($teamResult['data'])) {
+                Log::info('URS用户无上级关系', ['urs_user_id' => $ursUserId]);
+                return;
+            }
+
+            $teamData = $teamResult['data'];
+            
+            // 检查是否已存在推荐关系
+            $existingReferral = \App\Module\UrsPromotion\Models\UrsUserReferral::where('urs_user_id', $ursUserId)->first();
+            if ($existingReferral) {
+                Log::info('URS用户推荐关系已存在', [
+                    'urs_user_id' => $ursUserId,
+                    'urs_referrer_id' => $existingReferral->urs_referrer_id
+                ]);
+                return;
+            }
+
+            // 获取直接推荐人(一级上级)
+            $directReferrerId = $teamData['level1'] ?? null;
+            if (!$directReferrerId) {
+                Log::info('URS用户无直接推荐人', ['urs_user_id' => $ursUserId]);
+                return;
+            }
+
+            // 创建推荐关系
+            $referralDto = UrsReferralService::createReferral($ursUserId, $directReferrerId);
+            
+            Log::info('URS推荐关系同步成功', [
+                'urs_user_id' => $ursUserId,
+                'urs_referrer_id' => $directReferrerId,
+                'referral_id' => $referralDto->id
+            ]);
+
+        } catch (\Exception $e) {
+            // 推荐关系同步失败不影响登录流程
+            Log::warning('URS推荐关系同步失败', [
+                'urs_user_id' => $ursUserId,
+                'error' => $e->getMessage()
+            ]);
+        }
+    }
+}

+ 6 - 1
app/Module/AppGame/Providers/AppGameServiceProvider.php

@@ -37,7 +37,12 @@ class AppGameServiceProvider extends ServiceProvider
      */
     public function register(): void
     {
-        // 注册命令或其他服务
+        // 注册命令
+        if ($this->app->runningInConsole()) {
+            $this->commands([
+                \App\Module\AppGame\Commands\TestLogin4uCommand::class,
+            ]);
+        }
     }
 
     /**

+ 0 - 4
app/Module/ThirdParty/Services/BaseRequest.php

@@ -132,10 +132,6 @@ abstract class BaseRequest
      */
     abstract protected function handler(array $params = []): array;
 
-    abstract protected function getCredential(string $params = ''): Credential;
-
-    abstract protected function getConfig(string $params = ''): Config;
-
     /**
      * 检查配额
      *