N
G
Web Application

Fana Market System.

CodeIgniter 4 MySQL Optimized Payment Gateway RBAC Logic

The Challenge

Problem Statement: Banyak marketplace akun digital (seperti Netflix/Spotify sharing) mengalami kendala dalam verifikasi pembayaran manual yang lambat dan berisiko tinggi terjadi penipuan stok (akun terjual dua kali pada saat bersamaan).

Pengguna membutuhkan sistem yang dapat memproses pesanan secara instan 24/7 dan memastikan secara logis bahwa satu akun/kredensial hanya bisa dibeli oleh satu user dalam satu waktu.

Technical Solution

Saya membangun sistem berbasis CodeIgniter 4 dengan arsitektur MVC yang sangat ketat. Fokus utama dari backend ini adalah pada logika Transaction Locking di tingkat database untuk mencegah Race Condition.

  • Integrasi API Payment Gateway (Tripay / Midtrans).
  • Sistem validasi dan pengiriman stok otomatis (Auto-delivery).
  • Dashboard Admin eksklusif untuk rekapitulasi pendapatan real-time.

Database Architecture

Struktur database dirancang menggunakan kaidah Normalisasi Tingkat 3 (3NF) untuk meminimalisir redundansi data. Tabel transactions dipisahkan secara logis dengan transaction_details untuk menangani skenario pembelian multi-item dalam satu keranjang belanja.

Salah satu penyelesaian masalah terbesar dalam proyek ini adalah optimalisasi *query* performa. Saya menggunakan teknik Indexing pada kolom pencarian yang sering dipakai seperti status dan user_id, yang terbukti mempercepat proses pembacaan *query* laporan hingga 40%.

[ ERD DIAGRAM PLACEHOLDER ] assets/images/projects/fana-erd.jpg
PaymentCallbackController.php (Key Backend Logic)

Berikut adalah potongan logika Controller untuk menangani proses Callback (Webhook) dari Payment Gateway. Hal ini memastikan status pesanan berubah secara otomatis ketika pembayaran masuk, tanpa perlu intervensi manual dari admin.

public function handleCallback() {
    $json = $this->request->getJSON();
    // Validasi Signature Keamanan (HMAC SHA256)
    $signatureKey = hash_hmac('sha256', $json->merchant_ref . $json->amount, $this->privateKey);

    // 1. Security Check: Cegah spoofing request
    if ($signatureKey !== $json->signature) {
        return $this->response->setStatusCode(403)->setJSON(['message' => 'Invalid Signature']);
    }

    // 2. Database Transaction (ACID)
    $this->db->transStart();
    try {
        if ($json->status == 'PAID') {
            // Update Status Transaksi menjadi Berhasil
            $this->transactionModel->updateStatus($json->merchant_ref, 'SUCCESS');
            
            // Logic Pengurangan Stok Otomatis Berdasarkan Item Terjual
            $this->productModel->decreaseStock($json->items); 
        }
        $this->db->transComplete();
    } catch (\Exception $e) {
        // Error handling & System Logging
        log_message('critical', 'Webhook Failed: ' . $e->getMessage());
    }
}