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:
- Sözleşme imzalama (genelde 1-2 gün)
- Test environment credential’ları
- Production request (birkaç gün GIB validation)
- Production credential’ları
- İ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.