Перейти к основному содержимому

Пополнение баланса игрока

Связанный пользовательский сценарий описан в разделе Пополнение баланса игрока.

Сценарий пополнения состоит из read-only поиска способов и двух шагов запуска:

  1. playerWalletTopUpMethods выполняет read-only поиск подходящих способов по сумме.
  2. preparePlayerWalletTopUp или prepareGuestPlayerWalletTopUp после выбора способа создаёт намерение и возвращает неизменяемый расчёт только для него.
  3. startPlayerWalletTopUp или startGuestPlayerWalletTopUp запускает выбранный расчёт и возвращает действие, которое должен выполнить клиент.

Объект расчёта возвращается в поле quote.

Для получения способов оплаты передайте сумму и, при наличии, страну плательщика. Запрос не требует сессии. Авторизованные мутации пополняют баланс текущего игрока; для гостевых мутаций укажите email получателя. Режим общего или серверного баланса задаётся в настройках проекта. Во всех мутациях используются UUIDv7 запросов. Заголовок Origin должен совпадать с адресом, зарегистрированным для проекта.

Пополнение доступно и при задолженности. Зачисление основного баланса сначала погашает её, а остаток становится доступен для покупок. Бонусная часть не погашает задолженность. Текущее состояние возвращают me.paymentDebt, me.purchasesRestricted и запрос refreshBalance. После полного погашения purchasesRestricted становится false; отклонённую покупку нужно оформить заново с новым requestId.

Получение способов оплаты​

QuerydocumentId: playerWalletTopUpMethodsauth: optional

playerWalletTopUpMethods​

Входные данные​

ПолеТипОбязательноеОписание
amountString!даПоложительная десятичная сумма без экспоненты и разделителей групп
payerCountryStringнетДвухбуквенный код страны, например RU

Результат​

PlayerWalletTopUpMethodDiscovery содержит список карточек способов:

ПолеТипОписание
methodProfileIdID!Идентификатор профиля способа в текущем проекте
methodCodeString!Код способа в верхнем регистре, например BANK_CARD или PAYGOL; для подписи используйте displayName
displayNameString!Локализованное название
iconAssetIdIDИдентификатор иконки, если она настроена

Запрос не создаёт намерение, расчёт или попытку оплаты и не резервирует средства. Повторяйте его после изменения суммы, страны или контекста баланса. После выбора methodProfileId передайте его в защищённую операцию подготовки.

Пример обмена​

Запрос
documentId: playerWalletTopUpMethods
{
"documentId": "playerWalletTopUpMethods",
"variables": {
"input": {
"amount": "10.00",
"payerCountry": "RU"
}
}
}
Ответ
200 OK
{
"data": {
"playerWalletTopUpMethods": {
"methods": [
{
"methodProfileId": "01910000-0000-7000-8000-000000000003",
"methodCode": "BANK_CARD",
"displayName": "Банковская карта",
"iconAssetId": "payment-method-card"
},
{
"methodProfileId": "01910000-0000-7000-8000-000000000006",
"methodCode": "SBP",
"displayName": "Система быстрых платежей",
"iconAssetId": null
}
]
}
}
}

Если подходящих профилей нет, возвращается TOP_UP_METHODS_UNAVAILABLE. Причины выбора или исключения конкретного профиля и ответы провайдера наружу не передаются.

Подготовка пополнения​

MutationdocumentId: preparePlayerWalletTopUpauth: Bearer session

preparePlayerWalletTopUp​

Входные данные​

ПолеТипОбязательноеОписание
requestIdID!даНовый UUIDv7. Повтор того же запроса с теми же данными возвращает прежний результат
amountString!даПоложительная десятичная сумма без экспоненты и разделителей групп
methodProfileIdID!даПрофиль способа, выбранный из результата playerWalletTopUpMethods
payerCountryStringнетДвухбуквенный код страны, например RU

Результат​

PlayerWalletTopUpPreparation содержит:

ПолеТипОписание
checkoutIdID!Идентификатор пользовательского сценария, который передаётся в запуск
intentPlayerWalletTopUpIntent!Созданное намерение и сумма назначения
methods[PlayerWalletTopUpMethod!]!Выбранный способ и его расчёт; после успешной подготовки список содержит один элемент

Каждый PlayerWalletTopUpMoney содержит атомарные units, код code, точность scale и готовое десятичное представление decimal. Денежные значения следует отображать из decimal, не преобразуя их через float.

Пример обмена​

Запрос
documentId: preparePlayerWalletTopUp
{
"documentId": "preparePlayerWalletTopUp",
"variables": {
"input": {
"requestId": "01910000-0000-7000-8000-000000000001",
"amount": "10.00",
"methodProfileId": "01910000-0000-7000-8000-000000000003",
"payerCountry": "RU"
}
}
}
Ответ
200 OK
{
"data": {
"preparePlayerWalletTopUp": {
"checkoutId": "01910000-0000-7000-8000-000000000001",
"intent": {
"id": "01910000-0000-7000-8000-000000000002",
"status": "OPEN",
"destinationAmount": {
"units": "1000",
"code": "ELX",
"scale": 2,
"decimal": "10.00"
},
"createdAt": "2026-08-29T10:00:00.000000Z",
"expiresAt": "2026-08-29T10:15:00.000000Z",
"completedAt": null
},
"methods": [
{
"methodProfileId": "01910000-0000-7000-8000-000000000003",
"methodCode": "BANK_CARD",
"displayName": "Банковская карта",
"iconAssetId": "payment-method-card",
"quote": {
"id": "01910000-0000-7000-8000-000000000004",
"sequence": 1,
"expiresAt": "2026-08-29T10:10:00.000000Z",
"paymentAmount": {
"units": "1030",
"code": "USD",
"scale": 2,
"decimal": "10.30"
},
"destinationAmount": {
"units": "1000",
"code": "ELX",
"scale": 2,
"decimal": "10.00"
},
"payerFee": {
"units": "30",
"code": "USD",
"scale": 2,
"decimal": "0.30"
},
"conversion": {
"numerator": "1",
"denominator": "1",
"roundingMode": "HALF_UP"
},
"fees": [
{
"kind": "FIXED",
"amount": {
"units": "30",
"code": "USD",
"scale": 2,
"decimal": "0.30"
}
}
],
"funding": {
"baseAmount": {
"units": "1000",
"code": "ELX",
"scale": 2,
"decimal": "10.00"
},
"bonusAmount": {
"units": "300",
"code": "ELX",
"scale": 2,
"decimal": "3.00"
},
"totalAmount": {
"units": "1300",
"code": "ELX",
"scale": 2,
"decimal": "13.00"
},
"components": [
{
"source": "PAYMENT_PROMOTION",
"amount": {
"units": "100",
"code": "ELX",
"scale": 2,
"decimal": "1.00"
},
"percentage": 10,
"decidedAt": "2026-08-29T10:00:00.000000Z",
"validUntil": "2026-08-29T10:10:00.000000Z",
"grantLifetimeSeconds": null
},
{
"source": "LOYALTY",
"amount": {
"units": "200",
"code": "ELX",
"scale": 2,
"decimal": "2.00"
},
"percentage": 20,
"decidedAt": "2026-08-29T10:00:00.000000Z",
"validUntil": null,
"grantLifetimeSeconds": 86400
}
]
}
}
}
]
}
}
}

PAYMENT_PROMOTION и LOYALTY показываются отдельными строками. Расчёт фиксируется внутри поля quote: клиент не складывает проценты самостоятельно и не заменяет totalAmount собственным значением.

Запуск оплаты​

MutationdocumentId: startPlayerWalletTopUpauth: Bearer session

startPlayerWalletTopUp​

Входные данные​

ПолеТипОписание
requestIdID!Новый UUIDv7 запуска; обеспечивает идемпотентный повтор
checkoutIdID!Значение из подготовки
methodProfileIdID!Выбранный способ из methods
quoteIdID!Идентификатор расчёта выбранного способа

Повтор запуска с теми же четырьмя значениями безопасен. Повтор requestId с другим набором значений завершается конфликтом.

Пример обмена​

Запрос
documentId: startPlayerWalletTopUp
{
"documentId": "startPlayerWalletTopUp",
"variables": {
"input": {
"requestId": "01910000-0000-7000-8000-000000000010",
"checkoutId": "01910000-0000-7000-8000-000000000001",
"methodProfileId": "01910000-0000-7000-8000-000000000003",
"quoteId": "01910000-0000-7000-8000-000000000004"
}
}
}
Ответ
200 OK
{
"data": {
"startPlayerWalletTopUp": {
"checkoutId": "01910000-0000-7000-8000-000000000001",
"intent": {
"id": "01910000-0000-7000-8000-000000000002",
"status": "PROCESSING",
"destinationAmount": {
"units": "1000",
"code": "ELX",
"scale": 2,
"decimal": "10.00"
},
"createdAt": "2026-08-29T10:00:00.000000Z",
"expiresAt": "2026-08-29T10:15:00.000000Z",
"completedAt": null
},
"attempt": {
"id": "01910000-0000-7000-8000-000000000005",
"status": "REQUIRES_CUSTOMER_ACTION",
"createdAt": "2026-08-29T10:00:01.000000Z",
"expiresAt": "2026-08-29T10:15:00.000000Z"
},
"action": {
"kind": "REDIRECT",
"expiresAt": "2026-08-29T10:15:00.000000Z",
"redirect": {
"url": "https://checkout.example.test/pay/123"
},
"formPost": null,
"qrCode": null,
"deepLink": null,
"wait": null
}
}
}
}

Действия клиента​

kindЗаполненное полеДействие
REDIRECTredirect.urlПерейти на HTTPS-страницу оплаты
FORM_POSTformPost.url, formPost.fieldsСоздать и немедленно отправить POST-форму
QR_CODEqrCode.payload, необязательное imageUrlПоказать QR-код; payload остаётся источником данных
DEEP_LINKdeepLink.urlПоказать QR-код и кнопку открытия приложения
WAITwait.recommendedPollAfterSecondsПовторить тот же запуск после указанной задержки

Заполненным бывает только объект, соответствующий kind. action: null означает, что внешнее действие больше не требуется; итог определяется по intent.status.

Гостевая подготовка пополнения​

MutationdocumentId: prepareGuestPlayerWalletTopUpauth: public

prepareGuestPlayerWalletTopUp​

Гостевая подготовка доступна без входа в кабинет. Укажите email получателя, сумму и выбранный способ оплаты.

Входные данные​

ПолеТипОбязательноеОписание
requestIdID!даНовый UUIDv7 подготовки; повтор с теми же данными возвращает прежний результат
recipientEmailString!даEmail аккаунта-получателя
amountString!даПоложительная десятичная сумма без экспоненты и разделителей групп
methodProfileIdID!даПрофиль способа из playerWalletTopUpMethods
payerCountryStringнетДвухбуквенный код страны, например RU

Результат​

Возвращается тот же PlayerWalletTopUpPreparation, что и для авторизованной подготовки: checkoutId, намерение и один рассчитанный способ с полем quote.

Пример обмена​

Запрос
documentId: prepareGuestPlayerWalletTopUp
{
"documentId": "prepareGuestPlayerWalletTopUp",
"variables": {
"input": {
"requestId": "01910000-0000-7000-8000-000000000011",
"recipientEmail": "[email protected]",
"amount": "10.00",
"methodProfileId": "01910000-0000-7000-8000-000000000003",
"payerCountry": "RU"
}
}
}
Ответ
200 OK
{
"data": {
"prepareGuestPlayerWalletTopUp": {
"checkoutId": "01910000-0000-7000-8000-000000000011",
"intent": {
"id": "01910000-0000-7000-8000-000000000012",
"status": "OPEN",
"destinationAmount": {
"units": "1000",
"code": "ELX",
"scale": 2,
"decimal": "10.00"
},
"expiresAt": "2026-08-29T10:15:00.000000Z"
},
"methods": [
{
"methodProfileId": "01910000-0000-7000-8000-000000000003",
"methodCode": "BANK_CARD",
"displayName": "Банковская карта",
"iconAssetId": "payment-method-card",
"quote": {
"id": "01910000-0000-7000-8000-000000000013",
"sequence": 1,
"expiresAt": "2026-08-29T10:10:00.000000Z",
"paymentAmount": {
"units": "1030",
"code": "USD",
"scale": 2,
"decimal": "10.30"
},
"destinationAmount": {
"units": "1000",
"code": "ELX",
"scale": 2,
"decimal": "10.00"
},
"payerFee": {
"units": "30",
"code": "USD",
"scale": 2,
"decimal": "0.30"
},
"funding": null
}
}
]
}
}
}

Если пополнение для получателя недоступно, возвращается TOP_UP_RECIPIENT_UNAVAILABLE. Если нет подходящего способа оплаты, возвращается TOP_UP_METHODS_UNAVAILABLE.

Запуск гостевой оплаты​

MutationdocumentId: startGuestPlayerWalletTopUpauth: public

startGuestPlayerWalletTopUp​

Запускает гостевую оплату с получателем, способом и действующим расчётом из подготовки. Передайте их без изменений.

Входные данные​

ПолеТипОбязательноеОписание
requestIdID!даНовый UUIDv7 запуска
checkoutIdID!даЗначение из гостевой подготовки
recipientEmailString!даТот же email получателя; сервер разрешает его заново
methodProfileIdID!даВыбранный способ из подготовки
quoteIdID!даИдентификатор расчёта выбранного способа

Результат и действия клиента​

Возвращается тот же PlayerWalletTopUpCheckout, что и для авторизованного запуска: состояние намерения, попытка и одно из действий REDIRECT, FORM_POST, QR_CODE, DEEP_LINK или WAIT. Описание полей действий приведено в разделе Действия клиента.

Пример обмена​

Запрос
documentId: startGuestPlayerWalletTopUp
{
"documentId": "startGuestPlayerWalletTopUp",
"variables": {
"input": {
"requestId": "01910000-0000-7000-8000-000000000014",
"checkoutId": "01910000-0000-7000-8000-000000000011",
"recipientEmail": "[email protected]",
"methodProfileId": "01910000-0000-7000-8000-000000000003",
"quoteId": "01910000-0000-7000-8000-000000000013"
}
}
}
Ответ
200 OK
{
"data": {
"startGuestPlayerWalletTopUp": {
"checkoutId": "01910000-0000-7000-8000-000000000011",
"intent": {
"id": "01910000-0000-7000-8000-000000000012",
"status": "PROCESSING",
"destinationAmount": {
"units": "1000",
"code": "ELX",
"scale": 2,
"decimal": "10.00"
},
"expiresAt": "2026-08-29T10:15:00.000000Z"
},
"attempt": {
"id": "01910000-0000-7000-8000-000000000015",
"status": "REQUIRES_CUSTOMER_ACTION",
"createdAt": "2026-08-29T10:00:01.000000Z",
"expiresAt": "2026-08-29T10:15:00.000000Z"
},
"action": {
"kind": "REDIRECT",
"expiresAt": "2026-08-29T10:15:00.000000Z",
"redirect": {
"url": "https://checkout.example.test/pay/123"
},
"formPost": null,
"qrCode": null,
"deepLink": null,
"wait": null
}
}
}
}

Для гостевой оплаты используйте результат запуска; отдельной операции гостевой истории нет.

История платежей​

QuerydocumentId: playerPaymentHistoryauth: Bearer session

playerPaymentHistory​

Возвращает платежи текущего игрока с курсорной пагинацией. Фильтр statuses необязателен; пустой список означает все состояния.

ПолеТипОбязательноеОписание
firstInt!даРазмер страницы от 1 до 100
afterIDнетendCursor предыдущей страницы
statuses[PlayerPaymentStatus!]нетСостояния для фильтрации
Запрос
documentId: playerPaymentHistory
{
"documentId": "playerPaymentHistory",
"variables": {
"first": 20,
"after": null,
"statuses": [
"PROCESSING",
"SETTLED"
]
}
}
Ответ
200 OK
{
"data": {
"playerPaymentHistory": {
"items": [
{
"id": "01910000-0000-7000-8000-000000000002",
"purpose": "PLAYER_WALLET_CREDIT",
"status": "SETTLED",
"destinationAmount": {
"units": "1000",
"code": "ELX",
"scale": 2,
"decimal": "10.00"
},
"quotedAmount": {
"units": "1030",
"code": "USD",
"scale": 2,
"decimal": "10.30"
},
"settledAmount": {
"units": "1030",
"code": "USD",
"scale": 2,
"decimal": "10.30"
},
"method": {
"code": "card",
"displayName": "Банковская карта",
"iconAssetId": "payment-method-card"
},
"description": "Пополнение баланса",
"createdAt": "2026-08-29T10:00:00.000000Z",
"expiresAt": "2026-08-29T10:15:00.000000Z",
"completedAt": "2026-08-29T10:02:10.000000Z"
}
],
"pageInfo": {
"endCursor": "01910000-0000-7000-8000-000000000002",
"hasNextPage": false
}
}
}
}

Один платёж​

QuerydocumentId: playerPaymentauth: Bearer session

playerPayment​

Принимает публичный paymentId из истории и возвращает тот же снимок платежа. Если платёж не найден, возвращается PLAYER_PAYMENT_NOT_FOUND.

Запрос
documentId: playerPayment
{
"documentId": "playerPayment",
"variables": {
"paymentId": "01910000-0000-7000-8000-000000000002"
}
}
Ответ
200 OK
{
"data": {
"playerPayment": {
"id": "01910000-0000-7000-8000-000000000002",
"purpose": "PLAYER_WALLET_CREDIT",
"status": "SETTLED",
"destinationAmount": {
"units": "1000",
"code": "ELX",
"scale": 2,
"decimal": "10.00"
},
"quotedAmount": {
"units": "1030",
"code": "USD",
"scale": 2,
"decimal": "10.30"
},
"settledAmount": {
"units": "1030",
"code": "USD",
"scale": 2,
"decimal": "10.30"
},
"method": {
"code": "card",
"displayName": "Банковская карта",
"iconAssetId": "payment-method-card"
},
"description": "Пополнение баланса",
"createdAt": "2026-08-29T10:00:00.000000Z",
"expiresAt": "2026-08-29T10:15:00.000000Z",
"completedAt": "2026-08-29T10:02:10.000000Z"
}
}
}

Состояния​

PlayerWalletTopUpIntentStatus: OPEN, PROCESSING, SETTLED, CANCELLED, EXPIRED.

PlayerWalletTopUpAttemptStatus: CREATED, REQUIRES_CUSTOMER_ACTION, PENDING_PROVIDER, AUTHORIZED, CAPTURED, DECLINED, CANCELLED, EXPIRED, REVIEW_REQUIRED.

Истёкший расчёт не запускается. Нужно снова вызвать подготовку и показать новый результат. Успешный callback зачисляет средства один раз; повтор callback не создаёт второе начисление.

Ошибки​

КодЗначение для клиента
TOP_UP_INVALID_REQUESTНеверный формат входных данных
TOP_UP_INVALID_AMOUNTСумма вне допустимых границ
TOP_UP_ORIGIN_NOT_ALLOWEDТекущий Origin не зарегистрирован для проекта
TOP_UP_RECIPIENT_UNAVAILABLEПолучатель не найден, заблокирован или не может принять пополнение
TOP_UP_MERCHANT_UNAVAILABLEПополнение проекта выключено или не настроено
TOP_UP_METHODS_UNAVAILABLEДля суммы и контекста нет доступного способа оплаты
TOP_UP_REFRESH_REQUIREDНамерение, способ или расчёт устарели; подготовку нужно повторить
TOP_UP_SCOPE_UNAVAILABLEНе удалось определить назначение баланса
TOP_UP_CONFLICTИдемпотентный идентификатор повторён с другими данными
TOP_UP_RATE_LIMITEDПревышен лимит; extensions.retryAfterSeconds задаёт ожидание
TOP_UP_UNAVAILABLEОперация временно недоступна

При истечении расчёта выполните подготовку заново. При временной ошибке сохраните параметры исходного запроса для повтора.