Игрок
Операции игрока выполняются в браузере витрины. Передавайте Content-Type и X-Game-Platform-ID, используйте настроенный домен площадки, чтобы браузерный Origin совпадал с ним, и указывайте credentials: 'include' в каждом запросе.
Не передавайте API-ключ площадки из браузера. После входа API устанавливает HttpOnly-cookie сессии: браузерный JavaScript не должен читать или создавать её.
Получение конфигурации авторизации
Ответ содержит только публичные идентификаторы провайдеров, необходимые для запуска входа. Секреты провайдеров в контексте витрины не возвращаются.
fragment PlatformAuthConfig on AuthConfig {
id
name
description
xsollaConfig {
loginProjectId
}
googleConfig {
clientID
}
yandexConfig {
clientID
}
vkIdConfig {
clientID
}
configs {
web {
implementation
activeService
}
}
}
query PlayerAuthConfiguration {
result: PlatformFetchGamePlatform {
__typename
... on Problem {
message
}
... on GamePlatform {
isMultipleAuthConfigUsed
authConfig {
...PlatformAuthConfig
}
allAuthConfigs {
...PlatformAuthConfig
}
}
}
}
Структура успешного ответа:
{
"data": {
"result": {
"__typename": "GamePlatform",
"isMultipleAuthConfigUsed": false,
"authConfig": {
"id": "configured-auth-id",
"name": "Вход через Google",
"description": "Войти с помощью Google",
"googleConfig": {
"clientID": "public-oauth-client-id"
},
"configs": {
"web": {
"implementation": "EXTERNAL",
"activeService": "GOOGLE"
}
}
},
"allAuthConfigs": []
}
}
}
Если isMultipleAuthConfigUsed равен true, предложите игроку выбрать конфигурацию из allAuthConfigs и передайте её id как authConfigId при входе. Иначе используйте authConfig.
Вход игрока
Завершите OAuth-сценарий одного из провайдеров авторизации, настроенных на площадке, а затем обменяйте полученный короткоживущий токен провайдера в GamePush.
Настройка провайдеров и требования к callback описаны в разделе «Сторонняя авторизация». На этой странице остаются специфичные для витрины обмен токена и работа с cookie сессии.
mutation LoginPlayer($input: LoginPlayerOnGamePlatformInput!) {
result: LoginPlayerOnGamePlatform(input: $input) {
__typename
... on Problem {
message
}
... on LoginPlayerOnGamePlatformResult {
isNewUser
}
}
}
Переменные:
{
"input": {
"gamePlatformID": 42,
"token": "SHORT_LIVED_PROVIDER_TOKEN",
"tokenType": "AccessToken",
"redirectUri": "https://games.example.com/auth/callback",
"authConfigId": "configured-auth-id"
}
}
Во время выполнения используйте настоящий короткоживущий токен провайдера, не записывайте его в логи и репозиторий. tokenType принимает AccessToken или ExchangeToken в зависимости от выбранного провайдера.
Успешный ответ:
{
"data": {
"result": {
"__typename": "LoginPlayerOnGamePlatformResult",
"isNewUser": false
}
}
}
Чтобы завершить сессию, сохраните те же браузерные заголовки и настройки cookie:
mutation LogoutPlayer {
result: LogoutPlayerOnGamePlatform {
__typename
... on Problem {
message
}
... on Success {
success
}
}
}
{
"data": {
"result": {
"__typename": "Success",
"success": true
}
}
}
Получение и обновление профиля
query CurrentPlatformPlayer($input: GetGamePlatformPlayerInput!) {
result: GetGamePlatformPlayer(input: $input) {
__typename
... on Problem {
message
}
... on GamePlatformPlayer {
id
gamePlatformID
name
avatar
balance
autoSkipAds
credentials {
login
type
}
vip {
productTag
enabled
disableGameAds
disablePlatformAds
currencyAccrual
bonusCurrency
endTime
}
playedGames
}
}
}
Переменные:
{
"input": {}
}
Структура успешного ответа:
{
"data": {
"result": {
"__typename": "GamePlatformPlayer",
"id": 9001,
"gamePlatformID": 42,
"name": "Игрок",
"avatar": "https://cdn.example.com/avatar.webp",
"balance": "1200",
"autoSkipAds": false,
"credentials": {
"login": "player@example.com",
"type": "EMAIL"
},
"vip": {
"productTag": "vip-month",
"enabled": true,
"disableGameAds": true,
"disablePlatformAds": true,
"currencyAccrual": 100,
"bonusCurrency": 50,
"endTime": "2026-09-01T00:00:00Z"
},
"playedGames": [101, 102]
}
}
}
Передавайте projectId во входных данных только тогда, когда профиль нужно подготовить для конкретной игры.
mutation UpdatePlatformPlayer($input: UpdatePlayerProfileOnGamePlatformInput!) {
result: UpdatePlayerProfileOnGamePlatform(input: $input) {
__typename
... on Problem {
message
}
... on GamePlatformPlayer {
id
name
avatar
autoSkipAds
}
}
}
Переменные и успешный ответ:
{
"input": {
"name": "Новое имя",
"avatarURL": "https://cdn.example.com/new-avatar.webp",
"autoSkipAds": false
}
}
{
"data": {
"result": {
"__typename": "GamePlatformPlayer",
"id": 9001,
"name": "Новое имя",
"avatar": "https://cdn.example.com/new-avatar.webp",
"autoSkipAds": false
}
}
}
Формирование раздела «Мои игры»
Получите playedGames из профиля, а затем преобразуйте эти ID в карточки игр. Пустой список ID возвращает пустой список игр.
query MyGames($input: FetchGamesOnGamePlatformByIdsInput!, $lang: Lang) {
result: FetchGamesOnGamePlatformByIds(input: $input) {
__typename
... on Problem {
message
}
... on GameViewsList {
count
items {
id
name(lang: $lang)
icon(lang: $lang)
cover(lang: $lang)
platformUrl(lang: $lang)
rating
}
}
}
}
{
"lang": "RU",
"input": {
"gamePlatformId": 42,
"gameIds": [101, 102],
"targetOS": "Desktop"
}
}
{
"data": {
"result": {
"__typename": "GameViewsList",
"count": 2,
"items": [
{
"id": 101,
"name": "Пример игры",
"platformUrl": "https://games.example.com/game/example-game",
"rating": 8.4
}
]
}
}
}
Запишите игру после её запуска:
mutation AddPlayedGame($input: AddGameToPlayedOnGamePlatformInput!) {
result: AddGameToPlayedOnGamePlatform(input: $input) {
__typename
... on Problem {
message
}
... on Success {
success
}
}
}
{
"input": {
"gameViewId": 101
}
}
{
"data": {
"result": {
"__typename": "Success",
"success": true
}
}
}
Удалите одну игру или импортируйте локальный список в пустой профиль игрока с помощью следующих операций:
mutation RemovePlayedGame(
$input: RemoveGameFromPlayedOnGamePlatformInput!
) {
result: RemoveGameFromPlayedOnGamePlatform(input: $input) {
__typename
... on Problem {
message
}
... on Success {
success
}
}
}
mutation SyncPlayedGames($input: SyncPlayedGamesOnGamePlatformInput!) {
result: SyncPlayedGamesOnGamePlatform(input: $input) {
__typename
... on Problem {
message
}
... on Success {
success
}
}
}
Переменные для RemovePlayedGame:
{
"input": {
"gameViewId": 101
}
}
Переменные для SyncPlayedGames:
{
"input": {
"gameViewIds": [101, 102]
}
}
Обе успешные мутации возвращают {"__typename":"Success","success":true}. SyncPlayedGamesOnGamePlatform предназначена для импорта локально сохранённых игр гостя после первой регистрации игрока. Она сохраняет не более первых 25 опубликованных игр и только тогда, когда серверный список playedGames пуст. Если в нём уже есть игры, мутация возвращает успех без изменений. Она не заменяет существующий список; для последующих изменений используйте мутации добавления и удаления.
Покупка валюты или преимуществ площадки
Показывайте доступные пакеты из productsList запроса площадки. Начинайте покупку только после входа игрока.
Общие понятия товара и покупки описаны в разделе «Покупки». Запросы ниже покрывают специфичные для витрины покупку пакета, payload провайдера и проверку статуса.
mutation PurchasePlatformBundle($input: PurchaseGamePlatformCurrencyBundleInput!) {
result: PurchaseGamePlatformCurrencyBundle(input: $input) {
__typename
... on Problem {
message
}
... on PlayerPurchaseOutput {
product {
id
tag
type
price(platform: PARTNER)
currency
}
purchase {
_id
orderStatus
payload
}
}
}
}
{
"input": {
"productId": 15,
"lang": "RU"
}
}
{
"data": {
"result": {
"__typename": "PlayerPurchaseOutput",
"product": {
"id": 15,
"tag": "coins-1000",
"type": "CURRENCY_BUNDLE",
"price": 4.99,
"currency": "USD"
},
"purchase": {
"_id": "purchase-id",
"orderStatus": "NEW",
"payload": {
"token": "SHORT_LIVED_PAYMENT_TOKEN"
}
}
}
}
}
Получите paymentsConfig.configs.web.activeService из запроса площадки и обрабатывайте payload в зависимости от выбранного сервиса:
activeService | Поля payload | Действие витрины |
|---|---|---|
XSOLLA | { "token": "..." } | Откройте Xsolla Pay Station по адресу https://secure.xsolla.com/paystation4/?token=<token>. |
ROBOKASSA | { "url": "https://..." } | Откройте полученный адрес оплаты в платёжном интерфейсе или перенаправьте на него игрока. |
STRIPE | { "url": "https://..." } | Откройте полученный адрес Stripe Checkout в платёжном интерфейсе или перенаправьте на него игрока. |
Настройка стороны провайдера описана в разделах «Xsolla», «Robokassa» и «Stripe». Выбирайте интеграцию по activeService, а не по случайно найденному полю в payload. Считайте платёжные токены и адреса краткоживущими данными: не записывайте их в логи и не сохраняйте.
Браузер не должен самостоятельно отмечать покупку оплаченной. После завершения сценария провайдера опрашивайте покупку по ID и используйте orderStatus как источник истины:
query PlatformPurchase($input: GetGamePlatformPurchaseInput!) {
result: GetGamePlatformPurchase(input: $input) {
__typename
... on Problem {
message
}
... on PlayerPurchase {
_id
orderStatus
payload
product {
id
type
price(platform: PARTNER)
}
}
}
}
{
"input": {
"purchaseId": "purchase-id"
}
}
{
"data": {
"result": {
"__typename": "PlayerPurchase",
"_id": "purchase-id",
"orderStatus": "PAID",
"payload": {
"token": "SHORT_LIVED_PAYMENT_TOKEN"
},
"product": {
"id": 15,
"type": "CURRENCY_BUNDLE",
"price": 4.99
}
}
}
}
Для внутриигрового товара, оплачиваемого с баланса площадки, передайте товар, проект и провайдера из API игры:
mutation PurchaseGameProduct($input: PurchaseProductOnGamePlatformInput!) {
result: PurchaseProductOnGamePlatform(input: $input) {
__typename
... on Problem {
message
}
... on PlayerPurchase {
_id
projectId
productId
orderStatus
product {
id
name(lang: RU)
price(platform: PARTNER)
}
}
}
}
{
"input": {
"productId": 301,
"projectId": 501,
"provider": "GAMEPUSH"
}
}
{
"data": {
"result": {
"__typename": "PlayerPurchase",
"_id": "game-purchase-id",
"projectId": 501,
"productId": 301,
"orderStatus": "PAID",
"product": {
"id": 301,
"name": "Стартовый набор",
"price": 500
}
}
}
}
Всегда считайте orderStatus из API источником истины: не помечайте покупку оплаченной только потому, что браузер вернулся с платёжной страницы.