Wallet
Назначение Wallet
Кошелек (Wallet) используется для начисления и списания валюты лояльности (бонусные рубли, баллы и т.д.).
Ключевые функции:
- Хранит баланс клиента в различных валютах лояльности (бонусные баллы, кэшбэк-рубли, мили и т.д.)
- Обеспечивает функционал начисления и списания средств с кошелька клиента
- Поддерживает блокировку средств (поле
on_hold)
Важно: Созданный кошелек не привязан к окружению и может использоваться как универсальный в рамках нескольких программ лояльности.
Примеры использования
- Начисление баллов за покупки
- Списание внутриигровой валюты для покупки предметов в игровом магазине
Покупка item-а валютой кошелька
Важно: Валютой из кошелька можно покупать сущность item, в настройках которой указывается сумма и валюта списания. После успешной покупки у пользователя появляется купленная сущность и вычитается сумма из кошелька.
История транзакций
Каждая операция с кошельком (начисление, списание, блокировка) фиксируется в истории транзакций. Это позволяет:
- Отслеживать движение средств клиента
- Анализировать активность (например, частые покупки за баллы)
- Формировать отчеты
- Урегулировать спорные ситуации (например, ошибочное списание)
Справочник валют (global.wallet)
Таблица: global.wallet
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
id | string(50) | Да | Уникальный идентификатор валюты (например: "bonus-points", "gold-coins") |
title | string(50) | Нет | Название валюты для отображения |
description | string(250) | Нет | Описание назначения валюты |
is_default | boolean | Нет | Является ли валюта дефолтной (доступна всем клиентам автоматически) |
balance | float | Да | Начальный баланс для дефолтных валют (по умолчанию 0.0) |
on_hold | float | Нет | Начальное количество зарезервированных средств (по умолчанию 0.0) |
status | string(50) | Нет | Статус валюты: "active" или "blocked" |
creator | string(250) | Нет | Логин пользователя, создавшего валюту |
timestamp | bigint | Да | Временная метка создания/обновления (Unix timestamp) |
datetime | datetime | Да | Дата и время создания/обновления |
Пример записи:
{
"id": "bonus-points",
"title": "Бонусные баллы",
"description": "Основная валюта программы лояльности",
"is_default": true,
"balance": 100.0,
"on_hold": 0.0,
"status": "active",
"creator": "admin",
"datetime": "2024-01-15 10:30:00"
}Балансы клиентов (clients.wallet)
Таблица: clients.wallet
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
num | bigint | Да (PK) | Автоинкрементный идентификатор записи (служебное поле) |
client_id | string(50) | Да | Идентификатор клиента (CTN, номер телефона и т.д.) |
id | string(50) | Да | Идентификатор валюты (FK на global.wallet.id) |
balance | float | Да | Текущий баланс клиента по данной валюте |
on_hold | float | Нет | Количество зарезервированных средств |
status | string(50) | Да | Статус валюты для клиента: "active" или "blocked" |
timestamp | bigint | Да | Временная метка последнего обновления |
datetime | datetime | Да | Дата и время последнего обновления |
Индексы:
wallet_id_indexна полеidwallet_client_id_indexна полеclient_id
Пример записи:
{
"num": 12345,
"client_id": "9031112233",
"id": "bonus-points",
"balance": 350.5,
"on_hold": 0.0,
"status": "active",
"datetime": "2024-01-20 15:45:00"
}История транзакций (history.transactions)
Таблица: history.transactions
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
transaction_id | string(50) | Да (PK) | Уникальный идентификатор транзакции |
client_id | string(50) | Да | Идентификатор клиента |
entity_id | string(50) | Нет | Идентификатор игрового профиля |
environment_id | string(50) | Нет | Идентификатор окружения (проекта) |
id | string(50) | Да | Идентификатор валюты |
target | string(50) | Нет | ID объекта транзакции (например, ID задания или предмета) |
amount | float | Нет | Сумма операции (положительная для начислений, отрицательная для списаний) |
balance | float | Нет | Баланс после совершения операции |
type | string(250) | Нет | Тип операции: "income" (начисление), "expense" (списание), "hold" (резервирование) |
status | string(250) | Нет | Статус: "pending" (в процессе), "completed" (завершена), "failed" (ошибка) |
source_type | string(250) | Нет | Тип источника: "game", "manual", "system", "auto_expiring" |
source_code | string(250) | Нет | Код источника (например, environment_id или ID кампании) |
content | jsonb | Нет | Дополнительная информация (объект с произвольными полями: title, description, details) |
timestamp | bigint | Да | Временная метка транзакции |
datetime | datetime | Да | Дата и время транзакции |
Индексы:
history_transactions_id_indexна полеidhistory_transactions_client_id_indexна полеclient_id
Пример записи:
{
"transaction_id": "txn_abc123xyz",
"client_id": "9031112233",
"entity_id": "ent_xyz789",
"environment_id": "game-1",
"id": "bonus-points",
"target": "task-complete-profile",
"amount": 50.0,
"balance": 400.5,
"type": "income",
"status": "completed",
"source_type": "game",
"source_code": "game-1",
"content": {
"title": "Выполнение задания",
"description": "Заполнение профиля",
"details": "Задание: task-complete-profile"
},
"datetime": "2024-01-20 15:45:30"
}История резервирований (history.holds)
Таблица: history.holds
Аналогична структуре history.transactions, используется для отслеживания операций резервирования средств (холдов).
Internal API
Префикс: /v1/internal/wallet
Аутентификация: Basic Authentication
Целевая аудитория: Игровые клиенты, системы интеграции, кампейнеры
1. Получить весь кошелек клиента
Endpoint: GET /v1/internal/wallet/clients/{client_id}
Описание: Возвращает все доступные валюты клиента (персональные + дефолтные).
Параметры пути:
client_id(string, обязательный) - ID клиента
Заголовки:
Authorization(обязательный) - Basic Auth (формат:Basic base64(login:password))
Пример запроса:
GET /v1/internal/wallet/clients/9031112233
Authorization: Basic YWRtaW46cGFzc3dvcmQ=Пример ответа (200 OK):
{
"wallet": [
{
"client_id": "9031112233",
"id": "bonus-points",
"balance": 350.5,
"on_hold": 0.0,
"status": "active",
"title": "Бонусные баллы",
"description": "Основная валюта программы лояльности",
"creator": "admin"
},
{
"client_id": "9031112233",
"id": "premium-keys",
"balance": 3.0,
"on_hold": 0.0,
"status": "active",
"title": "Премиум ключи",
"description": "Ключи для открытия премиум сундуков",
"creator": "admin"
}
]
}2. Получить баланс конкретной валюты
Endpoint: GET /v1/internal/wallet/currency/{client_id}/{id}
Описание: Возвращает баланс клиента по конкретной валюте.
Параметры пути:
client_id(string, обязательный) - ID клиентаid(string, обязательный) - ID валюты
Заголовки:
Authorization(обязательный) - Basic Auth
Пример запроса:
GET /v1/internal/wallet/currency/9031112233/bonus-points
Authorization: Basic YWRtaW46cGFzc3dvcmQ=Пример ответа (200 OK) - персональная валюта:
{
"client_id": "9031112233",
"id": "bonus-points",
"balance": 350.5,
"on_hold": 0.0,
"status": "active",
"title": "Бонусные баллы",
"description": "Основная валюта программы лояльности",
"creator": "admin"
}Пример ответа (200 OK) - дефолтная валюта:
Если у клиента нет персональной записи, но валюта является дефолтной:
{
"client_id": "9031112233",
"id": "premium-keys",
"balance": 3.0,
"on_hold": 0.0,
"status": "active",
"title": "Премиум ключи",
"description": "Ключи для открытия премиум сундуков",
"creator": "admin"
}Ответ (400 Bad Request):
Если валюта не существует и не является дефолтной:
{}Ответ (403 Forbidden):
Если валюта заблокирована для клиента:
{}3. Начислить или списать валюту (транзакция)
Endpoint: POST /v1/internal/wallet/transaction
Описание: Основной метод для начисления или списания валюты. Создает транзакцию в истории.
Заголовки:
Authorization(обязательный) - Basic AuthContent-Type(обязательный) -application/json
Тело запроса:
{
"client_id": "9031112233",
"id": "bonus-points",
"amount": 50.0,
"target": "task-1",
"environment_id": "game-1",
"source_type": "game",
"source_code": "game-1",
"expired_at": "2024-12-31 23:59:59",
"content": {
"title": "Выполнение задания",
"description": "Заполнение профиля"
}
}Поля:
client_id(string, обязательный) - ID клиентаid(string, обязательный) - ID валютыamount(number, обязательный) - Сумма транзакции со знаком: положительное для начисления, отрицательное для списанияtarget(string, необязательный) - ID объекта (например, ID задания)environment_id(string, необязательный) - ID окруженияsource_type(string, необязательный) - Тип источника: "game", "manual", "system"source_code(string, необязательный) - Код источникаexpired_at(string, необязательный) - Дата истечения срока действия начисленияcontent(object, необязательный) - Дополнительная информация
Пример запроса (начисление):
POST /v1/internal/wallet/transaction
Authorization: Basic YWRtaW46cGFzc3dvcmQ=
Content-Type: application/json
{
"client_id": "9031112233",
"id": "bonus-points",
"amount": 50.0,
"target": "task-complete-profile",
"environment_id": "game-1",
"source_type": "game",
"source_code": "game-1",
"content": {
"title": "Выполнение задания",
"description": "Заполнение профиля"
}
}Пример ответа (200 OK):
{
"transaction_id": "txn_abc123xyz",
"client_id": "9031112233",
"target": "task-complete-profile",
"transaction_date": "2024-01-20 16:30:00",
"expired_at": null,
"status": "completed",
"type": "income",
"source_type": "game",
"source_code": "game-1",
"currency": "bonus-points",
"amount": 50.0,
"balance": 400.5,
"content": {
"title": "Выполнение задания",
"description": "Заполнение профиля"
}
}Пример запроса (списание):
POST /v1/internal/wallet/transaction
Authorization: Basic YWRtaW46cGFzc3dvcmQ=
Content-Type: application/json
{
"client_id": "9031112233",
"id": "bonus-points",
"amount": -100.0,
"target": "item-sword-001",
"environment_id": "game-1",
"source_type": "game",
"source_code": "game-1",
"content": {
"title": "Покупка предмета",
"description": "Меч воина"
}
}Пример ответа (200 OK):
{
"transaction_id": "txn_def456uvw",
"client_id": "9031112233",
"target": "item-sword-001",
"transaction_date": "2024-01-20 16:35:00",
"status": "completed",
"type": "expense",
"source_type": "game",
"source_code": "game-1",
"currency": "bonus-points",
"amount": -100.0,
"balance": 300.5,
"content": {
"title": "Покупка предмета",
"description": "Меч воина"
}
}Ответ (403 Forbidden):
Если кошелек клиента заблокирован:
{}4. Получить историю транзакций
Endpoint: POST /v1/internal/wallet/transactions
Описание: Возвращает историю транзакций по конкретной валюте клиента с поддержкой пагинации и фильтрации.
Заголовки:
Authorization(обязательный) - Basic AuthContent-Type(обязательный) -application/json
Тело запроса:
{
"client_id": "9031112233",
"id": "bonus-points",
"limit": 20,
"offset": 0,
"type": "income",
"status": "completed",
"datetime": ["2024-01-01 00:00:00", "2024-01-31 23:59:59"]
}Поля:
client_id(string, обязательный) - ID клиентаid(string, обязательный) - ID валютыlimit(number, необязательный) - Количество записей на странице (0 = все)offset(number, необязательный) - Смещение для пагинации (по умолчанию 0)type(string, необязательный) - Фильтр по типу: "income" или "expense"status(string, необязательный) - Фильтр по статусу: "pending", "completed", "failed"datetime(array[string], необязательный) - Диапазон дат в формате["начало", "конец"]
Варианты фильтрации по датам:
// Транзакции между двумя датами
"datetime": ["2024-01-01 00:00:00", "2024-01-31 23:59:59"]
// Транзакции после указанной даты
"datetime": ["2024-01-15 00:00:00", ""]
// Транзакции до указанной даты
"datetime": ["", "2024-01-31 23:59:59"]Пример запроса:
POST /v1/internal/wallet/transactions
Authorization: Basic YWRtaW46cGFzc3dvcmQ=
Content-Type: application/json
{
"client_id": "9031112233",
"id": "bonus-points",
"limit": 10,
"offset": 0,
"type": "income"
}Пример ответа (200 OK):
{
"count": 42,
"transactions": [
{
"transaction_id": "txn_abc123xyz",
"client_id": "9031112233",
"entity_id": "ent_xyz789",
"environment_id": "game-1",
"id": "bonus-points",
"target": "task-complete-profile",
"amount": 50.0,
"balance": 400.5,
"type": "income",
"status": "completed",
"source_type": "game",
"source_code": "game-1",
"content": {
"title": "Выполнение задания",
"description": "Заполнение профиля"
},
"datetime": "2024-01-20 16:30:00"
},
{
"transaction_id": "txn_ghi789klm",
"client_id": "9031112233",
"entity_id": "ent_xyz789",
"environment_id": "game-1",
"id": "bonus-points",
"target": "daily-login",
"amount": 10.0,
"balance": 350.5,
"type": "income",
"status": "completed",
"source_type": "system",
"source_code": "auto",
"content": {
"title": "Ежедневный вход",
"description": "Бонус за вход в игру"
},
"datetime": "2024-01-20 10:00:00"
}
]
}5. Блокировка кошелька
Endpoint: POST /v1/internal/wallet/block
Описание: Блокирует весь кошелек клиента (все валюты). После блокировки операции с кошельком будут недоступны.
Заголовки:
Authorization(обязательный) - Basic AuthContent-Type(обязательный) -application/json
Тело запроса:
{
"client_id": "9031112233"
}Пример запроса:
POST /v1/internal/wallet/block
Authorization: Basic YWRtaW46cGFzc3dvcmQ=
Content-Type: application/json
{
"client_id": "9031112233"
}Пример ответа (200 OK):
{
"status": "blocked",
"client_id": "9031112233"
}6. Разблокировка кошелька
Endpoint: POST /v1/internal/wallet/unblock
Описание: Разблокирует кошелек клиента (все валюты).
Заголовки:
Authorization(обязательный) - Basic AuthContent-Type(обязательный) -application/json
Тело запроса:
{
"client_id": "9031112233"
}Пример запроса:
POST /v1/internal/wallet/unblock
Authorization: Basic YWRтаW46cGFzc3dvcmQ=
Content-Type: application/json
{
"client_id": "9031112233"
}Пример ответа (200 OK):
{
"status": "active",
"client_id": "9031112233"
}7. Покупка предмета за валюту
Endpoint: POST /v1/internal/wallet/purchase
Описание: Проводит покупку предмета (Item) за валюту из кошелька. Метод поддерживает покупку обычных предметов и сундуков с призами.
Заголовки:
Authorization(обязательный) - Basic AuthContent-Type(обязательный) -application/json
Тело запроса:
{
"client_id": "9031112233",
"id": "item-sword-001",
"environment_id": "game-1"
}Поля:
client_id(string, обязательный) - ID клиентаid(string, обязательный) - ID предмета для покупкиenvironment_id(string, обязательный) - ID окружения
Пример запроса:
POST /v1/internal/wallet/purchase
Authorization: Basic YWRtaW46cGFzc3dvcmQ=
Content-Type: application/json
{
"client_id": "9031112233",
"id": "item-sword-001",
"environment_id": "game-1"
}Пример ответа (200 OK) - обычный предмет:
{
"transaction_id": "txn_purchase_001"
}Пример ответа (200 OK) - сундук с призом:
{
"transaction_id": "txn_purchase_002",
"client_id": "9031112233",
"entity_id": "ent_xyz789",
"transaction_date": "2024-01-20 17:00:00",
"id": "treasure-chest-001",
"status": "completed",
"type": "expense",
"source_type": "game",
"source_code": "game-1",
"currency": "bonus-points",
"amount": -200.0,
"balance": 200.5,
"content": {
"id": "reward-gold-500",
"unique_id": "reward_unique_123",
"title": "500 золотых монет",
"description": "Выигрыш из сундука",
"entity_id": "ent_xyz789",
"client_id": "9031112233"
}
}Ответ (422 Unprocessable Entity) - недостаточно средств:
{
"status": "Недостаточно средств",
"reason": "Недостаточно средств",
"balance": 100.5,
"price": 200.0
}Ответ (500 Internal Server Error) - предмет недоступен:
{
"status": "Покупка невозможна",
"is_purchased": false,
"is_locked": false,
"is_multiple_purchases": false
}Ответ (403 Forbidden) - кошелек заблокирован:
{}Management API
Префикс: /v1/management/wallet
Аутентификация: Session-based (cookie: sessionId)
Целевая аудитория: Администраторы системы
1. Получить список всех валют
Endpoint: GET /v1/management/wallet
Описание: Возвращает список всех созданных валют в справочнике.
Параметры запроса:
sessionId(cookie, обязательный) - Идентификатор сессии
Пример запроса:
GET /v1/management/wallet
Cookie: sessionId=AGK31XwAx1fS49gWПример ответа (200 OK):
{
"wallet": [
{
"id": "bonus-points",
"title": "Бонусные баллы",
"description": "Основная валюта программы лояльности",
"is_default": true,
"balance": 100.0,
"on_hold": 0.0,
"status": "active",
"creator": "admin",
"datetime": "2024-01-15 10:30:00"
},
{
"id": "gold-coins",
"title": "Золотые монеты",
"description": "Премиум валюта",
"is_default": false,
"balance": 0.0,
"on_hold": 0.0,
"status": "active",
"creator": "admin",
"datetime": "2024-01-16 12:00:00"
}
]
}2. Получить валюту по ID
Endpoint: GET /v1/management/wallet/{id}
Описание: Возвращает информацию о конкретной валюте.
Параметры пути:
id(string, обязательный) - ID валюты
Параметры запроса:
sessionId(cookie, обязательный) - Идентификатор сессии
Пример запроса:
GET /v1/management/wallet/bonus-points
Cookie: sessionId=AGK31XwAx1fS49gWПример ответа (200 OK):
{
"id": "bonus-points",
"title": "Бонусные баллы",
"description": "Основная валюта программы лояльности",
"is_default": true,
"balance": 100.0,
"on_hold": 0.0,
"status": "active",
"creator": "admin",
"datetime": "2024-01-15 10:30:00"
}3. Создать новую валюту
Endpoint: POST /v1/management/wallet
Описание: Создает новую валюту в справочнике.
Параметры запроса:
sessionId(cookie, обязательный) - Идентификатор сессии
Тело запроса:
{
"id": "premium-keys",
"title": "Премиум ключи",
"description": "Ключи для открытия премиум сундуков",
"is_default": true,
"balance": 3.0,
"on_hold": 0.0,
"status": "active"
}Обязательные поля:
id- уникальный идентификатор валюты
Пример запроса:
POST /v1/management/wallet
Cookie: sessionId=AGK31XwAx1fS49gW
Content-Type: application/json
{
"id": "premium-keys",
"title": "Премиум ключи",
"description": "Ключи для открытия премиум сундуков",
"is_default": true,
"balance": 3.0
}Пример ответа (200 OK):
{
"id": "premium-keys",
"title": "Премиум ключи",
"description": "Ключи для открытия премиум сундуков",
"is_default": true,
"balance": 3.0,
"on_hold": 0.0,
"status": "active",
"creator": "admin",
"datetime": "2024-01-20 16:00:00"
}4. Обновить валюту
Endpoint: PUT /v1/management/wallet
Описание: Обновляет существующую валюту в справочнике.
Параметры запроса:
sessionId(cookie, обязательный) - Идентификатор сессии
Тело запроса:
{
"id": "bonus-points",
"title": "Бонусные баллы (обновлено)",
"description": "Основная валюта программы лояльности с новым описанием",
"is_default": true,
"balance": 150.0
}Пример ответа (200 OK):
{
"id": "bonus-points",
"title": "Бонусные баллы (обновлено)",
"description": "Основная валюта программы лояльности с новым описанием",
"is_default": true,
"balance": 150.0,
"on_hold": 0.0,
"status": "active",
"creator": "admin",
"datetime": "2024-01-20 16:10:00"
}5. Удалить валюту
Endpoint: DELETE /v1/management/wallet/{id}
Описание: Удаляет валюту из справочника.
⚠️ Внимание: Удаление валюты из справочника не удаляет балансы клиентов. Будьте осторожны!
Параметры пути:
id(string, обязательный) - ID валюты
Параметры запроса:
sessionId(cookie, обязательный) - Идентификатор сессии
Пример запроса:
DELETE /v1/management/wallet/premium-keys
Cookie: sessionId=AGK31XwAx1fS49gWПример ответа (200 OK):
{
"id": "premium-keys"
}6. Получить кошелек клиента
Endpoint: GET /v1/management/wallet/clients/{client_id}
Описание: Возвращает все валюты в кошельке конкретного клиента (включая дефолтные).
Параметры пути:
client_id(string, обязательный) - ID клиента
Параметры запроса:
sessionId(cookie, обязательный) - Идентификатор сессии
Пример запроса:
GET /v1/management/wallet/clients/9031112233
Cookie: sessionId=AGK31XwAx1fS49gWПример ответа (200 OK):
{
"wallet": [
{
"client_id": "9031112233",
"id": "bonus-points",
"balance": 350.5,
"on_hold": 0.0,
"status": "active",
"title": "Бонусные баллы",
"description": "Основная валюта программы лояльности",
"datetime": "2024-01-20 15:45:00"
},
{
"client_id": "9031112233",
"id": "premium-keys",
"balance": 3.0,
"on_hold": 0.0,
"status": "active",
"title": "Премиум ключи",
"description": "Ключи для открытия премиум сундуков",
"datetime": "2024-01-20 16:00:00"
}
]
}7. Начислить или списать валюту вручную
Endpoint: POST /v1/management/wallet/clients
Описание: Позволяет администратору вручную начислить или списать валюту клиенту.
Параметры запроса:
sessionId(cookie, обязательный) - Идентификатор сессии
Тело запроса:
{
"client_id": "9031112233",
"id": "bonus-points",
"value": 50.0
}Поля:
client_id(string, обязательный) - ID клиентаid(string, обязательный) - ID валютыvalue(number, обязательный) - Размерность операции со знаком: положительное число для начисления, отрицательное для списания
Пример запроса (начисление):
POST /v1/management/wallet/clients
Cookie: sessionId=AGK31XwAx1fS49gW
Content-Type: application/json
{
"client_id": "9031112233",
"id": "bonus-points",
"value": 100.0
}Пример ответа (200 OK):
{
"currency": "bonus-points",
"value": 100.0,
"balance": 450.5
}Пример запроса (списание):
POST /v1/management/wallet/clients
Cookie: sessionId=AGK31XwAx1fS49gW
Content-Type: application/json
{
"client_id": "9031112233",
"id": "bonus-points",
"value": -50.0
}Пример ответа (200 OK):
{
"currency": "bonus-points",
"value": -50.0,
"balance": 400.5
}8. Удалить валюту из кошелька клиента
Endpoint: DELETE /v1/management/wallet/clients/{client_id}/{id}
Описание: Удаляет персональную запись валюты из кошелька клиента.
Параметры пути:
client_id(string, обязательный) - ID клиентаid(string, обязательный) - ID валюты
Параметры запроса:
sessionId(cookie, обязательный) - Идентификатор сессии
Пример запроса:
DELETE /v1/management/wallet/clients/9031112233/bonus-points
Cookie: sessionId=AGK31XwAx1fS49gWПример ответа (200 OK):
{
"id": "bonus-points"
}Partners API
Префикс: /v1/partners/wallet
Описание: Partners API полностью дублирует Internal API с другим префиксом URL. Используется теми же роутерами, что и Internal API.
Аутентификация: Basic Authentication (аналогично Internal API)
Доступные endpoints:
Все endpoints из Internal API доступны с префиксом /v1/partners/wallet:
GET /v1/partners/wallet/clients/{client_id}GET /v1/partners/wallet/currency/{client_id}/{id}POST /v1/partners/wallet/transactionPOST /v1/partners/wallet/transactionsPOST /v1/partners/wallet/blockPOST /v1/partners/wallet/unblockPOST /v1/partners/wallet/purchase
Параметры запросов и ответы полностью идентичны Internal API.