Ana Sayfa / Blog / E-fatura (GIB) WooCommerce entegrasyonu

E-fatura (GIB) WooCommerce entegrasyonu

Türkiye'de belirli bir ciroyu geçen e-ticaret siteleri e-fatura kesmek zorunda. WooCommerce'te GIB entegrasyonunun pratik adımları, popüler provider'lar, dikkat edilecek şey.

Türkiye’de ciro eşiğini geçen işletmeler e-Fatura mükellefi oluyor. Eski kağıt faturalar yerine GIB (Gelir İdaresi Başkanlığı) portalı üzerinden dijital fatura kesilmesi zorunlu.

WooCommerce’te e-fatura entegrasyonu 2 müşteri için yaptım. Süreç manuel’den otomatik’e geçerken öğrendiklerim.

E-fatura mı e-arşiv mi

İkisinin farkını bilmek ilk adım:

e-Fatura: iki e-fatura mükellefi arasında kesiliyor. B2B. Alıcının GIB’de kayıtlı olması gerekli.

e-Arşiv: e-fatura mükellefinin e-fatura mükellefi olmayan alıcılara kestiği fatura. B2C çoğunluk. Alıcı GIB’de kayıtlı değilse otomatik e-arşiv.

WooCommerce e-ticaret genelde B2C. Her siparişte e-arşiv default, ama müşteri vergi kimlik veriyorsa ve e-fatura mükellefi ise e-fatura kesiliyor.

Backend tarafında: müşterinin e-fatura mükellefi olup olmadığını GIB API’si ile sorgulamanız gerekiyor. Her sipariş için.

Özel entegratör şart

GIB’e doğrudan API erişimi büyük kurumlar için. Küçük-orta işletme “özel entegratör” üzerinden gidiyor. Türkiye’de yaygın entegratörler:

  • Uyumsoft
  • Logo (eLogo)
  • BizimHesap
  • Paraşüt
  • Foriba (artık iyzico altında)
  • Netsis

Seçerken bakılacaklar:
– API kalitesi (REST/SOAP, dokümantasyon)
– Aylık/yıllık komisyon ve fatura başı ücret
– WooCommerce entegrasyon plugin var mı
– Customer support hızı (GIB reject durumları için)
– Portal kullanım kolaylığı (müşterinizin muhasebe ekibi de kullanacak)

Ben genelde Paraşüt veya Uyumsoft tercih ediyorum. API’leri modern, support iyi.

Entegratör onboarding süreci

Her entegratör farklı ama benzer pattern:

  1. Sözleşme imzalama (genelde 1-2 gün)
  2. Test environment credential’ları
  3. Production request (birkaç gün GIB validation)
  4. Production credential’ları
  5. İlk gerçek fatura testing

Bu süreç 1-3 hafta sürüyor. E-ticaret launch tarihi planlarken buffer bırakın.

WooCommerce integration pattern

Order tamamlandığında (payment success, status = processing or completed) e-fatura otomatik kesilir.

Hook:

add_action('woocommerce_order_status_processing', 'create_e_invoice_for_order', 10, 1);

function create_e_invoice_for_order($order_id) {
    $order = wc_get_order($order_id);
    
    // TCKN/VKN alıp müşteri tipi belirle
    $tax_id = $order->get_meta('_billing_tax_id');
    $is_company = !empty($order->get_billing_company());
    
    // GIB mükellef sorgusu
    $is_efatura_mukellefi = check_gib_taxpayer($tax_id);
    
    $invoice_type = ($is_efatura_mukellefi && $is_company) ? 'FATURA' : 'E_ARSIV_FATURA';
    
    // Entegratör API'sine gönder
    $invoice_data = build_invoice_payload($order, $invoice_type);
    $result = send_to_integrator($invoice_data);
    
    if ($result->success) {
        $order->update_meta_data('_e_invoice_number', $result->invoice_number);
        $order->update_meta_data('_e_invoice_uuid', $result->uuid);
        $order->save();
    } else {
        // Fail - alarm, manuel intervention
        error_log("e-invoice failed for order {$order_id}: {$result->error}");
        $order->add_order_note("e-fatura kesilemedi: {$result->error}");
    }
}

Mutlaka dikkat: alan isimleri

GIB şema’sı XML tabanlı ve alan isimleri hassas. Hata yaparsanız fatura reject oluyor.

Kritik alanlar:

  • Ünvan/Ad Soyad: company=unvan, individual=ad+soyad ayrı
  • Vergi Dairesi: zorunlu (e-fatura’da)
  • Adres: il, ilçe, mahalle, sokak ayrı field. Tek string olmaz
  • KDV oranı: %0, %1, %8, %18, %20 (2024 değişti). Her ürüne göre farklı olabilir
  • Para birimi: TRY default, USD/EUR için kur bilgisi gerekli
  • Ödeme tipi: kart, havale, kapıda ödeme, vs kod olarak

Malum rakamlardan çok ufak hatalar (kuruş rounding) fatura reject sebebi olabiliyor.

KDV hesaplama: kuruş kaybolmasın

KDV hesaplamada float arithmetic güvenilmez. 100.00 * 0.18 = 18.0000001 olabiliyor, round yanlış çıkıyor.

Her zaman integer kuruş ile çalışın:

$price_kurus = (int) round($price_tl * 100);
$kdv_kurus = (int) round($price_kurus * $kdv_rate);
$total_kurus = $price_kurus + $kdv_kurus;

Fatura response’unda total amount’unun 1 kuruş sapma ile sizinki ile match etmediğini göreceksiniz. Rounding matematiği consistent olmalı.

Iptal ve iade

Fatura kesilince iptal / iade süreci karmaşık:

İptal: fatura kesildiği gün içinde mümkün, daha sonra iade faturası gerekiyor.

İade: iade faturası ayrı bir fatura. Eksi tutarlı, original fatura reference’ı ile.

WooCommerce’te refund event’i:

add_action('woocommerce_order_refunded', 'create_refund_invoice', 10, 2);

function create_refund_invoice($order_id, $refund_id) {
    $order = wc_get_order($order_id);
    $refund = wc_get_order($refund_id);
    
    $original_invoice_uuid = $order->get_meta('_e_invoice_uuid');
    
    $refund_data = [
        'type' => 'IADE_FATURA',
        'original_uuid' => $original_invoice_uuid,
        'amount' => $refund->get_amount(),
        // ...
    ];
    
    send_to_integrator($refund_data);
}

Mukellef query rate limit

Her sipariş için GIB mükellef sorgusu yaparsanız rate limit’e takılıyorsunuz. Entegratörler cache’liyor ama siz de cache’leyin:

function check_gib_taxpayer($tax_id) {
    $cache_key = "gib_taxpayer_{$tax_id}";
    $cached = get_transient($cache_key);
    if ($cached !== false) return $cached;
    
    $result = integrator_api->check_taxpayer($tax_id);
    set_transient($cache_key, $result, WEEK_IN_SECONDS);
    return $result;
}

Mükellef statüsü seyrek değişiyor (yıllık GIB listesi), 1 hafta cache fine.

Fatura arşivi

GIB regulation: 10 yıl arşiv zorunluluğu. Entegratör bunu yapıyor ama siz de yedek tutun.

Her başarılı fatura için:
– UUID kaydet (order meta)
– PDF download edin ve wp-content/uploads/invoices/ altına kaydedin
– ZIP file aylık backup

Entegratör şirketi batsaydı (rare ama olmuş), 10 yıllık data geri almanın zor olduğu senaryo var. Kendi backup’ınız önemli.

Reporting: aylık raporlar

Muhasebe ekibi aylık fatura raporu istiyor. WooCommerce admin’de custom page:

  • Tarih aralığına göre kesilen tüm faturalar
  • Sum total, KDV total
  • Iptal/iade olanlar ayrı
  • CSV export

Custom plugin 1-2 günde yazılıyor, muhasebe ekibinin iş yükünü çok hafifletiyor.

Customer-facing: fatura indirme

Müşteri my-account sayfasında kendi fatura’sını indirebilmeli:

add_action('woocommerce_account_orders_endpoint', 'add_invoice_download_button');

function add_invoice_download_button($order) {
    $uuid = $order->get_meta('_e_invoice_uuid');
    if ($uuid) {
        echo '<a href="' . get_invoice_pdf_url($uuid) . '">Faturayı İndir</a>';
    }
}

PDF URL entegratör üzerinden veya self-hosted. Download için auth check gerekli – sadece order sahibi indirebilmeli.

Yaygın sorunlar

1. Address field eksik. Çoğu müşteri checkout’ta adres field’ları dolduruyor ama yeterli granularity yok. Mahalle eksik olabiliyor. Checkout’u extend edin.

2. TCKN/VKN validation. Müşteri yanlış tax ID giriyor. Client-side checksum validation ekleyin (algoritma public).

3. Reject recovery. Fatura reject oldu. Muhasebe ekibi problem’i fix etmeli (adres, item description), retry etmeli. Admin panelde reject list + retry button kritik.

4. Vergi daireleri. Her ilin vergi daireleri listesi değişiyor. Entegratör güncellenmiş liste tutar ama manuel sync gerekebiliyor.

Son tavsiye

E-fatura entegrasyonu e-ticaret launch öncesi yapılmalı, launch sonrası eklemek 2 hafta boyunca manuel fatura kesmek demek (her sipariş için).

Özel entegratör seç, plugin varsa kullan, custom logic’i hook’larla ekle, reject recovery UI kur, backup disciplinle geleceği koru.

Türkiye e-ticaretinde kaçınılmaz bir zorunluluk. Doğru yapıldığında invisible çalışıyor, yanlış yapıldığında operation nightmare.

Bu konuda bir projeniz mi var?

Kısa bir özet bırakın, 24 saat içinde size dönüş yapayım.

İletişime Geç