KaleGame

API Dokümantasyonu

API dokümantasyonuna hoş geldiniz. Bu dokümantasyon ödeme sistemini uygulamanıza entegre etmenize yardımcı olacaktır.

API endpointlerine ve kaynaklara göz atmak için kenar çubuğunu kullanın ya da tüm bölümleri keşfetmek için aşağı kaydırın.

Önemli: Tüm API istekleri api.kalegame.net adresine yapılmalıdır.

Hash Oluşturma

Aşağıdaki iki link oluşturma endpoint’i için hash gereklidir. Hesabı yalnızca kendi sunucunuzda yapın; secretKey tarayıcıya veya mobil uygulamaya konulmamalıdır. SHA-256 sonucunun ham baytları Base64 kodlanır; hex metninin Base64 karşılığı kullanılmaz.

Önemli: Hash hesaplama API güvenliği ve istek doğrulaması için kritiktir.

Hash Hesaplama Adımları

  1. Bu değerleri tam olarak bu sırayla birleştirin: apiKey + secretKey + userEmail + userID
  2. Birleştirilmiş string'in SHA-256 hash'ini oluşturun
  3. Elde edilen hash'i Base64 formatında kodlayın

JavaScript Örneği

// apiKey değeri X-API-Key header'ında gönderilecek
const crypto = require('crypto');
const stringToHash = apiKey + secretKey + userEmail + userID;
const hash = crypto.createHash('sha256').update(stringToHash).digest('base64');

Mağaza (Store)

mağazanızda önceden tanımladığınız ürünleri doğrudan müşterilerinize listeleyebilir ve ödemelerini alabilirsiniz.

Bu senaryo genellikle sabit ürünlerin satıldığı online oyunlarda tercih edilir. Ürünleri Merchant panelinden tanımlamanız gerekmektedir.

Mağaza Ödeme Linki Oluşturma

POST /v1/store/create

Yeni bir mağaza ödeme linki oluşturur. JWT yerine API Key ve hash tabanlı kimlik doğrulama kullanır.

CURL Örneği

# Mağaza ödeme linki oluştur
curl -X POST https://pay.karakaptan.com/api/v1/store/create \
     -H "Content-Type: application/json" \
     -H "X-API-Key: your_api_key" \
     -d '{
       "userUsername": "player123",
       "userAccountName": "Customer Name",
       "userEmail": "customer\u0040example.com",
       "userID": "123456",
       "userAddress": "123 Main St, City, Country",
       "userPhone": "+901234567890",
       "success_url": "https://yoursite.com/success",
       "fail_url": "https://yoursite.com/failed",
       "hash": "calculated_hash_value"
     }'

İSTEK HEADER'LARI

HeaderTipAçıklama
X-API-KeyStringMerchant'ın API anahtarı. (Gerekli)

İSTEK GÖVDESI (JSON)

userUsername gerekli · string

Oyuncunun giriş/kullanıcı adı. userAccountName alanından ayrıdır.

userAccountName gerekli string

Müşterinin hesap adı.

userEmail gerekli string

Müşterinin email adresi.

userID gerekli string

Merchant sistemindeki müşteri ID'si.

userAddress gerekli string

Müşterinin adresi.

userPhone gerekli string

Müşterinin telefon numarası.

hash gerekli string

apiKey + secretKey + userEmail + userID'nin SHA-256 hash'i base64 formatında.

success_url ve fail_url zorunlu string alanlarıdır. Müşterinin ödeme sonrası döneceği kendi HTTPS adreslerinizi gönderin. Tarayıcı yönlendirmesi ödeme kanıtı değildir; teslimatı doğrulanmış başarılı webhook üzerinden yapın.

YANITLAR

201 CreatedBaşarılı
{
  "success": true,
  "message": "Ödeme linki başarıyla oluşturuldu.",
  "payment_link": "https://pay.karakaptan.com/payments/11111111-2222-4333-8444-555555555555"
}
400 Bad RequestEksik Parametreler
{
  "success": false,
  "message": "Eksik parametreler: X-API-Key (header), userUsername, userAccountName, userEmail, userID, userAddress, userPhone, success_url, fail_url ve hash gereklidir."
}
401 UnauthorizedGeçersiz API Key
403 ForbiddenHash Doğrulama Hatası

FARKLI DİLLERDE KOD ÖRNEKLERİ

PHP Örneği
<?php
// API key ve diğer bilgiler
$apiKey = "your_api_key";
$secretKey = "your_secret_key"; // Merchant API Key'den alınmalı
$userEmail = "customer" . "@" . "example.com";
$userID = "123456";

// Hash oluşturma
$stringToHash = $apiKey . $secretKey . $userEmail . $userID;
$hash = base64_encode(hash('sha256', $stringToHash, true));

// İstek verileri
$data = [
    'userUsername' => 'player123',
    'userAccountName' => 'Customer Name',
    'userEmail' => $userEmail,
    'userID' => $userID,
    'userAddress' => '123 Main St, City, Country', // Gerekli
    'userPhone' => '+901234567890', // Gerekli
    'success_url' => 'https://yoursite.com/success',
    'fail_url' => 'https://yoursite.com/failed',
    'hash' => $hash
];

// cURL ayarları
$curl = curl_init('https://pay.karakaptan.com/api/v1/store/create');
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($curl, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'X-API-Key: ' . $apiKey
]);

// İsteği gönder
$response = curl_exec($curl);
$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);

// Yanıtı işle
$result = json_decode($response, true);
if ($httpCode == 201 && isset($result['success']) && $result['success']) {
    echo "Ödeme linki başarıyla oluşturuldu: " . $result['payment_link'];
} else {
    echo "Hata: " . ($result['message'] ?? 'Bilinmeyen hata');
}
?>
Node.js Örneği
const axios = require('axios');
const crypto = require('crypto');

// API key ve diğer bilgiler
const apiKey = 'your_api_key';
const secretKey = 'your_secret_key'; // Merchant API Key'den alınmalı
const userEmail = 'customer\u0040example.com';
const userID = '123456';

// Hash oluşturma
const stringToHash = apiKey + secretKey + userEmail + userID;
const hash = crypto.createHash('sha256').update(stringToHash).digest('base64');

// İstek verileri
const requestData = {
    userUsername: 'player123',
    userAccountName: 'Customer Name',
    userEmail: userEmail,
    userID: userID,
    userAddress: '123 Main St, City, Country', // Gerekli
    userPhone: '+901234567890', // Gerekli
    success_url: 'https://yoursite.com/success',
    fail_url: 'https://yoursite.com/failed',
    hash: hash
};

// İsteği gönder
async function createStorePaymentLink() {
  try {
    const response = await axios({
      method: 'post',
      url: 'https://pay.karakaptan.com/api/v1/store/create',
      headers: {
        'Content-Type': 'application/json',
        'X-API-Key': apiKey
      },
      data: requestData
    });
    
    console.log('Ödeme linki başarıyla oluşturuldu:', response.data.payment_link);
    return response.data;
  } catch (error) {
    console.error('Hata:', error.response ? error.response.data : error.message);
    throw error;
  }
}

createStorePaymentLink();

Mağazada Tanımlı Ürünler

Ürünler mağaza panelinde tanımlanır ve oluşturulan ödeme linkinde müşteriye listelenir. Bu bölüm ayrı bir API-key tabanlı ürün listeleme endpoint’i sunmaz.

Not: Mağaza aktif olmalı ve en az bir ürün içermelidir. Ürün yoksa 400, mağaza pasifse 403 yanıtı alınır.

Ödeme Linki

Ürün verisi ile yeni ödeme linki oluşturmanızı sağlar. Tüm ödeme istekleri uygun kimlik doğrulama ve hash doğrulaması gerektirir.

POST /v1/payment-link/create

Ürün verisi ile yeni bir ödeme linki oluşturur. JWT yerine API Key ve hash tabanlı kimlik doğrulama kullanır.

CURL Örneği

# Ürün verisi ile ödeme linki oluştur
curl -X POST https://pay.karakaptan.com/api/v1/payment-link/create \
     -H "Content-Type: application/json" \
     -H "X-API-Key: your_api_key" \
     -d '{
       "userUsername": "player123",
       "userAccountName": "Customer Name",
       "userEmail": "customer\u0040example.com",
       "userID": "123456",
       "userAddress": "123 Main St, City, Country",
       "userPhone": "+901234567890",
       "success_url": "https://yoursite.com/success",
       "fail_url": "https://yoursite.com/failed",
       "productData": {
         "name": "Gold Membership",
         "description": "Premium subscription for 12 months",
         "amount": 199.99
       },
       "hash": "calculated_hash_value"
     }'

İSTEK GÖVDESI (JSON)

userUsername gerekli · string

Oyuncunun giriş/kullanıcı adı. userAccountName alanından ayrıdır.

userAccountName gerekli string

Müşterinin hesap adı.

userEmail gerekli string

Müşterinin email adresi.

userID gerekli string

Merchant sistemindeki müşteri ID'si.

userAddress gerekli string

Müşterinin adresi.

userPhone gerekli string

Müşterinin telefon numarası.

success_url gerekli string

Başarılı ödeme sonrası yönlendirilecek URL.

fail_url gerekli string

Başarısız ödeme sonrası yönlendirilecek URL.

productData gerekli object

Name, description ve amount içeren ürün bilgileri.

productData.name gerekli string

Ürün adı.

productData.description gerekli string

Ürün açıklaması.

productData.amount gerekli number

Ürün fiyatı.

hash gerekli string

apiKey + secretKey + userEmail + userID'nin SHA-256 hash'i base64 formatında.

YANITLAR

201 CreatedBaşarılı
{
  "success": true,
  "message": "Ödeme linki başarıyla oluşturuldu.",
  "payment_link": "https://pay.karakaptan.com/pay/11111111-2222-4333-8444-555555555555"
}
400 Bad RequestEksik Parametreler
{
  "success": false,
  "message": "Eksik parametreler: X-API-Key (header), userUsername, userAccountName, userEmail, userID, userAddress, userPhone, success_url, fail_url, productData ve hash gereklidir."
}

KOD ÖRNEKLERİ

PHP Örneği
<?php
// API key ve diğer bilgiler
$apiKey = "your_api_key";
$secretKey = "your_secret_key"; // Merchant API Key'den alınmalı
$userEmail = "customer" . "@" . "example.com";
$userID = "123456";

// Hash oluşturma
$stringToHash = $apiKey . $secretKey . $userEmail . $userID;
$hash = base64_encode(hash('sha256', $stringToHash, true));

// İstek verileri
$data = [
    'userUsername' => 'player123',
    'userAccountName' => 'Customer Name',
    'userEmail' => $userEmail,
    'userID' => $userID,
    'userAddress' => '100 Sk, Ankara, Ankara', 
    'userPhone' => '+901234567890', 
    'success_url' => 'https://yoursite.com/success', 
    'fail_url' => 'https://yoursite.com/failed', 
    'productData' => [
        'name' => 'Valorant VP',
        'description' => 'Valorant VP',
        'amount' => 3.19
    ],
    'hash' => $hash
];

// cURL ayarları
$curl = curl_init('https://pay.karakaptan.com/api/v1/payment-link/create');
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($curl, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'X-API-Key: ' . $apiKey
]);

// İsteği gönder
$response = curl_exec($curl);
$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);

// Yanıtı işle
$result = json_decode($response, true);
if ($httpCode == 201 && isset($result['success']) && $result['success']) {
    echo "Ödeme linki başarıyla oluşturuldu: " . $result['payment_link'];
} else {
    echo "Hata: " . ($result['message'] ?? 'Bilinmeyen hata');
}
?>
Node.js Örneği
const axios = require('axios');
const crypto = require('crypto');

// API key ve diğer bilgiler
const apiKey = 'your_api_key';
const secretKey = 'your_secret_key';  // Merchant API Key'den alınmalı
const userEmail = 'customer\u0040example.com';
const userID = '123456';

// Hash oluşturma
const stringToHash = apiKey + secretKey + userEmail + userID;
const hash = crypto.createHash('sha256').update(stringToHash).digest('base64');

// İstek verileri - Float değerleri stabilize et
const requestData = {
    userUsername: 'player123',
    userAccountName: 'Customer Name',
    userEmail: userEmail,
    userID: userID,
    userAddress: '123 Main St, City, Country', 
    userPhone: '+901234567890', 
    success_url: 'https://yoursite.com/success', 
    fail_url: 'https://yoursite.com/failed', 
    productData: {
        name: 'Gold Membership',
        description: 'Premium subscription for 12 months',
        amount: 199.99 // TRY cinsinden ürün fiyatı
    },
    hash: hash
};


// API isteği - Async/await kullanarak daha iyi hata yönetimi
async function createPaymentLink() {
    try {
        const response = await axios({
            method: 'post',
            url: 'https://pay.karakaptan.com/api/v1/payment-link/create',
            headers: {
                'Content-Type': 'application/json',
                'X-API-Key': apiKey
            },
            data: requestData,
            timeout: 30000 // 30 saniye timeout
        });
        
        if (response.status === 201 && response.data.success) {
            console.log('Ödeme linki başarıyla oluşturuldu:', response.data.payment_link);
            return response.data;
        } else {
            throw new Error(response.data.message || 'Bilinmeyen hata');
        }
    } catch (error) {
        if (error.response) {
            console.error('API Hatası:', error.response.data.message || error.response.data);
            console.error('HTTP Kod:', error.response.status);
        } else if (error.request) {
            console.error('Bağlantı hatası: İstek gönderildi ancak yanıt alınamadı');
        } else {
            console.error('Hata:', error.message);
        }
        throw error;
    }
}

// Fonksiyonu çağır
createPaymentLink()
    .then(result => {
        console.log('İşlem tamamlandı:', result);
    })
    .catch(error => {
        console.error('İşlem başarısız:', error.message);
    });

🔗 Webhook Callback Examples

Sistemimiz başarılı (status: success) veya başarısız (status: failed) ödeme sonucunu mağazanızın webhook URL’sine POST eder. Yalnızca doğrulanmış success bildiriminde teslimat yapın. Bu webhook callback'lerini işlemek için farklı programlama dillerinde implementasyon örnekleri:

📋 Webhook Payload Yapısı

Webhook endpoint'iniz aşağıdaki JSON payload ile POST isteği alacak:

Tek Ödeme Linkleri İçin:

{
  "userAccountName": "Customer Name",
  "userEmail": "customer\u0040example.com", 
  "userID": "123456",
  "userAddress": "123 Main St, City, Country",
  "userPhone": "+901234567890",
  "orderID": "92811772704",
  "status": "success",
  "productData": {
    "name": "Gold Membership",
    "description": "Premium subscription for 12 months", 
    "amount": 199.99
  },
  "hash": "generated_security_hash"
}

Mağaza Ödeme Linkleri İçin:

{
  "userAccountName": "Customer Name",
  "userEmail": "customer\u0040example.com",
  "userID": "123456", 
  "userAddress": "123 Main St, City, Country",
  "userPhone": "+901234567890",
  "orderID": "42005226715",
  "status": "success",
  "productData": {
    "name": "Harika Akıllı Telefon X",
    "description": "En son teknolojiye sahip, yüksek performanslı akıllı telefon.",
    "amount": 1299.99,
    "callback_data": {
      "product_code": "SMARTX123", 
      "color": "black"
    }
  },
  "hash": "generated_security_hash"
}

Tutar: Başarılı ödemede komisyon varsa productData.amount komisyon düşülmüş net tutardır (iki ondalığa aşağı yuvarlanır). Örneğin 100 TRY ve %5 komisyon için 95 gönderilir. Başarısız bildirimde tutar brüttür. EP miktarını bu tutardan hesaplamayın; mağaza ürününün callback_data.cash alanını kullanın. Tek ödeme linkinde callback_data gönderilmez.

İmza: SHA256-hex(userAccountName + userEmail + userID + orderID + productDataJSON + secretKey). productData alan sırası korunmalı; Unicode karakterler küçük harfli \uXXXX biçiminde kaçırılmalı, slash (/) kaçırılmamalıdır. JSON’u yeniden sıralamayın. Aynı mağazanın secretKey değerini kullanın.

Mevcut protokol sınırı: status alanı hash hesabına dahil değildir. TLS zorunludur; hash’in bütün payload alanlarını imzaladığını varsaymayın. Tarayıcı dönüş URL’sini teslimat için kullanmayın.

Örneklerin kapsamı: Aşağıdaki örnekler bildirimi doğrulama ve yanıtlama iskeletidir. İşaretli yere kendi sipariş/EP teslimat işleminizi ekleyin. Mağaza + orderID üzerinde benzersiz kayıt kullanın; kayıt ve teslimat aynı veritabanı transaction’ında olmalı. Teslimat kaydedilmeden 200 dönmeyin. Daha önce işlenmiş bildirimde yeniden EP vermeden 200 dönün.

PHP Örneği

<?php
// webhook_handler.php

header('Content-Type: application/json');

// Get the request body
$input = file_get_contents('php://input');
$data = json_decode($input, true);
// productData içindeki JSON nesnelerini nesne olarak koruyun.
$rawObject = json_decode($input);
if (is_array($data) && is_object($rawObject) && isset($rawObject->productData)) {
    $data['productData'] = $rawObject->productData;
}

// Validate JSON
if (json_last_error() !== JSON_ERROR_NONE) {
    http_response_code(400);
    echo json_encode(['error' => 'Invalid JSON']);
    exit;
}

// Validate required fields
$required_fields = ['userAccountName', 'userEmail', 'userID', 'orderID', 'productData', 'status', 'hash'];
foreach ($required_fields as $field) {
    if (!isset($data[$field])) {
        http_response_code(400);
        echo json_encode(['error' => "Missing required field: $field"]);
        exit;
    }
}

// Webhook imzası SHA-256 hex formatındadır; link oluşturma hash’i ile farklıdır.
function verifyHash($data, $receivedHash) {
    // Alan sırasını koruyun; Unicode escape edilir, / karakteri escape edilmez.
    $dataToHash = $data['userAccountName'] . $data['userEmail'] . 
                  $data['userID'] . $data['orderID'] . 
                  str_replace(chr(127), '\u007f', json_encode($data['productData'], JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR));
    $secretKey = getenv('KALEGAME_SECRET_KEY');
    if (!$secretKey) { throw new RuntimeException('KALEGAME_SECRET_KEY eksik'); }
    $expectedHash = hash('sha256', $dataToHash . $secretKey);
    return hash_equals($expectedHash, $receivedHash);
}

// Verify the hash
if (!is_string($data['hash']) || !verifyHash($data, $data['hash'])) {
    http_response_code(401);
    echo json_encode(['error' => 'Invalid hash']);
    exit;
}

if (!in_array($data['status'], ['success', 'failed'], true)) {
    http_response_code(400); exit;
}
if ($data['status'] === 'failed') {
    http_response_code(200); echo json_encode(['success' => true]); exit;
}
// Hash doğrulandı - burada kendi iş mantığınızı uygulayabilirsiniz
// Örneğin: database güncellemesi, email gönderimi, vb.

// Başarılı yanıt döndür
http_response_code(200);
echo json_encode([
    'success' => true,
    'message' => 'Webhook successfully verified',
    'orderID' => $data['orderID']
]);
?>

Node.js Örneği

// webhook_handler.js
const express = require('express');
const crypto = require('crypto');

if (!process.env.KALEGAME_SECRET_KEY) throw new Error('KALEGAME_SECRET_KEY eksik');
const app = express();
app.use(express.json());

// Hash doğrulama için gerekli modüller

// Hash verification function
function verifyHash(data, receivedHash) {
    const dataToHash = data.userAccountName + data.userEmail + 
                      data.userID + data.orderID + 
                      JSON.stringify(data.productData).replace(/[\u007F-\uFFFF]/g, c =>
                        '\\u' + c.charCodeAt(0).toString(16).padStart(4, '0'));
    const expectedHash = crypto.createHash('sha256')
                              .update(dataToHash + process.env.KALEGAME_SECRET_KEY)
                              .digest('hex');
    if (typeof receivedHash !== 'string' || !/^[a-f0-9]{64}$/.test(receivedHash)) return false;
    return crypto.timingSafeEqual(Buffer.from(expectedHash, 'hex'), Buffer.from(receivedHash, 'hex'));
}

// Webhook endpoint
app.post('/webhook', async (req, res) => {
    try {
        const data = req.body;
        
        // Validate required fields
        const requiredFields = ['userAccountName', 'userEmail', 'userID', 'orderID', 'productData', 'status', 'hash'];
        for (const field of requiredFields) {
            if (!data[field]) {
                return res.status(400).json({ error: `Missing required field: ${field}` });
            }
        }
        
        // Verify hash
        if (!verifyHash(data, data.hash)) {
            return res.status(401).json({ error: 'Invalid hash' });
        }
        
        if (!['success', 'failed'].includes(data.status)) return res.status(400).json({ error: 'Invalid status' });
        if (data.status === 'failed') return res.json({ success: true });

        // Hash doğrulandı - burada kendi iş mantığınızı uygulayabilirsiniz
        // Örneğin: database güncellemesi, email gönderimi, vb.
        
        // Başarılı yanıt döndür
        res.json({
            success: true,
            message: 'Webhook successfully verified',
            orderID: data.orderID
        });
        
    } catch (error) {
        console.error('Webhook processing error:', error);
        res.status(500).json({ error: 'Internal server error' });
    }
});



const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
    console.log(`Webhook server running on port ${PORT}`);
});

module.exports = app;

🔒 Güvenlik En İyi Uygulamaları

⚠️ Önemli Güvenlik Notları:

  • Hash Doğrulama: Webhook'un gerçek olduğundan emin olmak için hash'i her zaman doğrulayın
  • Sadece HTTPS: Production'da webhook endpoint'leriniz için HTTPS kullanın
  • Idempotency: Tekrarlanan webhook'ları düzgün şekilde handle edin (sipariş zaten işlenmiş mi kontrol edin)
  • Hata Yönetimi: Uygun HTTP status kodları döndürün
  • Loglama: Gizli anahtarları ve kişisel verileri maskeleyin; orderID ve HTTP sonucu gibi gerekli alanları kaydedin
  • Timeout: Gönderici 30 saniyede zaman aşımına uğrar. Bildirimi kalıcı ve güvenli şekilde işleyip hızlı yanıtlayın; otomatik yeniden gönderim garantisi yoktur.

📝 Response Gereksinimleri

Webhook endpoint'iniz şu HTTP status kodlarıyla yanıt vermelidir:

  • 200 OK: Webhook başarıyla işlendiğinde
  • 400 Bad Request: Payload geçersiz veya gerekli alanlar eksik olduğunda
  • 401 Unauthorized: Hash doğrulama başarısız olduğunda
  • 500 Internal Server Error: İşleme başarısız olduğunda