ensureDemoIntegrationSite($siteCode, $currency, $mockWalletPort); $this->ensureE2ELeafAgent($siteCode, $password); // LocalDemoSeeder 可能已建无 password_hash 的 demo_player;合并为一条可登录行。 Player::query() ->where('site_code', $siteCode) ->where('username', $username) ->where('site_player_id', '!=', 'e2e-001') ->delete(); /** @var Player $player */ $player = Player::query()->updateOrCreate( ['site_code' => $siteCode, 'username' => $username], [ 'site_player_id' => 'e2e-001', 'password_hash' => Hash::make($password), 'auth_source' => PlayerAuthSource::LOTTERY_NATIVE, 'funding_mode' => 'wallet', 'nickname' => 'E2E Player', 'default_currency' => $currency, 'status' => 0, 'login_failed_count' => 0, ], ); PlayerWallet::query()->updateOrCreate( ['player_id' => $player->id, 'wallet_type' => 'lottery', 'currency_code' => $currency], [ 'balance' => $balance, 'frozen_balance' => 0, 'status' => 0, 'version' => 0, ], ); } private function ensureDemoIntegrationSite(string $siteCode, string $currency, string $mockWalletPort): void { $walletBase = 'http://127.0.0.1:'.trim($mockWalletPort); AdminSite::query()->updateOrCreate( ['code' => $siteCode], [ 'name' => 'E2E Demo Site', 'currency_code' => $currency, 'status' => 1, 'is_default' => false, 'extra_json' => ['source' => 'e2e'], 'wallet_api_url' => $walletBase, 'wallet_debit_path' => '/wallet/debit-for-lottery', 'wallet_credit_path' => '/wallet/credit-from-lottery', 'wallet_balance_path' => '/wallet/balance', 'wallet_api_key_encrypted' => encrypt('e2e-mock-key'), 'sso_jwt_secret_encrypted' => encrypt('e2e-sso-secret'), 'wallet_timeout_seconds' => 10, ], ); $siteId = (int) AdminSite::query()->where('code', $siteCode)->value('id'); if ($siteId <= 0) { return; } $rootId = (int) DB::table('agent_nodes') ->where('admin_site_id', $siteId) ->where('depth', 0) ->value('id'); if ($rootId <= 0) { $now = now(); $rootId = (int) DB::table('agent_nodes')->insertGetId([ 'admin_site_id' => $siteId, 'parent_id' => null, 'path' => '/', 'depth' => 0, 'code' => 'root-'.$siteCode, 'name' => 'E2E Root', 'status' => 1, 'created_by' => null, 'extra_json' => null, 'created_at' => $now, 'updated_at' => $now, ]); DB::table('agent_nodes')->where('id', $rootId)->update([ 'path' => '/'.$rootId.'/', ]); } if (! DB::table('agent_profiles')->where('agent_node_id', $rootId)->exists()) { $defaults = config('agent_line_defaults', []); $now = now(); DB::table('agent_profiles')->insert([ 'agent_node_id' => $rootId, 'total_share_rate' => (float) ($defaults['total_share_rate'] ?? 100), 'credit_limit' => (int) ($defaults['credit_limit'] ?? 0) > 0 ? (int) $defaults['credit_limit'] : 1_000_000, 'allocated_credit' => 0, 'used_credit' => 0, 'rebate_limit' => (float) ($defaults['rebate_limit'] ?? 0.005), 'default_player_rebate' => (float) ($defaults['default_player_rebate'] ?? 0.005), 'can_grant_extra_rebate' => true, 'can_create_child_agent' => true, 'can_create_player' => true, 'created_at' => $now, 'updated_at' => $now, ]); } } private function ensureE2ELeafAgent(string $siteCode, string $password): void { $siteId = (int) AdminSite::query()->where('code', $siteCode)->value('id'); if ($siteId <= 0) { return; } $exists = DB::table('admin_users')->where('username', 'e2e_leaf_agent')->exists(); if ($exists) { return; } $rootId = (int) DB::table('agent_nodes') ->where('admin_site_id', $siteId) ->where('depth', 0) ->value('id'); if ($rootId <= 0) { return; } $super = AdminUser::query()->where('username', 'admin')->first(); if ($super === null) { return; } app(AgentNodeService::class)->createChild($super, [ 'parent_id' => $rootId, 'code' => 'e2e_leaf', 'name' => 'E2E Leaf Agent', 'username' => 'e2e_leaf_agent', 'password' => $password, 'total_share_rate' => 25, 'credit_limit' => 200_000, 'rebate_limit' => 0.01, 'default_player_rebate' => 0.005, ]); } }