Jak To Działa
API Vote Rewards metin2.gg pozwala Twojemu serwerowi Metin2 automatycznie wykrywać, kiedy gracze głosują i przyznawać nagrody w grze. Przepływ jest prosty: gracze głosują na metin2.gg podając nazwę postaci, a Twój serwer odpytuje nasze API, aby sprawdzić i odebrać te głosy.
Są dwa tryby integracji — wybierz ten, który pasuje do Twojej konfiguracji:
Polling (Zalecany)
Twój serwer okresowo wywołuje nasze API, aby sprawdzić nowe głosy. Najłatwiejszy do wdrożenia — działa z każdą konfiguracją serwera Metin2. Po prostu dodaj jedno żądanie HTTP do kodu serwera gry.
Webhooks (Zaawansowany)
metin2.gg wysyła powiadomienie do Twojego serwera w momencie, gdy gracz zagłosuje. W czasie rzeczywistym, ale wymaga publicznie dostępnego endpointu HTTPS po Twojej stronie.
Uwierzytelnianie
Wszystkie żądania API wymagają klucza API wysyłanego przez nagłówek X-API-Key. Klucze mają format mg_live_... i są generowane z panelu Twojego serwera.
X-API-Key: mg_live_5bef...1a70Twój klucz API jest przypisany do jednego serwera i wyświetlany tylko raz przy generowaniu. Jeśli go zgubisz, wygeneruj nowy z panelu (stary klucz jest natychmiast unieważniany).
Jak Uzyskać Klucz API
- 1Przejdź do Mój Panel → Moje Serwery. Kliknij nazwę swojego serwera, aby otworzyć stronę zarządzania.
- 2Na stronie zarządzania zweryfikuj własność (rekord DNS TXT lub meta tag), jeśli jeszcze tego nie zrobiłeś.
- 3Dodaj link zwrotny do metin2.gg na stronie swojego serwera, aby odblokować status Partnera.
- 4Na stronie zarządzania swoim serwerem kliknij przycisk "Ustawienia API". Następnie kliknij "Generuj Klucz API" i skopiuj go — jest wyświetlany tylko raz.
Sprawdź Status Głosu
Sprawdź, czy określony gracz ma nieodebrany głos. Jeśli istnieje oczekujący głos, jest automatycznie odbierany (oznaczany jako wykorzystany), aby ten sam głos nie mógł być odebrany dwukrotnie.
GET /api/v1/vote/check?player_id=PlayerName HTTP/1.1
Host: metin2.gg
X-API-Key: mg_live_YOUR_KEY_HEREParametry Zapytania
| Parameter | Type | Required | Description |
|---|---|---|---|
| player_id | string | Yes | Nazwa postaci, którą gracz użył podczas głosowania. Wielkość liter nie ma znaczenia. |
Odpowiedź
Gracz ma nieodebrany głos (teraz odebrany)
{
"voted": true,
"player_id": "PlayerName",
"vote_id": "550e8400-e29b-41d4-a716-446655440000",
"voted_at": "2026-03-02T14:30:00Z"
}Brak oczekującego głosu dla tego gracza
{
"voted": false
}Lista Nieodebranych Głosów
Pobierz wszystkie nieodebrane głosy dla Twojego serwera. Przydatne do przetwarzania wsadowego — na przykład cron job uruchamiany co 5 minut, który przyznaje nagrody za wszystkie oczekujące głosy naraz.
GET /api/v1/vote/unclaimed?limit=50 HTTP/1.1
Host: metin2.gg
X-API-Key: mg_live_YOUR_KEY_HEREParametry Zapytania
| Parameter | Type | Required | Description |
|---|---|---|---|
| limit | integer | No | Maksymalna liczba zwracanych głosów (1–100, domyślnie 50). |
Odpowiedź
{
"votes": [
{
"vote_id": "550e8400-e29b-41d4-a716-446655440000",
"player_id": "PlayerName",
"voted_at": "2026-03-02T14:30:00Z"
},
{
"vote_id": "660e8400-e29b-41d4-a716-446655440001",
"player_id": "AnotherPlayer",
"voted_at": "2026-03-02T14:32:00Z"
}
],
"total": 2
}Wsadowe Odbieranie Głosów
Oznacz wiele głosów jako odebrane w jednym żądaniu. Użyj tego po przetworzeniu głosów z endpointu unclaimed.
POST /api/v1/vote/claim HTTP/1.1
Host: metin2.gg
Content-Type: application/json
X-API-Key: mg_live_YOUR_KEY_HERE
{
"vote_ids": [
"550e8400-e29b-41d4-a716-446655440000",
"660e8400-e29b-41d4-a716-446655440001"
]
}Treść Żądania (JSON)
| Parameter | Type | Required | Description |
|---|---|---|---|
| vote_ids | string[] | Yes | Tablica UUID głosów do odebrania. Maksymalnie 100 na żądanie. |
Odpowiedź
{
"claimed": 2,
"failed": 0
}Webhooks
Zamiast pollingu, możesz otrzymywać powiadomienia push w czasie rzeczywistym, gdy gracz zagłosuje. Skonfiguruj URL webhooka w panelu serwera w Ustawieniach API.
Payload Webhooka
POST https://your-server.com/api/vote-webhook HTTP/1.1
Content-Type: application/json
X-Metin2GG-Signature: a1b2c3d4e5f6...
{
"event": "vote.created",
"vote_id": "550e8400-e29b-41d4-a716-446655440000",
"server_id": "your-server-uuid",
"player_id": "PlayerName",
"voted_at": "2026-03-02T14:30:00Z",
"timestamp": "2026-03-02T14:30:01Z"
}Weryfikacja Podpisu
Każde żądanie webhooka zawiera nagłówek X-Metin2GG-Signature z digest hex HMAC-SHA256 surowej treści żądania, podpisany Twoim sekretnym kluczem API. Zawsze weryfikuj ten podpis przed zaufaniem payloadowi.
import hmac
import hashlib
def verify_webhook(request_body: bytes, signature: str, secret: str) -> bool:
"""Verify the X-Metin2GG-Signature header."""
expected = hmac.new(
secret.encode("utf-8"),
request_body,
hashlib.sha256,
).hexdigest()
return hmac.compare_digest(expected, signature)
# Usage in your webhook handler:
# body = request.body (raw bytes)
# sig = request.headers["X-Metin2GG-Signature"]
# if not verify_webhook(body, sig, "your_api_secret"):
# return HttpResponse(status=403)<?php
function verifyWebhook(string $body, string $signature, string $secret): bool {
$expected = hash_hmac('sha256', $body, $secret);
return hash_equals($expected, $signature);
}
// Usage in your webhook handler:
// $body = file_get_contents('php://input');
// $sig = $_SERVER['HTTP_X_METIN2GG_SIGNATURE'] ?? '';
// if (!verifyWebhook($body, $sig, 'your_api_secret')) {
// http_response_code(403);
// exit('Invalid signature');
// }Integracja Metin2: Komenda Python
Umieść ten skrypt w systemie komend Python Twojego serwera gry. Gdy gracz wpisze /reward w grze, sprawdza metin2.gg pod kątem oczekującego głosu i przyznaje nagrodę.
# vote_reward.py — Drop into your game server's command scripts
# Works with Python 2.7+ (common in Metin2 servers)
import json
import os
METIN2GG_API_KEY = "mg_live_YOUR_KEY_HERE"
METIN2GG_API_URL = "https://metin2.gg/api/v1/vote/check"
def check_vote(player_name):
"""Check if player has a pending vote and auto-claim it."""
url = "%s?player_id=%s" % (METIN2GG_API_URL, player_name)
# Method 1: Use urllib2 (Python 2) or urllib.request (Python 3)
try:
try:
import urllib2
req = urllib2.Request(url)
req.add_header("X-API-Key", METIN2GG_API_KEY)
resp = urllib2.urlopen(req, timeout=5)
data = json.loads(resp.read())
except ImportError:
import urllib.request
req = urllib.request.Request(url)
req.add_header("X-API-Key", METIN2GG_API_KEY)
resp = urllib.request.urlopen(req, timeout=5)
data = json.loads(resp.read().decode("utf-8"))
return data.get("voted", False)
except Exception:
pass
# Method 2: Fallback to curl (works even with broken SSL)
try:
cmd = 'curl -s -H "X-API-Key: %s" "%s"' % (METIN2GG_API_KEY, url)
raw = os.popen(cmd).read()
data = json.loads(raw)
return data.get("voted", False)
except Exception:
return None
# Example usage in your game command handler:
# def cmd_reward(player):
# result = check_vote(player.GetName())
# if result is True:
# player.GiveItem(50011, 10) # Example: 10x Dragon God Coins
# player.ChatInfoMessage("Vote reward claimed!")
# elif result is False:
# player.ChatInfoMessage("No pending vote. Vote at metin2.gg!")
# else:
# player.ChatInfoMessage("Could not reach metin2.gg. Try again.")Integracja Metin2: Plik Quest (Lua)
Ten plik quest tworzy interakcję z NPC, gdzie gracze mogą sprawdzić status głosu. Wywołuje komendę po stronie serwera, która uruchamia sprawdzenie głosu Python.
quest vote_reward begin
state start begin
when login or letter begin
send_letter("Vote Reward")
end
when button or info begin
say_title("Vote Reward")
say("")
say("Vote for our server on metin2.gg")
say("and claim your reward here!")
say("")
local s = select("Check My Vote", "How to Vote", "Close")
if s == 1 then
-- Triggers the Python command that checks the API
cmdchat("checkvote "..pc.get_name())
elseif s == 2 then
say_title("How to Vote")
say("")
say("1. Open metin2.gg in your browser")
say("2. Find our server page")
say("3. Enter your character name")
say("4. Click the Vote button")
say("5. Come back here to claim your reward!")
say("")
end
end
end
endIntegracja Metin2: Panel Web PHP
Jeśli Twój serwer ma panel web (oparty na PHP), użyj tego snippetu, aby sprawdzać i odbierać głosy z panelu. Działa z każdym środowiskiem PHP 7+ z cURL.
<?php
/**
* check_vote.php — Vote check for PHP-based web panels
* Requires PHP 7.0+ with cURL extension
*/
$apiKey = "mg_live_YOUR_KEY_HERE";
$playerName = $_GET["player"] ?? "";
if (empty($playerName)) {
echo json_encode(["error" => "Missing player name"]);
exit;
}
// Check vote status
$ch = curl_init(
"https://metin2.gg/api/v1/vote/check?player_id=" . urlencode($playerName)
);
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => ["X-API-Key: $apiKey"],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_SSL_VERIFYPEER => true,
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
echo json_encode(["error" => "API returned HTTP $httpCode"]);
exit;
}
$data = json_decode($response, true);
if ($data["voted"] ?? false) {
// Player has voted — grant reward via your game DB
// Example: INSERT INTO player.reward_queue (player, item_vnum, count) ...
echo json_encode([
"success" => true,
"message" => "Vote reward granted!",
"vote_id" => $data["vote_id"],
]);
} else {
echo json_encode([
"success" => false,
"message" => "No pending vote found.",
]);
}Limity Częstotliwości i Kody Błędów
API wymusza limity częstotliwości, aby zapewnić sprawiedliwe użycie. Aktualne limity:
- 60 requests per minute per API key
- 1,000 requests per hour per API key
| Status | Opis |
|---|---|
| 200 OK | Żądanie powiodło się. |
| 400 Bad Request | Brakujące lub nieprawidłowe parametry. Sprawdź format player_id lub vote_ids. |
| 401 Unauthorized | Brakujący lub nieprawidłowy klucz API. Upewnij się, że dołączasz nagłówek X-API-Key. |
| 403 Forbidden | Dostęp do API jest wyłączony — zwykle dlatego, że link zwrotny został usunięty. Dodaj ponownie link zwrotny i sprawdź. |
| 404 Not Found | Endpoint nie istnieje. Sprawdź ponownie ścieżkę URL. |
| 429 Too Many Requests | Przekroczono limit częstotliwości. Poczekaj i ponów próbę po wartości nagłówka Retry-After (w sekundach). |
| 500 Internal Server Error | Coś poszło nie tak po naszej stronie. Ponów próbę po kilku sekundach. |
Strategia Ponawiania
On 429 errors, read the Retry-After header (value in seconds) and wait before retrying. For 500 errors, retry with exponential backoff (1s, 2s, 4s).
FAQ Rozwiązywanie Problemów
Otrzymuję 401 Unauthorized przy każdym żądaniu
Upewnij się, że wysyłasz klucz API w nagłówku X-API-Key (nie jako parametr zapytania ani w treści). Klucz musi zaczynać się od mg_live_.
API mówi voted: false, ale gracz twierdzi, że zagłosował
Gracz mógł zagłosować bez wpisania nazwy postaci lub użyć innej nazwy. Sprawdź URL linku do głosowania — musi zawierać ?player_id=DOKŁADNA_NAZWA. Nazwy nie rozróżniają wielkości liter.
Otrzymuję 403 Forbidden
Twój dostęp do API jest wstrzymany, prawdopodobnie dlatego, że link zwrotny do metin2.gg został usunięty z Twojej strony. Dodaj go ponownie i kliknij 'Sprawdź Teraz' w panelu, aby ponownie zweryfikować.
Czy mogę przetestować API bez prawdziwych głosów?
Obecnie nie ma trybu sandbox. Zagłosuj na własną listę serwera z testową nazwą postaci, aby zweryfikować integrację od początku do końca.
Mój skrypt Python nie może się połączyć (timeout lub błąd SSL)
Większość serwerów Metin2 używa Pythona 2.7, który ma przestarzałe certyfikaty SSL. Użyj awaryjnego os.popen('curl ...') pokazanego w przykładzie Python lub zaktualizuj pakiet CA Pythona na swoim serwerze.
Jak często powinienem odpytywać API?
Dla endpointu /check (na gracza): wywołuj go, gdy gracz żąda nagrody (np. komenda /reward). Dla /unclaimed (wsadowo): co 3–5 minut przez cron jest idealne. Nie odpytuj częściej niż raz na minutę.
Czy wiele serwerów może współdzielić jeden klucz API?
Nie. Każdy klucz API jest przypisany do jednej listy serwera. Jeśli prowadzisz wiele serwerów, wygeneruj osobny klucz dla każdego z odpowiednich stron panelu.
Co się stanie, jeśli mój endpoint webhooka jest niedostępny?
metin2.gg ponawia nieudane dostawy webhooków do 5 razy z wykładniczym opóźnieniem. Jeśli wszystkie próby zawiodą, głos pozostaje nieodebrany i nadal może być pobrany przez endpointy pollingu.
Gotowy do Integracji?
Dodaj swój serwer do metin2.gg, wygeneruj klucz API i zacznij nagradzać głosujących w kilka minut.