İlk bağlantı için bu sırayı izleyin: site ayarları → sunucu oturumu → iframe veya modül → cüzdan → kabul kontrolleri. Örnek alan adlarını ve `SITE_SLUG` değerini kendi kurulumunuzla değiştirin.

## 1. Siteyi ve sunucu anahtarını hazırlayın
Yönetici, site kodunu, kesin izinli origin’leri, oyun/tutar sınırlarını ve cüzdan modunu tanımlar. Anahtar yalnız sitenizin backend’inde saklanır. Oturum oluşturmak için launch, katalog ve rapor okumak için read kapsamı gerekir. wallet yalnız transfer cüzdanı işlemleri içindir; seamless callback’leri ayrı imza sırrı kullanır.

Sunucu ortamına `SLOT_BATTLES_ORIGIN` (sağlayıcının public origin’i), `SLOT_BATTLES_KEY` (sunucu anahtarı) ve `SLOT_BATTLES_SITE_ORIGIN` (izin verilen müşteri origin’i) tanımlayın. `ADMIN_ORIGIN` / `OPERATOR_ORIGIN` panel adresleridir; oyun API anahtarını bu adreslere göndermeyin.

## 2. Doğrulanmış üye için oturum oluşturun
Aşağıdaki `Node.js` 22.16+ modülü SDK dosyasıyla aynı klasördedir. Kendi `POST /integration/launch` endpoint’iniz önce site oturumunu ve CSRF değerini doğrular, üyeyi sunucudan bulur ve `createLaunchForMember` sonucunu JSON olarak döndürür. Yanıta Cache-Control: no-store ekleyin. Üye ID’sini, adını veya bakiyeyi tarayıcının beyanından almayın.

```javascript launch-service.mjs
import { SlotBattlesClient } from './slot-battles-sdk.mjs';

const client = new SlotBattlesClient({
  origin: process.env.SLOT_BATTLES_ORIGIN,
  apiKey: process.env.SLOT_BATTLES_KEY
});

export async function createLaunchForMember(member, mode = 'iframe') {
  if (!member?.id) throw new Error('Authenticated member required.');

  return client.launch({
    externalId: String(member.id),
    name: member.displayName,
    siteUsername: member.username,
    origin: process.env.SLOT_BATTLES_SITE_ORIGIN,
    route: 'lobby',
    mode
  });
}
```

member.id kalıcı site üye anahtarıdır. member.username kaynak sitedeki kullanıcı adıdır; yalnız yetkili panel/API’de görünür. `member.displayName`, site öneki kapalıyken yeni hesap adı için gerekir. tenant + `externalId` tekrar açıldığında aynı Arena Battle hesabı kullanılır. Launch yeni bir başlangıç bakiyesi oluşturmaz.

## 3. Iframe olarak yerleştirin
Sayfanızda bir #game kapsayıcısı ve sunucunuzun ürettiği csrf-token meta alanı bulunmalıdır. Aşağıdaki kod type="module" olan harici bir dosyada çalışır. Kendi launch endpoint’iniz mode=iframe kullanır. provider.example yerine gerçek public sağlayıcı origin’ini yazın.

```javascript mount-arena.mjs
import { mountSlotBattles } from './slot-battles-browser.mjs';

const csrfToken = document.querySelector('meta[name="csrf-token"]')?.content;
if (!csrfToken) throw new Error('CSRF token is missing.');

const response = await fetch('/integration/launch', {
  method: 'POST',
  credentials: 'same-origin',
  headers: { 'X-CSRF-Token': csrfToken }
});
if (!response.ok) throw new Error('Launch request failed.');

const launch = await response.json();
const game = mountSlotBattles({
  container: document.querySelector('#game'),
  providerOrigin: 'https://provider.example',
  launch
});

// Call game.destroy() when your page or component is removed.
```

Bilet 90 saniye geçerli ve tek kullanımlıdır; her açılışta yeni launch isteyin. Iframe’in kapsayıcısına görünür bir yükseklik verin. Sesli otomatik oynatma, tarayıcının kullanıcı etkileşimi kurallarına bağlıdır.

## 4. Dosyalı modül olarak yerleştirin
slot-battles-client.zip içeriğinin tamamını sitenizin `/arena/` dizinine çıkarın. CSS, fontlar, görseller ve JavaScript dosyalarını birlikte dağıtın. Mevcut `slot-battles-config.js` dosyasını aşağıdaki ayarlarla güncelleyin; `integration-context.js` öncesinde yüklenmelidir.

```javascript slot-battles-config.js
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.content;
if (!csrfToken) throw new Error('CSRF token is missing.');

window.SlotBattlesConfig = {
  apiBase: 'https://provider.example/play/SITE_SLUG/',
  launchEndpoint: '/integration/launch',
  launchMethod: 'POST',
  launchCsrfToken: csrfToken,
  shareBase: '/arena/'
};
```

`SITE_SLUG` size tanımlanan site kodudur. Müşteri sayfası csrf-token meta değerini kendi sunucu oturumundan üretir. `POST /integration/launch` aynı müşteri origin’indedir ve mode=module ile `launchTicket`, `apiBase` ve `expiresAt` içeren sağlayıcı yanıtını döndürür. Bu örnek, mevcut üyelik sisteminizin yerine geçen bir login sunucusu değildir.

CSP politikanıza sağlayıcının HTTPS/WSS kaynaklarını connect-src, img-src ve media-src için ekleyin. Iframe için frame-src izni gerekir; sağlayıcı kendi frame-ancestors politikasında yalnız kayıtlı site origin’lerini kabul eder.

## Oyuncu arayüzünün dili

Oyuncu arayüzü Türkçe ve İngilizceyi destekler. Öncelik sırası: geçerli `?lang=tr` veya `?lang=en` adres parametresi, oyuncunun kaydettiği manuel tercih, isteğe bağlı `window.SlotBattlesConfig.locale`, tarayıcının sıralı dil tercihleri, son olarak Türkçe. `en-GB` ve `tr-TR` gibi bölgesel dil kodları tanınır. Footer dil menüsünden yapılan seçim kaydedilir; Otomatik seçeneği kaydı kaldırır. Otomatik tespit kalıcı tercih kaydetmez. IP konumu yerine tarayıcı tercihleri kullanılır.

Modül kurulumunda operatör varsayılanı istenirse herkese açık `slot-battles-config.js` nesnesine `locale: 'en'` veya `locale: 'tr'` ekleyin. Tarayıcıyı izlemek için bu alanı eklemeyin. Bu ayar yalnız arayüz metinlerini değiştirir; kimlik doğrulama veya API yetkisi değildir. Yeni dosyalar için tam istemci ZIP'ini güncelleyin. Mevcut iframe kurulumları güncel oyuncu arayüzünü sağlayıcıdan alır.

Ortak yayın içindeki sağlayıcı oyunları mevcut dilinde kalır. Arayüz dili odayı, seçilen oyunu, para tutarlarını veya para birimini değiştirmez. Oyuncu adları ve sohbet mesajları çevrilmez. Kurumsal site ayrı olarak İngilizce, Türkçe, Ermenice, Rusça ve Almancayı destekler; uygun dil bulunamazsa İngilizce açılır.

## 5. Aynı site cüzdanını kullanın
Site bakiyesiyle oyun bakiyesinin aynı olmasını istiyorsanız SEAMLESS-WALLET.txt ve WALLET-CONFIG.txt rehberlerini uygulayın. Site defteri tek harcanabilir bakiyedir. reserve kullanılabilir tutarı kilitler, refund aynı kilidi iade eder, settle kilidi tüketip ödülü ekler. Settle sırasında katılım tutarını ikinci kez düşürmeyin.

Tutarlar tam sayı kuruştur: 20000 = 200,00 TL. Aynı işlem kimliğiyle aynı içerik tekrar geldiğinde ikinci para hareketi oluşmamalıdır. Zaman aşımında yeni işlem kimliği üretmeyin; kalıcı makbuz ve aynı `requestId` ile mutabakat yapın. Transfer modu mevcut ayrı aktarım entegrasyonları içindir; seamless ile aynı hesapta karıştırılmaz.

## 6. Paylaşım ve bakiye olayları
Iframe yardımcısında `onShare({route})`, `onIdentity({player})` ve `onWalletChange()` kullanılabilir. Paylaşım linki kendi site sayfanıza watch/ID veya join/KOD rotasını taşımalıdır; yeni ziyaretçi kendi oturumu için yeni launch alır. Linke API anahtarı, player token veya bilet koymayın.

`onWalletChange` yalnız değişiklik bildirimidir. Yeni bakiyeyi mesajdan kabul etmek yerine kendi doğrulanmış backend’inizden tekrar okuyun. Modülde `shareBase` aynı müşteri origin’inde olmalıdır. Sayfa/komponent kaldırılırken `game.destroy()` çağırın.

## 7. Yerel referans ve kabul listesi
Çalışan seamless site örneği `examples/operator-seamless.cjs`, transfer örneği `examples/operator-authenticated.cjs` dosyasıdır. Bunlar sunucu örnekleridir; web kökünde yayınlanmaz. Örnek test hesapları gerçek üyelik sisteminizin yerine geçmez. Sunucu SDK’sı, callback sırları ve anahtarlar browser paketine girmez.

- Aynı üye yeniden açıldığında aynı ID ve bakiye görünmeli.
- İkinci açılış önceki oyuncu oturumunu kapatmalı.
- Katılım bir kez kesilmeli; tekrar istek ikinci kesinti yaratmamalı.
- Başlamamış oda iptalinde kilit bir kez iade edilmeli.
- completed ile `settlementStatus`=complete ayrılmalı; pending ödül aktarılmış gösterilmemeli.
- Iframe/modül masaüstü, fiziksel telefon ve dış ağda ayrı doğrulanmalı.

## Paketler ve sonuç kaynağı
İndirilebilir paketler genel istemci kodu ve anahtarsız örnekler içerir. Dosyaların ele geçmesi tek başına API yetkisi vermez; gerçek anahtar sızarsa iptal edip yenileyin. Minimum kapsam, IP sınırı ve kesin origin ayarlarını uygulayın.

Oyunlar mevcut public demo oturumlarıyla çalışır. Cüzdan muhasebesinin çalışması, demo sonucunu gerçek para için yetkili finansal kaynak haline getirmez. Sonuç doğrulama ve kurulum sınırları RESULT-AUTHORITY.txt rehberindedir.

## Dönem savaşları — site raporu

Günlük, haftalık ve aylık katılımları Operatör / Dönem savaşları sayfasından izle. Yalnız kendi sitenin katılımcıları, özel üye kimlikleri, tutarları ve ödülleri görünür; genel sıra tüm sitelerden hesaplanır. Personel izinleri: `rooms.read`, `players.read`, `finance.read`. Sunucudan `GET /provider/v1/competitions?kind=daily&limit=50&offset=0` (`read` kapsamı) veya `client.competitions({kind: 'daily'})` kullan. Para birimi TRY, tutarlar kuruştur. Ödenen ve bekleyen ödül ayrıdır. Dönem rehberindeki sayfalama, olay bağlamı ve paket güncelleme adımlarını uygula: [PERIOD-WARS.txt](PERIOD-WARS.txt). Iframe bağlantısı korunur; modül için güncel istemci ZIP'i gerekir.
