GİB e-Fatura / e-Arşiv belgeleri (UBL-TR 1.2) için Go kütüphanesi. Belge modeli, parse ve deterministik XML üretimi, GİB iş kuralı doğrulaması, XAdES imza ve SBDH zarf katmanı; entegratör taşıması yolda.
Geliştirme sürüyor. v0.1 belge katmanı (builder + parse), v0.2 doğrulama, v0.3 XAdES imza, v0.4 zarf + durum kodları. Entegratör/GİB taşıması sonraki sürümde.
Türkiye e-belge ekosisteminde ciddi kütüphaneler C# ve PHP tarafında; Go'da UBL-TR üreten, GİB kurallarını bilen bir kütüphane yok. Backend'i Go olan herkes ya entegratörün hazır paketine kilitleniyor ya da XML'i elle kuruyor. Bu kütüphane o boşluk için: hangi entegratörü kullanırsanız kullanın, doğru UBL-TR belgesini üretmek ve gelen belgeyi parse etmek ortak ihtiyaç.
go get github.com/YusufDrymz/go-efaturaFatura kurma — satır tutarı, KDV dağılımı ve belge toplamları otomatik hesaplanır, VKN/TCKN checksum'ları go-trvalidate ile doğrulanır:
import "github.com/YusufDrymz/go-efatura/ubltr"
b := ubltr.NewInvoice(
ubltr.WithProfile(ubltr.ProfileTemelFatura),
ubltr.WithType(ubltr.TypeSatis),
ubltr.WithID("ABC2026000000001"),
ubltr.WithIssueDate(time.Now()),
ubltr.WithSupplier(ubltr.PartyInfo{VKN: "9990000005", Name: "Örnek A.Ş.", TaxOffice: "Beşiktaş",
Address: ubltr.Address{CitySubdivisionName: "Beşiktaş", CityName: "İstanbul",
Country: ubltr.Country{Name: "Türkiye"}}}),
ubltr.WithCustomer(ubltr.PartyInfo{TCKN: "99900000074", FirstName: "Ali", FamilyName: "Yılmaz",
Address: ubltr.Address{CitySubdivisionName: "Çankaya", CityName: "Ankara",
Country: ubltr.Country{Name: "Türkiye"}}}),
)
b.AddLine(ubltr.Line{Name: "Danışmanlık", Qty: ubltr.D("2"), Unit: "C62",
UnitPrice: ubltr.D("1500"), VATRate: ubltr.D("20")})
inv, err := b.Build() // hesap + dogrulama burada
if err != nil {
return err // birden fazla hata errors.Join ile birlikte doner
}
out, err := inv.XML()Build eksik/geçersiz her alanı ayrı raporlar (profil, fatura no biçimi,
checksum, adres, kur, istisna gerekçesi...) ve hepsini tek seferde döner —
tek tek düzeltip yeniden denemek gerekmez. Üretilen XML, testlerde GİB'in
resmi XSD'sine karşı xmllint ile doğrulanır (ubltr/testdata/xsd/).
Gelen faturayı parse etme:
inv, err := ubltr.ParseInvoice(data)
fmt.Println(inv.ProfileID, inv.InvoiceTypeCode) // TEMELFATURA SATIS
fmt.Println(inv.LegalMonetaryTotal.PayableAmount.Value) // 17.88Göndermeden (veya gelen belgeyi işlemeden) önce GİB iş kurallarıyla doğrulama:
import "github.com/YusufDrymz/go-efatura/validate"
issues := validate.Invoice(inv)
for _, is := range issues {
fmt.Println(is) // [hata] InvoicedQuantityCheck: unitCode niteliği zorunludur (InvoiceLine[1]/InvoicedQuantity)
}
if len(validate.Errors(issues)) == 0 {
// kurallardan geçti
}
// opsiyonel XSD katmanı: xmllint gerektirir, şema seti pakete gömülü
if err := validate.XSD(xmlBytes); err != nil { ... }XAdES-BES ile imzalama (entegratör kullanıyorsanız gerek yok — imzayı entegratör atar):
import "github.com/YusufDrymz/go-efatura/sign"
// Kamu SM test sertifikaları PFX dağıtılır (şifre: dosya adının son 6 hanesi)
s, err := sign.NewFromPKCS12(pfxBytes, "123456") // veya sign.NewFromPEM / sign.New(cert, cryptoSigner)
signed, err := s.Sign(ctx, xmlBytes) // placeholder gerçek imzayla değişir
res, err := sign.Verify(gelenFatura) // digest'ler + RSA; zincir kararı sizde
fmt.Println(res.Certificate.Subject.CommonName, res.SigningTime)Zarflama ve gelen sistem yanıtını okuma:
import "github.com/YusufDrymz/go-efatura/envelope"
env, err := envelope.Build(envelope.Envelope{
Sender: envelope.Party{Alias: "urn:mail:defaultgb@ornek.com.tr", VKN: "9990000005", Title: "Örnek A.Ş."},
Receiver: envelope.Party{Alias: "urn:mail:defaultpk@alici.com.tr", VKN: "9990000013"},
Documents: [][]byte{signed}, // imzali fatura baytlari — bayt bayt korunur
})
zipped, err := envelope.Zip(env, zarfID) // GIB'e giden paket: tek xml, adi zarf ID
opened, err := envelope.Open(gelenZarf) // belgeler ham dilimlenir, imza bozulmaz
r, err := envelope.ParseResponse(opened.Documents[0]) // sistem yanıtı
fmt.Println(r.Code, envelope.StatusText(r.Code), envelope.StatusSucceeded(r.Code))Durum kodları (1000–1300) ve anlamları Ek-2 kılavuzundan gelir;
StatusSucceeded/Failed/Pending sınıflandırması kılavuzdaki akışa göredir.
Zarf açmada belgeler yeniden serialize edilmez, orijinal baytlarıyla
dilimlenir — testlerdeki uçtan uca zincir (kur → imzala → zarfla → aç →
imza doğrula) bunu garanti eder.
İmza yapısı GİB'in resmi imzalı örnekleriyle birebir aynı iskelettedir
(rsa-sha256, tek enveloped transform, SignedProperties referansı) ve
testlerde gerçek bir GİB test mührü imzasının SignedInfo/SignedProperties
kısımları bizim kanonikalizasyonla doğrulanır. Yine de bu katman GİB'in
imza doğrulayıcısına karşı test edilmemiştir — canlıya çıkmadan kendi
mührünüzle uçtan uca deneyin. crypto.Signer kabul edildiği için HSM/
PKCS#11 implementasyonu dışarıdan takılabilir.
Kuralların kaynağı GİB'in resmi schematron dosyalarıdır; her bulgu,
schematron'daki kural ID'siyle gelir (UBLVersionIDCheck, decimalCheck,
WithholdingTaxTotalCheck...). GOEF- önekli kurallar go-efatura'nın ek
kurallarıdır: GİB schematron'u aritmetik tutarlılığı ve VKN/TCKN
checksum'ını hiç denetlemez — toplam formülleri ve checksum'lar burada
doğrulanır. Kapsam kritik fatura alt kümesidir; zarf ve e-İrsaliye kuralları
sonraki fazlarda.
Çalışan örnek: examples/. Yuvarlama tercihi: satır ve
vergi tutarları 2 haneye half-up yuvarlanır, toplamlar yuvarlanmış
değerlerden türetilir — GİB hiçbir kılavuzda yöntem tanımlamadığı için bu
bilinçli ve dokümante bir tercihtir; resmi örneklerdeki değerlerle uyumludur.
Model, UBL-TR kılavuzlarındaki eleman sırasını birebir taşır (XSD sequence
tabanlı olduğu için alan sırası sözleşmenin parçası). Tutarlar
shopspring/decimal üzerine kurulu Dec tipiyle taşınır ve parse edilen
ölçek korunur: 18.0 geri yazarken 18 olmaz, 18.0 kalır.
| Sürüm | Katman | İçerik |
|---|---|---|
| v0.1 ✓ | ubltr/ |
belge modeli, builder, otomatik toplam/KDV hesabı, golden testler |
| v0.2 ✓ | validate/ |
GİB schematron kurallarının kritik alt kümesi (kural ID referanslı) + XSD katmanı |
| v0.3 ✓ | sign/ |
XAdES-BES imza + doğrulama, pluggable Signer |
| v0.4 ✓ | envelope/ |
SBDH zarf + zip paketleme + sistem yanıtı / durum kodları |
| v0.5+ | transport/, earsiv/ |
entegratör adaptörleri, GİB doğrudan entegrasyon, e-Arşiv raporu |
- Yalnız resmi yollar hedeflenir: UBL-TR belge + özel entegratör veya GİB doğrudan entegrasyon. e-Arşiv portalının resmi olmayan JSON API'si (earsivportal) kapsam dışıdır: dokümante değil, sık kırılıyor.
- Test verileri GİB'in kamuya açık paketlerindeki resmi örneklerden gelir
(
ubltr/testdata/gib/). Gerçek mükellef verisi yoktur; sentetik fixture'larda VKN/TCKN değerleri uydurma ama checksum-geçerlidir. - İmza katmanı çekirdeğe bulaşmaz: entegratör kullanan çoğunluk belgeyi
imzasız üretir, imzayı entegratör atar. GİB XSD'si
UBLExtensions'ı zorunlu kıldığı için imzasız belgede şema-geçerli bir placeholder yazılır; imzacı bunu XAdES içeriğiyle değiştirir.
Go library for Turkish electronic invoices (GİB e-Fatura / e-Arşiv, UBL-TR 1.2 — a national customization of OASIS UBL 2.1). Ships the document layer (build invoices with automatic VAT distribution and totals, parse official documents, re-emit deterministic prefix-correct XML) and a validation layer implementing the critical subset of GİB's official schematron rules — every finding carries the schematron rule ID — plus an optional XSD check backed by the embedded official schema set (requires xmllint), and an XAdES-BES signing/verification layer mirroring the exact structure of GİB's official signed samples (tests verify a real GİB test seal signature with our canonicalization), and an SBDH envelope layer with status codes — documents travel through envelopes byte-intact, so signatures survive the round trip. Roadmap: integrator transports (v0.5+). Docs are in Turkish on purpose — the domain, its terminology and its regulator are Turkish.
MIT — see LICENSE.