input('site_code') ?: env('E2E_PLAYER_SITE_CODE', 'demo')); $username = (string) ($request->input('username') ?: 'e2e_credit_player'); $password = (string) ($request->input('password') ?: env('E2E_PLAYER_PASSWORD', '12345678')); $creditLimit = max(1, (int) $request->input('credit_limit', 50_000)); $currency = strtoupper((string) ($request->input('currency') ?: config('lottery.default_currency', 'NPR'))); $site = AdminSite::query()->where('code', $siteCode)->first(); if ($site === null) { return ApiResponse::error('site not found', 'e2e_site_missing', null, 404); } $extra = $site->extra_json ?? []; if (! is_array($extra)) { $extra = json_decode((string) $extra, true); if (! is_array($extra)) { $extra = []; } } $extra['credit_line_mode'] = true; $site->extra_json = $extra; $site->save(); $rootId = (int) DB::table('agent_nodes') ->where('admin_site_id', $site->id) ->where('depth', 0) ->value('id'); if ($rootId <= 0) { return ApiResponse::error('root agent missing', 'e2e_agent_missing', null, 500); } $leafCode = (string) $request->input('agent_code', 'e2e_leaf'); $leaf = AgentNode::query() ->where('admin_site_id', $site->id) ->where('code', $leafCode) ->first(); if ($leaf === null) { $super = \App\Models\AdminUser::query()->where('username', 'admin')->first(); if ($super === null) { return ApiResponse::error('admin user missing', 'e2e_admin_missing', null, 500); } $leaf = app(AgentNodeService::class)->createChild($super, [ 'parent_id' => $rootId, 'code' => $leafCode, 'name' => 'E2E Leaf Agent', 'username' => 'e2e_leaf_agent', 'password' => (string) env('E2E_PLAYER_PASSWORD', '12345678'), 'total_share_rate' => 25, 'credit_limit' => 200_000, 'rebate_limit' => 0.01, 'default_player_rebate' => 0.005, ]); } /** @var Player $player */ $player = Player::query()->updateOrCreate( ['site_code' => $siteCode, 'username' => $username], [ 'site_player_id' => 'e2e-credit-'.substr(md5($username), 0, 8), 'password_hash' => Hash::make($password), 'auth_source' => PlayerAuthSource::LOTTERY_NATIVE, 'funding_mode' => 'credit', 'nickname' => 'E2E Credit', 'default_currency' => $currency, 'status' => 0, 'login_failed_count' => 0, 'login_locked_until' => null, 'agent_node_id' => $leaf->id, ], ); PlayerWallet::query()->updateOrCreate( ['player_id' => $player->id, 'wallet_type' => 'lottery', 'currency_code' => $currency], [ 'balance' => 0, 'frozen_balance' => 0, 'status' => 0, 'version' => 0, ], ); DB::table('player_credit_accounts')->updateOrInsert( ['player_id' => $player->id], [ 'credit_limit' => $creditLimit, 'used_credit' => 0, 'frozen_credit' => 0, 'updated_at' => now(), 'created_at' => now(), ], ); DB::table('player_rebate_profiles')->updateOrInsert( ['player_id' => $player->id, 'game_type' => '*'], [ 'rebate_rate' => 0.005, 'extra_rebate_rate' => 0, 'inherit_from_agent' => true, 'updated_at' => now(), 'created_at' => now(), ], ); return ApiResponse::success([ 'player_id' => (int) $player->id, 'username' => $username, 'password' => $password, 'site_code' => $siteCode, 'admin_site_id' => (int) $site->id, 'agent_node_id' => (int) $leaf->id, 'credit_limit' => $creditLimit, 'currency' => $currency, ]); } public function setupSiteOperator(Request $request): JsonResponse { PlatformSystemRoles::ensureAll(); $roleSlug = (string) ($request->input('role_slug') ?: SiteOperatorRoles::SLUG_SITE_FINANCE); $username = (string) ($request->input('username') ?: 'e2e_site_finance'); $password = (string) ($request->input('password') ?: env('E2E_PLAYER_PASSWORD', '12345678')); $siteCode = (string) ($request->input('site_code') ?: env('E2E_PLAYER_SITE_CODE', 'demo')); $site = AdminSite::query()->where('code', $siteCode)->first(); if ($site === null) { return ApiResponse::error('site not found', 'e2e_site_missing', null, 404); } $roleId = (int) DB::table('admin_roles')->where('slug', $roleSlug)->value('id'); if ($roleId <= 0) { return ApiResponse::error('role not found', 'e2e_role_missing', null, 500); } /** @var AdminUser $user */ $user = AdminUser::query()->updateOrCreate( ['username' => $username], [ 'name' => 'E2E Site Operator', 'email' => null, 'password' => $password, 'status' => 0, ], ); DB::table('admin_user_site_roles')->updateOrInsert( ['admin_user_id' => $user->id, 'site_id' => $site->id], ['role_id' => $roleId, 'granted_at' => now()], ); return ApiResponse::success([ 'admin_user_id' => (int) $user->id, 'username' => $username, 'password' => $password, 'role_slug' => $roleSlug, 'admin_site_id' => (int) $site->id, 'site_code' => $siteCode, ]); } public function resetSiteSettlement(Request $request): JsonResponse { $siteCode = (string) ($request->input('site_code') ?: env('E2E_PLAYER_SITE_CODE', 'demo')); $site = AdminSite::query()->where('code', $siteCode)->first(); if ($site === null) { return ApiResponse::error('site not found', 'e2e_site_missing', null, 404); } $siteId = (int) $site->id; $periodIds = DB::table('settlement_periods') ->where('admin_site_id', $siteId) ->pluck('id') ->all(); if ($periodIds !== []) { $billIds = DB::table('settlement_bills') ->whereIn('settlement_period_id', $periodIds) ->pluck('id') ->all(); if ($billIds !== []) { DB::table('payment_records')->whereIn('settlement_bill_id', $billIds)->delete(); } DB::table('settlement_adjustments')->whereIn('settlement_period_id', $periodIds)->delete(); DB::table('settlement_bills')->whereIn('settlement_period_id', $periodIds)->delete(); DB::table('settlement_periods')->where('admin_site_id', $siteId)->delete(); } return ApiResponse::success([ 'site_code' => $siteCode, 'admin_site_id' => $siteId, 'cleared_periods' => count($periodIds), ]); } public function mintSsoJwt(Request $request): JsonResponse { $siteCode = (string) ($request->input('site_code') ?: env('E2E_PLAYER_SITE_CODE', 'demo')); $sitePlayerId = (string) ($request->input('site_player_id') ?: 'e2e-sso-'.bin2hex(random_bytes(4))); $site = AdminSite::query()->where('code', $siteCode)->first(); if ($site === null) { return ApiResponse::error('site not found', 'e2e_site_missing', null, 404); } $secret = $site->decryptedSsoJwtSecret(); if (! is_string($secret) || $secret === '') { return ApiResponse::error('sso secret missing on site', 'e2e_sso_secret_missing', null, 500); } $now = time(); $jwt = JWT::encode([ 'site_code' => $siteCode, 'site_player_id' => $sitePlayerId, 'iat' => $now, 'exp' => $now + 300, ], $secret, 'HS256'); return ApiResponse::success([ 'jwt' => $jwt, 'site_code' => $siteCode, 'site_player_id' => $sitePlayerId, ]); } public function configureWalletApi(Request $request): JsonResponse { $siteCode = (string) ($request->input('site_code') ?: env('E2E_PLAYER_SITE_CODE', 'demo')); $baseUrl = rtrim((string) $request->input('base_url', ''), '/'); if ($baseUrl === '') { return ApiResponse::error('base_url required', 'e2e_invalid_input', null, 422); } $site = AdminSite::query()->where('code', $siteCode)->first(); if ($site === null) { return ApiResponse::error('site not found', 'e2e_site_missing', null, 404); } $site->wallet_api_url = $baseUrl; if ($request->filled('wallet_api_key')) { $site->wallet_api_key_encrypted = encrypt((string) $request->input('wallet_api_key')); } $site->save(); app(PartnerSiteConfigResolver::class)->forgetCache($siteCode); return ApiResponse::success([ 'site_code' => $siteCode, 'wallet_api_url' => $baseUrl, ]); } public function resetWalletApi(Request $request): JsonResponse { $siteCode = (string) ($request->input('site_code') ?: env('E2E_PLAYER_SITE_CODE', 'demo')); $site = AdminSite::query()->where('code', $siteCode)->first(); if ($site === null) { return ApiResponse::error('site not found', 'e2e_site_missing', null, 404); } $site->wallet_api_url = null; $site->save(); app(PartnerSiteConfigResolver::class)->forgetCache($siteCode); return ApiResponse::success(['site_code' => $siteCode, 'wallet_api_url' => null]); } }