This commit is contained in:
2026-09-29 09:40:37 +03:00
parent 441021b9a6
commit 6567e731d1
34 changed files with 57 additions and 709 deletions
+1 -16
View File
@@ -46,8 +46,6 @@ QString normalizeUuid(const QString &uuid)
return QString(uuid).remove(u'-');
}
// Первый элемент DisplayClaims.xui — единственный, который отдают и Xbox Live,
// и XSTS: в нём лежат uhs (хеш пользователя) и xid (он же XUID).
QJsonObject displayClaim(const QJsonObject &response)
{
return response.value(QStringLiteral("DisplayClaims"))
@@ -58,8 +56,6 @@ QJsonObject displayClaim(const QJsonObject &response)
.toObject();
}
// XSTS отказывает не текстом, а числовым кодом — без расшифровки пользователь
// видит просто «401».
QString describeXstsError(const QJsonObject &response)
{
const qint64 code = static_cast<qint64>(response.value(QStringLiteral("XErr")).toDouble());
@@ -92,7 +88,7 @@ QString describeOauthError(const QJsonObject &response, int status)
return Loc::text("auth.msa.error.microsoftCode").arg(status);
}
} // namespace
}
MsaAuthService::MsaAuthService(QObject *parent)
: QObject(parent)
@@ -113,8 +109,6 @@ QUrl MsaAuthService::authorizationUrl()
query.addQueryItem(QStringLiteral("response_type"), QStringLiteral("code"));
query.addQueryItem(QStringLiteral("redirect_uri"), kRedirectUri);
query.addQueryItem(QStringLiteral("scope"), kScope);
// Без этого Microsoft молча пускает по прошлой сессии браузера, и добавить
// второй аккаунт становится нечем.
query.addQueryItem(QStringLiteral("prompt"), QStringLiteral("select_account"));
url.setQuery(query);
return url;
@@ -127,8 +121,6 @@ bool MsaAuthService::matchRedirect(const QUrl &url, QString *code, QString *erro
|| url.path() != redirect.path())
return false;
// Код приходит в query, но часть приложений Azure настроена на response_mode
// с фрагментом — разбираем оба места.
QUrlQuery query(url.query());
if (!query.hasQueryItem(QStringLiteral("code")) && !query.hasQueryItem(QStringLiteral("error")))
query = QUrlQuery(url.fragment());
@@ -268,8 +260,6 @@ void MsaAuthService::exchangeToken(const QByteArray &form, Callback callback)
}
const QString accessToken = response.value(QStringLiteral("access_token")).toString();
// Refresh-токен приходит и при продлении: Microsoft выдаёт новый
// и обесценивает прежний, поэтому сохранять надо свежий.
const QString refreshToken = response.value(QStringLiteral("refresh_token")).toString();
if (accessToken.isEmpty()) {
AuthResult result;
@@ -414,9 +404,6 @@ void MsaAuthService::checkLicense(AuthResult result, Callback callback)
getJson(QUrl(kEntitlementsUrl), result.accessToken,
[this, result, callback](int status, const QJsonObject &response, const QString &) {
// Сетевую ошибку здесь не считаем отказом: окончательный ответ
// про лицензию даёт профиль, а список покупок нужен только
// затем, чтобы точнее объяснить отказ.
const bool owns = status == 200
&& !response.value(QStringLiteral("items")).toArray().isEmpty();
fetchProfile(result, owns, callback);
@@ -435,8 +422,6 @@ void MsaAuthService::fetchProfile(AuthResult result, bool storeEntitlement, Call
return;
}
// 404 здесь — штатный ответ для аккаунта, на котором нет копии
// игры: профиль игрока создаётся только вместе с покупкой.
if (status == 404 || status == 401) {
result.licenseMissing = true;
result.error =