diff --git a/src/server/game/Handlers/AuthHandler.cpp b/src/server/game/Handlers/AuthHandler.cpp index 64943a639..78caf0a82 100644 --- a/src/server/game/Handlers/AuthHandler.cpp +++ b/src/server/game/Handlers/AuthHandler.cpp @@ -211,6 +211,14 @@ void WorldSession::SendFeatureSystemStatusGlueScreen() // defaults are Blizzard's dev hosts (https://us.apidev.blizzard.net, https://oauth.web.blizzard.net), // which is why an arbitrary host is acceptable to it. Only advertised when Shop.Shop2Enabled is on // AND a URL is actually configured, so we never announce a store with nowhere to reach. + // + // The retail client also gates storefront availability CLIENT-SIDE on the config vars below before + // it ever opens the webview. retail (build 69933) advertises the full set {VCSegmentStr, VCPlacementStr, + // POPStr, SSO/SFM/PMT/order/currency/bundle retry & throttle knobs, telemetry flags, ...}; with only + // the host + clientId vars present the storefront app considers itself unconfigured and shows + // "shop unavailable" without dialing the endpoint at all. Values below are the live retail values + // captured from the 09/23/2026 18:03 login of that sniff; our Shop2 endpoints ignore the placement + // GUIDs and echo whatever placement the client posts, so advertising the retail GUIDs is safe. std::vector varList(std::begin(vars), std::end(vars)); if (shopEnabled && sWorld->getBoolConfig(CONFIG_SHOP_SHOP2_ENABLED)) { @@ -224,6 +232,41 @@ void WorldSession::SendFeatureSystemStatusGlueScreen() addIfConfigured("shop2HostUrlRequests"sv, "Shop.Shop2HostUrlRequests"); addIfConfigured("shop2HostUrlAuth"sv, "Shop.Shop2HostUrlAuth"); addIfConfigured("shop2ClientIdStr"sv, "Shop.Shop2ClientId"); + + struct { std::string_view name; std::string_view value; } shop2Vars[] = + { + { "shop2VCSegmentStr"sv, "T2_WOW_US"sv }, + { "shop2VCPlacementStr"sv, "9aad42ec-a68c-487b-a300-b67518267a85"sv }, + { "shop2POPStr"sv, "b94aa31b-f910-4ec8-a180-3fb6bdac3215"sv }, + { "shop2SSOMaxTries"sv, "15"sv }, + { "shop2SSOPerMilliseconds"sv, "1000"sv }, + { "shop2ClientRetriesEnabled"sv, "1"sv }, + { "shop2SFMMaxTries"sv, "15"sv }, + { "shop2SFMPerMilliseconds"sv, "1000"sv }, + { "shop2PMTMaxTries"sv, "15"sv }, + { "shop2PMTPerMilliseconds"sv, "1000"sv }, + { "shop2DynamicBundleMaxTries"sv, "10"sv }, + { "shop2DynamicBundlePerMilliseconds"sv, "1000"sv }, + { "shop2DefaultCurrencyMaxTries"sv, "5"sv }, + { "shop2DefaultCurrencyPerMilliseconds"sv, "1000"sv }, + { "shop2OrderStatusMaxTries"sv, "3"sv }, + { "shop2OrderStatusPerMilliseconds"sv, "1000"sv }, + { "shop2VirtualCurrencyBalanceMaxTries"sv, "3"sv }, + { "shop2VirtualCurrencyBalancePerMilliseconds"sv, "1000"sv }, + { "shop2PendingOrderPollCheckoutEnabled"sv, "1"sv }, + { "shop2PendingOrderPollFileEnabled"sv, "1"sv }, + { "shop2PendingOrderPollSeconds"sv, "5"sv }, + // We serve no telemetry endpoints, so advertising 1 would send the storefront app after + // routes that only 404 (evryCore's local shop2 module ships these as 0 for the same reason). + { "shop2TelemetryAllowed"sv, "0"sv }, + { "shop2ClientErrorTelemetryAllowed"sv, "0"sv }, + { "shop2UseConnectedRealmGameServiceRegionId"sv, "0"sv }, + { "shop2BlockedPlacements"sv, ""sv }, + { "shop2AdditionalScopesStr"sv, ""sv }, + }; + + for (auto& shop2Var : shop2Vars) + varList.emplace_back(shop2Var.name, shop2Var.value); } WorldPackets::System::MirrorVars variables;