İçeriğe geç
Docs

Fatura Uygulamaları

Tecof’un fatura uygulamaları, kurumsal/bireysel alıcı, ortak invoice metafield’ı, para kuralları ve @tecof/invoice-kit.

Son güncelleme:

Tecof'ta fatura kesen her uygulama aynı sipariş verisini okur, aynı para kurallarını uygular ve faturanın durumunu siparişe aynı biçimde yazar. Böylece mağaza hangi entegratörü seçerse seçsin fatura tutarı aynı çıkar; kargo, muhasebe ya da raporlama uygulamaları da faturanın kesilip kesilmediğini sağlayıcıyı bilmeden öğrenir.

Bu sayfa üç şeyi anlatır: Tecof'un kendi fatura uygulamaları, fatura yazan bir uygulamanın uyması gereken ortak kurallar ve bu kuralları hazır veren @tecof/invoice-kit paketi.


Tecof'un Fatura Uygulamaları#

Hepsi platform uygulamasıdır (integration: "platform"): kimlik bilgileri Vault'ta şifreli durur, siparişler webhook ile gelir, sipariş ekranlarında aksiyon sunar. Her birinin deposunda kurulum, ayarlar ve sınırları anlatan kendi README'si bulunur.

UygulamaSlugBelgeModlarFatura numarasıSipariş iptal/iade edilince
Logo İşbaşıisbasiİşbaşı satış faturasıkapalı · taslak · kesİşbaşıİşaretle ya da yalnız taslağı sil
GİB e-Arşiv Portalıearsive-Arşiv (portal)kapalı · taslak (imza portalda)GİBİşaretle ya da imzasız taslağı sil
ParaşütparasutSatış faturası, isteğe bağlı e-Arşiv / e-Faturakapalı · fatura · e-belgeParaşütİşaretle ya da e-belgesi olmayan faturayı iptal et
EDM Bilişimedme-Fatura / e-Arşiv (UBL-TR)kapalı · taslak · gönderEDMİşaretle ya da e-Arşiv'i koşullu iptal et
QNB eSolutionsqnbe-Fatura / e-Arşiv (UBL-TR)kapalı · gönderQNBİşaretle (iptal QNB portalında)
KolayBikolaybiSatış faturası, isteğe bağlı e-Arşiv / e-Faturakapalı · fatura · e-belgeKolayBiİşaretle ya da resmileşmemiş ve tahsilatı olmayan faturayı sil

Ortak davranışlar:

  • Tetikleyici: order.paid, order.fulfilled ya da yalnız elle (manual).
  • Aksiyonlar: sipariş detayında önizleme, oluşturma, yeniden deneme ve PDF çekmecesi (order.detail, iframe); sipariş listesinde "Seçilenleri faturala" (order.list, api, en fazla 50 sipariş).
  • e-Fatura mı e-Arşiv mi: e-belge kesen uygulamalar alıcının e-Fatura mükellefiyetini sağlayıcıya sorar; mükellefe e-Fatura, diğerlerine e-Arşiv keser. Anonim ve yurt dışı alıcı sorgulanmadan e-Arşiv alır. Hangi alıcıların sorgulandığı sağlayıcıya göre değişir: İşbaşı ve Paraşüt yalnız kurumsal alıcıyı, EDM ve QNB kimlik numarası olan her yurt içi alıcıyı sorgular. KolayBi API'si mükellef sorgusu sunmadığı için belge türünü KolayBi belirler. Sorgu hata verirse belge kesilmez; mükellefe yanlışlıkla e-Arşiv gitmesin diye e-Arşiv'e düşülmez.
  • Çift fatura koruması: uygulama, sağlayıcıyı çağırmadan önce siparişi creating olarak işaretler. Zaman aşımı ya da yarım kalan denemeden sonra önce sağlayıcıda sipariş numarası veya belge UUID'siyle arar; belge varsa onu benimser, yoksa yeniden dener.

e-Fatura bu uygulamaların hiçbirinde otomatik iptal edilmez; düzeltme iade faturasıyla yapılır. e-Arşiv'i otomatik iptal eden tek uygulama EDM'dir: tam iptal ya da iade olması, fatura tarihinden itibaren 7 gün içinde kalınması ve EDM'deki belge durumunun iptale izin vermesi gerekir.


Kurumsal ve Bireysel Alıcı#

Checkout'ta müşteri Bireysel ya da Kurumsal fatura seçer. Seçim sipariş nesnesinin billingAddress alanına yazılır (Siparişler):

AlanBireyselKurumsal (Türkiye)Kurumsal (yurt dışı)
invoiceType"individual""corporate""corporate"
companyboş olabilirUnvan, zorunluUnvan, zorunlu
taxNumberboş10 haneli VKN ya da şahıs şirketi için 11 haneli TCKN; sağlama hanesi doğrulanırSerbest biçim (harf, rakam, -; en fazla 30)
taxOfficeboşZorunluZorunlu değil
identityNumberTCKN; yoksa anonim 11111111111——

Checkout bu kurallara uymayan siparişi 400 invalid-invoice-identity ile reddeder. Yine de eski siparişlerde ya da elle oluşturulan kayıtlarda tutarsız veri bulunabileceği için fatura uygulamaları alıcıyı kendileri sınıflandırmalıdır. classifyBuyer bunu tek adımda yapar (aşağıda).


Ortak Fatura Durumu#

Her fatura uygulaması sipariş başına tek bir paylaşılan metafield yazar. Panel bu alanı sipariş detayındaki "Uygulamalar" kartında gösterir. Aynı mağazadaki diğer uygulamalar orders:read kapsamıyla GET /api/v1/metafields?ownerType=order&ownerId=… üzerinden okuyabilir; yanıtta kendi alanlarının yanında öteki uygulamaların paylaşılan alanları da gelir.

ÖzellikDeğer
ownerType"order"
namespaceUygulamanın slug'ı (isbasi, parasut, …)
key"invoice"
type"json"
visibility"shared"
panel{ label: { tr, en }, show: true }
JSON
{
  "status": "issued",
  "documentType": "e-arsiv",
  "invoiceNumber": "ABC2026000000123",
  "uuid": "0b6c6f0e-3a7d-4a35-9a4e-5f2f6b1c9d10",
  "updatedAt": "2026-10-10T09:17:02.000Z"
}

status sözlüğü bütün fatura uygulamalarında aynıdır:

DurumAnlamı
creatingTalep alındı, sağlayıcıya gönderiliyor
draftSağlayıcıda taslak olarak duruyor
issuedKesildi; e-belgeyse GİB'e gönderildi
signedİmzalandı (portal akışlarında)
failedBaşarısız; error alanında temizlenmiş neden
skippedBilerek atlandı; neden reason alanında (örn. total-mismatch, non-try-currency, ayar kapalı)
needs-cancellationSipariş iptal ya da iade edildi; belgenin iptali elle yapılmalı
deletedTaslak silindi
cancelledSağlayıcıda iptal edildi

Değerde kişisel veri tutulmaz: alıcı adı, adresi ya da tam vergi numarası metafield'a ve olay yüküne yazılmaz.

Uygulamalar ayrıca şu olayları yayınlar; dinleyen uygulama app.<slug>. önekiyle abone olur:

OlayNe zaman
app.<slug>.invoice.createdFatura ya da taslak oluştu
app.<slug>.invoice.failedDeneme başarısız oldu
app.<slug>.invoice.cancelledBelge silindi ya da sağlayıcıda iptal edildi
TypeScript
// Kargo uygulaması: faturası kesilmemiş siparişi kargoya vermeden önce uyarır
const fields = await api.metafields.list({ ownerType: "order", ownerId: orderId });
const issued = fields.some((m) => m.key === "invoice" && ["issued", "signed"].includes(m.value?.status));

Ortak Para Kuralları#

Fatura yazan bir uygulama, sipariş toplamıyla birebir aynı faturayı üretmek zorundadır. Kurallar @tecof/invoice-kit içinde uygulanmıştır; kendi hesaplamanızı yazıyorsanız aynılarını izleyin.

  • Satır KDV modu önce satırdan (taxIncluded), sonra siparişten (totals.pricesIncludeTax) okunur. Oranı null olan eski satırlarda mağaza varsayılanı kullanılır.
  • KDV matrahı indirim sonrası tutardır. Sipariş, her satıra düşen indirimi lineItems[].discountAmount alanında taşır; faturayı bu paylarla kurun. Kapsamlı kupon yalnız kendi satırlarına düşer. Eski siparişlerde pay yoksa indirimi ürün satırlarına tutarla orantılı dağıtın. İndirim kargo ve ödeme ücretine düşmez.
  • Kargo ve ödeme ek ücreti ayrı hizmet satırıdır. Oranı bilinmeyen kargo KDV dahil sayılır.
  • Hediye çeki ödeme aracıdır, indirim değildir: fatura tam tutardan kesilir.
  • Mutabakat: küçük kuruş farkları (varsayılan max(0,05; 0,01 × satır sayısı)) en büyük satırda düzeltilir. Fark bu toleransı aşarsa total-mismatch uyarısı oluşur.
  • total-mismatch olan sipariş otomatik ve toplu faturalamada atlanır (status: "skipped", reason: "total-mismatch"). Mağaza sipariş çekmecesinde farkı görüp onaylayarak "Farka rağmen oluştur" diyebilir.
  • TRY dışı sipariş: Paraşüt ve KolayBi uygulamaları ayar açıksa döviz faturasını TCMB kuruyla keser; diğer uygulamalar bu sürümde yalnız TRY faturalar ve döviz siparişini skipped olarak işaretler. toInvoiceDraft döviz siparişinde kur ister (exchange-rate-missing).

@tecof/invoice-kit#

Siparişi (GET /api/v1/orders/:id) doğru bir Türk faturasına çeviren, bağımlılıksız TypeScript paketidir. Tecof'un bütün fatura uygulamaları bunu kullanır.

Terminal
npm install @tecof/invoice-kit
TypeScript
import { toInvoiceDraft, buildUblInvoice } from "@tecof/invoice-kit";

const order = await api.orders.get(orderId);
const draft = toInvoiceDraft(order, { defaultVatRate: 20 });

if (draft.warnings.some((w) => w.code === "total-mismatch")) {
  // Otomatik akışta atla; kararı mağazaya bırak
}

// e-Fatura / e-Arşiv entegratörü UBL bekliyorsa
const xml = buildUblInvoice(draft, {
  profile: "EARSIVFATURA",
  typeCode: "SATIS",
  uuid: crypto.randomUUID(),
  supplier,
});
Dışa aktarımNe yapar
toInvoiceDraft(order, options?)Alıcı, satırlar, KDV dökümü, toplamlar, düzenleme tarihi (Europe/Istanbul) ve uyarılar. Hata fırlatmaz; faturayı kesip kesmemek çağıranın kararıdır
classifyBuyer(order)corporate, individual, anonymous ya da foreign; kimlik numarası, unvan, vergi dairesi ve uyarılar
buildUblInvoice(draft, options)İmzasız UBL-TR 1.2 fatura XML'i (TEMELFATURA, TICARIFATURA, EARSIVFATURA)
isValidVkn, isValidTcknSağlama hanesi doğrulaması; checkout ile aynı algoritma
amountInWords(tutar)"Yalnız Bin İki Yüz Otuz Dört Türk Lirası Elli Kuruş"
suggestEArchivePaymentMethod(provider)Tecof ödeme sağlayıcısını GİB ödeme şekline çevirir

Alıcı sınıflandırması:

  1. Fatura adresi yurt dışıysa foreign olur. Kurumsalda kimlik 2222222222 kullanılır, alıcının kendi vergi numarası nota ve UBL'e ayrıca yazılır.
  2. invoiceType: "corporate" ve geçerli VKN ya da TCKN varsa corporate olur. Numara geçersizse bireysel kurala düşer ve tax-number-invalid uyarısı oluşur.
  3. Geçerli TCKN varsa individual, yoksa anonymous (11111111111) olur.

Bilinen sınırlar: ihracat, tevkifat, ÖTV ve özel matrah faturaları desteklenmez. Paket belgeyi imzalamaz ve zarf üretmez; bunlar entegratörün işidir. Alıcının e-Fatura mükellefi olup olmadığını da sorgulamaz; bunu entegratörden öğrenmeniz gerekir.


Kendi Fatura Uygulamanızı Yazarken#

  • Kimlik bilgilerini yalnız Vault'ta tutun; arayüze ve günlüklere maskeli yazın.
  • Sağlayıcı adresi ayarlanabiliyorsa yalnız https ve sağlayıcının kendi alan adlarına izin verin. Aksi hâlde saklanan kimlik bilgileri başka bir sunucuya gönderilebilir.
  • Siparişi her zaman kurulum token'ıyla okuyun. Başka mağazanın siparişi 404 döner; panelden gelen sipariş kimliğine bu kontrol olmadan güvenmeyin.
  • Webhook'u 8 saniye içinde yanıtlayın, sağlayıcı çağrısını arka plana alın. Aynı olay birden fazla gelebilir; creating işaretiyle çift faturayı önleyin.
  • Durumu yukarıdaki sözleşmeyle yazın, olayları yayınlayın. Sağlayıcı hata mesajlarını göstermeden önce oturum kimliği, parola ve tam vergi numarasından arındırın.
  • GİB'e gitmiş bir belgeyi kural dışında iptal etmeyin; emin değilseniz needs-cancellation işaretleyip kararı mağazaya bırakın.

Uçtan uca örnek için Örnek Uygulama: Logo İşbaşı sayfasına bakın.