Разработчикам

API наград за голоса, готовый код для Java и PTS серверов

Игроки голосуют намного чаще, когда получают за это награду в игре. Подключите награды за голоса к Java или PTS серверу за 10–15 минут: проект поднимается в ТОПе месяца, а игроки получают предметы за каждый голос.

Быстрый старт

1

Получите Server ID и API key

Сервер должен быть в каталоге L2Servers.top. Напишите нам — пришлём ID, секретный ключ и ссылку на страницу голосования.

Связаться
2

Установите скрипт наград

Один PHP-файл для вашего сайта — Java и PTS в одном скрипте. Он получает наш подписанный запрос после каждого голоса и выдаёт предметы персонажу.

⬇ l2s-vote-reward.php
3

Проверьте и запускайте

Отправьте тестовый голос инструментом ниже, поставьте кнопку на сайт и в лаунчер. Мы отметим сервер значком 🎁 на странице голосования.

Открыть проверку
Страница голосованияhttps://l2servers.top/vote/{server}/
Лимит1 голос / 12 ч на IP и персонажа
ПодписьHMAC-SHA256
Сброс рейтинга1-е число месяца

Java серверы: L2J, L2J Mobius, aCis, L2Scripts, Lucera

Два способа — используйте один или оба:

A. Автоматическая награда (callback) — рекомендуется

  1. Загрузите l2s-vote-reward.php на сайт (PHP 7.2+ с pdo_mysql и доступом к БД игры).
  2. Укажите server_type = java, БД и режим выдачи:
    • custom_mail — L2J Mobius: предметы приходят почтой в игре, онлайн и оффлайн (General.ini → CustomMailManagerEnabled = True).
    • items_delayed — L2Scripts, Lucera, Rebellion, Overworld: предмет выдаётся при следующем входе.
    • sql — aCis и свои сборки: собственный INSERT/UPDATE (например, очки в донат-магазине).
  3. Откройте ?test=1&char=ВашПерсонаж — скрипт проверит подключение, таблицы и поиск персонажа.
  4. Пришлите нам callback URL:
https://your-site.com/l2s-vote-reward.php?user={username}&ip={ip}&time={time}&sig={sig}
'api_key' => 'YOUR_API_KEY', 'server_type' => 'java', 'db_dsn' => 'mysql:host=127.0.0.1;port=3306;dbname=l2jgs;charset=utf8mb4', 'db_user' => 'l2j', 'db_pass' => 'secret', 'mode' => 'custom_mail', 'items' => array( array( 57, 1000000 ), array( 1538, 1 ) ), // Adena + Blessed Scroll of Escape

B. Команда в игре .vote

Игрок голосует у нас и пишет .vote в игре. Сервер спрашивает наш API, голосовал ли персонаж (или IP) за последние 12 часов, и выдаёт награду один раз за голос. Сайт не нужен — только игровой сервер.

⬇ L2ServersVote.java (L2J Mobius)

Для aCis / L2Scripts / Lucera логика та же — поменяйте интерфейс voiced-команды, вызов выдачи предмета и место хранения последнего полученного голоса.

PTS серверы (C++, MSSQL)

На PTS обычно нельзя добавить команду как на Java, а писать предметы прямо в user_item, пока персонаж онлайн, небезопасно. Поэтому скрипт работает с PTS через базу — находит персонажа в lin2world.dbo.user_data и передаёт награду системе, которая уже есть на вашем сервере:

1. Выдача через экстендер У большинства PTS-экстендеров есть таблица выдачи предметов — предмет приходит при входе или по команде. Впишите её INSERT в custom_sql (имя таблицы зависит от экстендера).
2. Очки на вашем сайте Начисляйте очки на аккаунт в донат-магазине / личном кабинете (плейсхолдер :account) — игроки тратят их там. Игровой сервер менять не нужно.
3. Вручную (лог) mode = log: скрипт пишет, кто проголосовал, в l2s-votes.log, а ГМ выдаёт награды вручную. Подходит на первое время.

Пример настроек для PTS (в PHP нужен pdo_sqlsrv на Windows или pdo_dblib на Linux):

'api_key' => 'YOUR_API_KEY', 'server_type' => 'pts', 'db_dsn' => 'sqlsrv:Server=127.0.0.1,1433;Database=lin2world', 'db_user' => 'sa', 'db_pass' => 'secret', 'mode' => 'sql', 'items' => array( array( 57, 1000000 ) ), // 1) extender delivery table (check the name in your extender docs): 'custom_sql' => 'INSERT INTO ItemDelivery (char_id, item_id, item_amount) VALUES (:char_id, :item_id, :count)', // 2) or vote points on the website (separate DB connection): // 'custom_sql' => 'UPDATE site_accounts SET vote_points = vote_points + :count WHERE login = :account', // 'sql_dsn' => 'mysql:host=127.0.0.1;dbname=website;charset=utf8mb4',

PTS и команда .vote: если экстендер поддерживает свои команды или скрипты, он может вызывать тот же API, что и Java-пример (/api/vote-check?username=…) — логика та же.

Справочник API

Callback (мы вызываем вас)

После каждого принятого голоса отправляем один GET-запрос на ваш callback URL (таймаут 3 с, без повторов). Плейсхолдеры:

ПлейсхолдерЗначение
{username}Имя персонажа, введённое игроком (буквы, цифры, _ и -; может быть пустым)
{ip}IP голосующего
{time}Время голоса, Unix (UTC)
{sig}hex( HMAC-SHA256( username + "|" + ip + "|" + time, API_KEY ) )

Проверка подписи (готовый скрипт уже делает это и отклоняет старые и повторные запросы):

// PHP $expected = hash_hmac('sha256', $_GET['user'] . '|' . $_GET['ip'] . '|' . $_GET['time'], $apiKey); if (!hash_equals($expected, $_GET['sig']) || abs(time() - (int) $_GET['time']) > 600) { http_response_code(403); exit; } // Java Mac mac = Mac.getInstance("HmacSHA256"); mac.init(new SecretKeySpec(apiKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256")); String expected = HexFormat.of().formatHex(mac.doFinal((user + "|" + ip + "|" + time).getBytes(StandardCharsets.UTF_8)));

Проверка голоса (вы вызываете нас)

GET https://l2servers.top/api/vote-check?server=SERVER_ID&key=API_KEY&username=CharName GET https://l2servers.top/api/vote-check?server=SERVER_ID&key=API_KEY&ip=1.2.3.4
HTTPОтвет
200{"voted":true,"voted_at":"2026-09-25T10:15:00+00:00","next_vote_at":"2026-09-25T22:15:00+00:00"}
200{"voted":false,"voted_at":null,"next_vote_at":null}
400{"error":"bad_request","message":"Pass username or ip."}
403{"error":"invalid_key","message":"Invalid server ID or API key."}

Храните последний выданный voted_at для аккаунта, чтобы один голос = одна награда. Держите API key в секрете — только на сервере, не в клиенте и не в JavaScript.

Проверка интеграции

Проверьте ключ, узнайте, голосовал ли персонаж, и отправьте настоящий подписанный тестовый запрос на ваш скрипт — голосовать самому не нужно.

Тестовый callback — настоящий подписанный запрос: если персонаж существует, скрипт выдаст награду — используйте тестового персонажа.

Кнопка для вашего сайта

Vote for us on L2Servers.top

<a href="https://l2servers.top/vote/YOUR-SERVER/" target="_blank"><img src="https://l2servers.top/vote-button.svg" width="88" height="31" alt="Vote for us on L2Servers.top"></a>

Замените YOUR-SERVER на ваш адрес на L2Servers.top (например /vote/forceplay/). Добавьте ?username=Имя, чтобы подставить имя персонажа — удобно в лаунчере и личном кабинете.

FAQ

Это бесплатно?

Да. Голосование, API и скрипт наград бесплатны для всех серверов в каталоге.

Callback не приходит

Используйте обычный домен с https:// (443) или http:// (80), без IP-адресов и нестандартных портов, и отвечайте за 3 секунды. Проверьте инструментом выше — он покажет HTTP-статус и первые 300 символов ответа.

Ответ «expired»

Часы вашего веб-сервера расходятся больше чем на 10 минут. Включите синхронизацию времени (NTP).

Можно ли накрутить многими персонажами?

Нет: один голос раз в 12 часов на IP и на имя персонажа, плюс защита от ботов. Для надёжности выдавайте награду раз на аккаунт (Java-пример так и делает).

Можно сменить ключ?

Да — напишите нам, мы сгенерируем новый; старый перестанет работать сразу.