Bloga Geri Dön
Tutorial9 dk. okuma

FiveM Bankacılık ve ATM Script'leri: Gerçekçi Para Sistemleri

FiveM bankacılık ve ATM scriptleri ile inandırıcı bir ekonomi oluşturun. Transfer mantığı, arayüz fikirleri, en iyi ücretsiz ve premium paketler ve framework entegrasyonu.

Agency Scripts

Agency Scripts Kurucusu ve Baş Geliştiricisi

Bankacılık Sistemi Mimarisi

Bir bankacılık sistemi, basit nakit yatırmalardan oyuncular arası karmaşık transferlere ve paylaşımlı organizasyon hesaplarına kadar her şeyi yöneten, FiveM roleplay sunucularının finansal omurgasıdır. QBCore ve ESX gibi çoğu framework temel para yönetimini içerir; ancak özel bir bankacılık sistemi bunu düzgün hesap yönetimi, işlem kayıtları ve oyuncuları roleplay'in finansal yönüne çeken şık bir ATM arayüzü ile genişletir. Mimari üç katmana ayrılır: veritabanı hesap bakiyelerini ve işlem kayıtlarını saklar, server tarafı her finansal işlemi doğrular ve iş kurallarını uygular, client tarafı ise NUI aracılığıyla ATM ve banka gişesi arayüzlerini sunar. Client taraflı para manipülasyonu FiveM sunucularındaki bir numaralı exploit vektörü olduğundan, tüm para işlemleri server tarafından geçmelidir. Bakiye görüntüleme bile kurcalanabilecek önbelleğe alınmış client taraflı verilerden değil, her zaman bir server callback'inden gelmelidir.

Bankacılık İçin Veri Tabanı Şeması

Banka veritabanınızın kişisel hesapları, kuruluşlar ve işletmeler için ortak hesapları ve kapsamlı bir işlem günlüğünü desteklemesi gerekir. İşlem günlüğü isteğe bağlı değildir; çünkü hem oyunculara yönelik bir özellik hem de para açığı (exploit) incelemeleri için bir yönetici aracı olarak çifte görev görür. Yoğun sunucular yoğun saatlerde dakikada yüzlerce işlem gerçekleştirebildiğinden, şemanızı yüksek verimli işlemleri kaldıracak şekilde tasarlayın:

CREATE TABLE IF NOT EXISTS bank_accounts (
    id INT AUTO_INCREMENT PRIMARY KEY,
    account_number VARCHAR(20) UNIQUE NOT NULL,
    owner_citizenid VARCHAR(50) NOT NULL,
    account_type ENUM('personal', 'business', 'gang', 'shared') DEFAULT 'personal',
    balance BIGINT DEFAULT 0,
    account_name VARCHAR(100) DEFAULT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    is_frozen BOOLEAN DEFAULT FALSE,
    INDEX idx_owner (owner_citizenid),
    INDEX idx_type (account_type)
);

CREATE TABLE IF NOT EXISTS bank_transactions (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    account_id INT NOT NULL,
    type ENUM('deposit', 'withdraw', 'transfer_in', 'transfer_out', 'paycheck', 'purchase') NOT NULL,
    amount BIGINT NOT NULL,
    balance_after BIGINT NOT NULL,
    description VARCHAR(255) DEFAULT NULL,
    other_account VARCHAR(20) DEFAULT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_account (account_id),
    INDEX idx_created (created_at),
    FOREIGN KEY (account_id) REFERENCES bank_accounts(id)
);

CREATE TABLE IF NOT EXISTS bank_account_access (
    account_id INT NOT NULL,
    citizenid VARCHAR(50) NOT NULL,
    permission ENUM('view', 'withdraw', 'full') DEFAULT 'view',
    PRIMARY KEY (account_id, citizenid),
    FOREIGN KEY (account_id) REFERENCES bank_accounts(id)
);

The bank_account_access tablosu, birden fazla oyuncunun farklı izin seviyelerine sahip olabileceği ortak hesapları etkinleştirir. Bir çete lideri çete kasasına tam erişime sahip olabilirken, normal üyeler yalnızca bakiyeyi görüntüleyebilir. Şunu kullanarak: BIGINT bakiye alanları için kullanılması, oyuncu bakiyelerinin milyarlara ulaşabildiği şişirilmiş ekonomilere sahip sunucularda taşma sorunlarını önler.

Sunucu Taraflı İşlem Mantığı

Her finansal işlem atomic olmalı ve server üzerinde doğrulanmalıdır. Transferler sırasında paranın asla yoktan var edilmediğinden veya kaybolmadığından emin olmak için veritabanı işlemlerini (database transactions) kullanın. A oyuncusu B oyuncusuna para gönderdiğinde, hem A'dan düşme hem de B'ye ekleme işlemi birlikte başarılı olmalı veya ikisi de uygulanmamalıdır. Yeterli bakiye, dondurulmuş hesap durumu, günlük transfer limitleri ve minimum işlem tutarları için doğrulama kontrolleri uygulayın. İşte güvenli bir transfer uygulaması:

RegisterNetEvent('banking:server:transfer', function(targetAccount, amount, description)
    local src = source
    local Player = QBCore.Functions.GetPlayer(src)
    if not Player then return end

    amount = math.floor(tonumber(amount) or 0)
    if amount <= 0 then
        TriggerClientEvent('QBCore:Notify', src, 'Invalid amount', 'error')
        return
    end

    local citizenid = Player.PlayerData.citizenid
    local senderAccount = GetPlayerPrimaryAccount(citizenid)

    if not senderAccount or senderAccount.is_frozen then
        TriggerClientEvent('QBCore:Notify', src, 'Account unavailable', 'error')
        return
    end

    if senderAccount.balance < amount then
        TriggerClientEvent('QBCore:Notify', src, 'Insufficient funds', 'error')
        return
    end

    -- Check daily transfer limit
    local todayTransfers = GetDailyTransferTotal(senderAccount.id)
    if todayTransfers + amount > Config.DailyTransferLimit then
        TriggerClientEvent('QBCore:Notify', src, 'Daily limit exceeded', 'error')
        return
    end

    -- Atomic transfer using database transaction
    local success = MySQL.transaction.await({
        {
            query = 'UPDATE bank_accounts SET balance = balance - ? WHERE id = ? AND balance >= ?',
            values = {amount, senderAccount.id, amount}
        },
        {
            query = 'UPDATE bank_accounts SET balance = balance + ? WHERE account_number = ?',
            values = {amount, targetAccount}
        },
        {
            query = 'INSERT INTO bank_transactions (account_id, type, amount, balance_after, description, other_account) VALUES (?, "transfer_out", ?, (SELECT balance FROM bank_accounts WHERE id = ?), ?, ?)',
            values = {senderAccount.id, amount, senderAccount.id, description or 'Transfer', targetAccount}
        },
    })

    if success then
        TriggerClientEvent('QBCore:Notify', src, 'Transfer complete: $' .. amount, 'success')
        TriggerClientEvent('banking:client:refreshBalance', src)
    else
        TriggerClientEvent('QBCore:Notify', src, 'Transfer failed', 'error')
    end
end)

Şuna dikkat edin: WHERE balance >= ? düşme sorgusundaki (deduction query) koşul, aynı andaki iki transferin hesabı eksiye düşürebileceği race condition durumlarına karşı son bir koruma görevi görür. Bakiyeyi zaten Lua tarafında doğruluyor olsanız bile bu veritabanı düzeyindeki kontrol gereklidir, çünkü kontrolünüz ile gerçek güncelleme arasına birden fazla istek girebilir.

ATM Kullanıcı Arayüzü

ATM arayüzü, temel bankacılık işlevlerine hızlı erişim sağlayan kompakt bir NUI panelidir: bakiye kontrolü, nakit yatırma, nakit çekme ve para transferi. Tasarımı sade ve tanıdık tutun, çünkü oyuncular içgüdüsel olarak bir ATM'nin gerçek dünyadaki karşılığı gibi çalışmasını bekler. Güncel bakiyeyi üstte belirgin şekilde gösterin ve her işlem için eylem butonlarını alt kısma yerleştirin. Yatırma ve çekme görünümleri, özel miktar giriş alanının yanı sıra $100, $500, $1000 ve $5000 gibi yaygın değerler için önceden ayarlanmış miktar butonları içermelidir. Transferler için alıcı hesap numarası ve miktar alanlarının yanında isteğe bağlı bir açıklama alanı sağlayın. Yanlışlıkla yapılan tıklamaların oyunculara para kaybettirmesini önlemek için herhangi bir işlemi yürütmeden önce bir onay adımı gösterin. Oyuncuların tam bir banka şubesini ziyaret etmelerine gerek kalmadan finansal aktivitelerini doğrulayabilmeleri için son 10 kaydı gösteren bir son işlemler listesi ekleyin. ATM arayüzü seri hissettirmelidir, bu nedenle her bilgi parçası için ayrı istekler yapmak yerine menü açıldığında bakiye ve işlem verilerini tek bir callback ile alın.

ATM Etkileşim Kurulumu

ATM etkileşim noktalarını tüm GTA haritasındaki mevcut ATM prop konumlarına yerleştirin. FiveM, oyun dünyasındaki tüm ATM prop'larını bulmak için üzerinden geçebileceğiniz bir ATM model hash listesi sağlar. Temiz bir etkileşim için ox_target gibi bir hedef sistemi kullanın veya her bir ATM prop'unun yakınında mesafe kontrollerine geri dönün. Oyuncu bir ATM ile etkileşime girdiğinde, oyuncunun ATM'yi kullandığı bir animasyon oynatın ve ardından NUI panelini açın:

local atmModels = {
    'prop_atm_01', 'prop_atm_02', 'prop_atm_03',
    'prop_fleeca_atm', 'v_5_b_atm1'
}

-- Using ox_target for ATM interaction
for _, model in ipairs(atmModels) do
    exports.ox_target:addModel(GetHashKey(model), {
        {
            name = 'use_atm',
            icon = 'fas fa-credit-card',
            label = 'Use ATM',
            onSelect = function(data)
                local ped = PlayerPedId()
                local atmCoords = GetEntityCoords(data.entity)

                -- Face the ATM
                TaskTurnPedToFaceCoord(ped, atmCoords.x, atmCoords.y, atmCoords.z, 1000)
                Wait(1000)

                -- Play ATM animation
                RequestAnimDict('mini@atmenter')
                while not HasAnimDictLoaded('mini@atmenter') do Wait(10) end
                TaskPlayAnim(ped, 'mini@atmenter', 'enter', 8.0, -8.0, -1, 0, 0, false, false, false)

                -- Open ATM UI
                QBCore.Functions.TriggerCallback('banking:server:getAccountData', function(data)
                    SetNuiFocus(true, true)
                    SendNUIMessage({
                        action = 'openATM',
                        balance = data.balance,
                        transactions = data.recentTransactions,
                        accountNumber = data.accountNumber
                    })
                end)
            end
        }
    })
end

İşlem Geçmişi ve Hesap Özetleri

İşlem geçmişi, bankacılık sisteminizi basit bir para yatırma ve çekme aracından tam teşekküllü bir finansal yönetim aracına dönüştürür. Oyuncular, banka şubelerinde tarih aralığına, işlem türüne veya tutara göre filtrelenmiş eksiksiz işlem geçmişlerini görüntüleyebilmelidir. Her işlem kaydı: tarihi, türü, tutarı, kalan bakiyeyi, açıklamayı ve transferlerde karşı tarafı göstermelidir. Sayfalandırmayı sunucu tarafında uygulayın, çünkü binlerce işlemi aynı anda yüklemek NUI çerçevesini dondurur ve sunucu bellek kullanımını aniden yükseltir. Sayfa başına 20 ila 30 işlem döndürün ve oyuncunun ihtiyaç duydukça daha fazlasını yüklemesine izin verin. Banka şubeleri için, yeni hesap açma, ortak hesap izinlerini yönetme, belirli bir dönem için hesap dökümü oluşturma ve sunucunuz bu mekaniği destekliyorsa kredi başvurusu yapma gibi ATM'lerin sunduklarının ötesinde ek özellikler sunun. İşlem açıklamalarını okunabilir metin dizgileri olarak saklayın: böylece işlerden, mağaza alışverişlerinden ve devlet vergilerinden gelen otomatik işlemlerin tümü oyuncuların bağlam olmadan da anlayabileceği net kayıtlar olarak görünür.

Banka Soygunu Mekanikleri

Banka soygunları; suçluları, polisi, rehine arabulucularını ve çevredeki sivilleri içeren yüksek riskli senaryolar yaratarak herhangi bir roleplay sunucusundaki en heyecan verici etkinliklerden biridir. İyi tasarlanmış bir soygun sistemi birden fazla aşama içerir: bankayı keşfetme, soygunu başlatma, minigame'ler aracılığıyla güvenlik sistemlerini hack'leme veya delme, ganimeti yükleme ve polisin takibinde kaçış. Hangi bankaların soyulabileceğini, zorluk derecelerini, bekleme sürelerini ve gerekli eşyaları tanımlayarak başlayın. Soygun; kasa kapıları için termit, güvenlik panelleri için hack cihazları ve ganimeti taşımak için spor çantaları gibi belirli araçlar gerektirmelidir. Her güvenlik katmanı için kademeli zorlukta minigame'ler uygulayın; burada başarısız bir hack ek alarmları tetikler veya kasayı daha da kilitler:

Config.BankRobberies = {
    ['fleeca_1'] = {
        label = 'Fleeca Bank - Legion Square',
        coords = vector3(149.73, -1042.65, 29.37),
        vault = vector3(144.87, -1044.16, 29.37),
        tier = 1,  -- 1=Fleeca, 2=Paleto, 3=Pacific Standard
        cooldown = 7200,  -- 2 hours
        minPolice = 3,
        requiredItems = {'electronickit', 'thermite'},
        reward = { min = 40000, max = 80000, markedBills = true },
        securityLayers = {
            { type = 'hack', difficulty = 'easy', time = 30 },
            { type = 'thermite', time = 10 },
            { type = 'drill', time = 45 },
        },
    },
    ['pacific_standard'] = {
        label = 'Pacific Standard Bank',
        coords = vector3(255.85, 225.60, 101.88),
        vault = vector3(262.20, 222.10, 101.68),
        tier = 3,
        cooldown = 14400,  -- 4 hours
        minPolice = 6,
        requiredItems = {'electronickit', 'thermite', 'advancedlaptop'},
        reward = { min = 200000, max = 400000, markedBills = true },
        securityLayers = {
            { type = 'hack', difficulty = 'hard', time = 20 },
            { type = 'hack', difficulty = 'hard', time = 20 },
            { type = 'thermite', time = 8 },
            { type = 'drill', time = 60 },
            { type = 'hack', difficulty = 'expert', time = 15 },
        },
    },
}

Soygun ödülü olarak temiz nakit yerine işaretli paralar kullanın; böylece suçluları kara para aklama noktaları veya kirli para takasları gibi ek oynanış döngüleriyle parayı aklamaya zorlayın. Bu, soygun rolünü soygunun kendisinin ötesine taşır ve polis soruşturmaları için fırsatlar yaratır. Bir soygun başladığında polis dispatch sistemine bildirim gönderin ve soygun ilerlemesini sunucu tarafında takip edin, böylece memurlar suçluların ne kadar ilerlediğine bağlı olarak taktiksel müdahalede bulunabilir.

Güvenlik ve Anti-Exploit Önlemleri

Finansal sistemler hile yapanlar için birincil hedeftir, çünkü para doğrudan oyun içi güce dönüşür. Daha önce bahsedilen sunucu tarafı doğrulamanın ötesinde, birkaç ek güvenlik katmanı uygulayın. Tek bir oyuncunun saniyede yüzlerce yatırma veya transfer isteği gönderememesi için tüm bankacılık eventlerine rate limiting ekleyin. Yöneticilerin para akışını takip edebilmesi ve kopyalama açıklarını tespit edebilmesi için her finansal işlemi kaynak oyuncunun kimlik bilgileri ve zaman damgasıyla günlüğe kaydedin. Açıklar keşfedildiğinde yöneticilerin hileli işlemleri geri alabilmesi için bir işlem tersine çevirme sistemi uygulayın. Oyuncunun hesap yaşı ve toplam oyun süresiyle orantılı olarak değişen maksimum tek işlem limitleri ve günlük kümülatif limitler belirleyin, böylece yeni oluşturulan hesaplar kara para aklama için daha az elverişli hale gelir. İki hesap arasında hızlı karşılıklı transferler, başka bir oyuncudan saniyeler içinde çekilen miktarla birebir eşleşen yatırmalar veya ilgili işlem kaydı olmaksızın bakiye artışları gibi şüpheli kalıpları izleyin. Şüpheli bir etkinlik tespit edildiğinde Discord webhook uyarıları gönderin, böylece moderasyon ekibiniz oyuncu raporlarını beklemeden gerçek zamanlı olarak inceleme yapabilir. Yöneticilerin soruşturma sırasında hesapları kilitleyebileceği dondurulmuş hesap sistemi uygulamayı düşünün, bu sayede sorun çözülürken istismar edilen paranın harcanması veya transfer edilmesi engellenir.

Sunucu Ekonomisiyle Entegrasyon

Banka sisteminiz, sunucudaki tüm para akışının merkezi noktası olarak hizmet vermelidir. Meslek maaşlarını banka sistemi üzerinden yönlendirin; böylece oyuncular maaşlarını, hangi işin ne kadar ödeme yaptığını gösteren net bir işlem kaydıyla birlikte banka mevduatı olarak alır. Oyuncular nakit yerine kartla ödeme yaptıklarında bankadan para çekilmesini tetikleyecek şekilde mağaza alışverişlerini bağlayın; bu sayede gerçekçilik katan ve oyunculara bankacılık sistemini basit bir depolamanın ötesinde kullanmaları için bir neden sunan bir işlem geçmişi oluşturun. Emlak vergileri, araç sigortası ve işletme giderleri gibi düzenli aralıklarla oyuncunun banka hesabından düşülen tekrarlayan maliyetler için otomatik faturalandırma uygulayın. Bir oyuncunun hesabında otomatik ödeme için yetersiz bakiye varsa, sistem başarısız bir ödeme kaydetmeli ve mülk haciz uyarıları veya sigorta iptalleri gibi sonuçları tetiklemelidir. Banka sistemini telefon resource'unuza bağlayın; böylece oyuncular bir ATM'yi veya banka şubesini fiziksel olarak ziyaret etmeden bakiyelerini kontrol edebilir, son işlemleri görüntüleyebilir ve hızlı transferler yapabilir. Bu entegrasyon, bankacılık sistemini yalıtılmış bir özellikten çıkarıp sunucunuzdaki her ekonomik faaliyeti birbirine bağlayan finansal bir sinir sistemine dönüştürür.

Eşleşen script

Sunucunuz için hazır, güncellemeler dahil.

Başlamaya Hazır mısınız?

Scriptleri mağazamızdan edinin veya destek, güncellemeler ve gelecek yeniliklere göz atmak için Discord'a katılın.