İstemci Kütüphaneleri
Dört dilde resmî istemci yayınlıyoruz. Hepsi aynı yüzeyi sunar: satış oluşturma, fatura kesme, durum sorgulama, OAuth ve tipli hatalar.
| Dil | Paket | Güncel sürüm | Kurulum | Kaynak |
|---|---|---|---|---|
| Python 3.8+ | finansfatura | 0.4.0 | pip install finansfatura | ff-python |
| Node 18+ | finansfatura | 0.4.0 | npm install finansfatura | ff-node |
| PHP 8.1+ | finansfatura/finansfatura | 3.2.0 | composer require finansfatura/finansfatura | ff-php |
| .NET (netstandard2.0 / net8.0) | Finansfatura | 0.4.0 | dotnet add package Finansfatura | ff-dotnet |
Dövizli belge (currency + exchangeRate), KDV istisnası (exemptionCode),
e-Fatura senaryosu (scenario), iade atfı (returnInfo), satır bazında
tevkifat ve özel matrah; refund() artık dört dilin hepsinde. Ayrıntılar
Örnek Senaryolar'da, alan alan
Değişiklikler'de.
Daha eski bir sürümdeyseniz bu belgeleri kesemezsiniz — alanlar kütüphanede yoktu.
Python/Node 0.3.x, PHP 3.x ve .NET 0.3.x ile birlikte kütüphaneler
alıcı → satış → fatura zincirini istek göndermeden doğrular: buyer ve
içindeki title (ya da contact_name), external_id, en az bir satır ve
belge tarafında transaction_header_id eksikse çağrı yerelde hata verir. Tek
istisna iadedir (IADE), o satışa bağlanmaz.
Daha eski sürümler eksik gövdeyi sunucuya gönderiyordu; sunucu artık 400
döndüğü için yükseltmeniz gerekir.
Kütüphane kullanmak zorunda değilsiniz — API düz JSON'dur, curl ile de
çalışır. Kütüphaneler üç şeyi sizin yerinize halleder: canonical gövdesindeki
alan yazımı, kuruş yuvarlaması ve hangi hatanın tekrar denenebilir olduğu.
Hazır eklentiler ve uygulamalar
Mağazanız WooCommerce veya ikas üzerindeyse kod yazmanıza gerek yok:
| Platform | Kurulum / İndir | Kaynak |
|---|---|---|
| WooCommerce 8.0+ / PHP 8.1+ | zip | woocommerce-plugin |
| ikas | ikas App Store | Resmî Uygulama |
WooCommerce
Eklenti aynı iki adımı (önce satış, sonra fatura) sizin için işletir, checkout'a TCKN/VKN alanlarını ekler ve sipariş ekranına "Fatura Kes" düğmesi koyar.
Zip'i WordPress → Eklentiler → Yeni Ekle → Eklenti Yükle üzerinden kurun, ardından WooCommerce → Finansfatura ekranından API anahtarınızı girin. Eklenti bu sayfadaki PHP kütüphanesini kullanır; bağımlılıklar zip'in içinde hazır gelir.
ikas
ikas mağazanızdaki siparişleri otomatik olarak GİB uyumlu e-Fatura ve e-Arşiv Fatura'ya dönüştürür.
ikas App Store üzerinden Finans Fatura uygulamasını yükleyip yetkilendirmeyi tamamlayarak doğrudan kullanmaya başlayabilirsiniz.
Ne yapar
- İki adımı da kapsar —
create_order+issue_invoice+order_status - Zorunlu alanları baştan yakalar — eksik
buyer/title,external_id, satır ya datransaction_header_idsunucuya gitmeden hata olur canonicalalan yazımı — dış katman snake_case, iç katman PascalCase. Yanlış yazılan alan sunucuda sessizce yok sayılır; builder'lar bunu kapatır- Kuruş aritmetiği — toplamlar float ile değil, tam sayı/ondalık aritmetikle
hesaplanır (Python
Decimal, PHPbcmath, Node BigInt) - Tipli hatalar — her hata sınıfı bir HTTP durumuna karşılık gelir ve
retryablealanı tekrar deneme tablosunu taşır - OAuth 2.0 — PKCE üretimi, onay URL'i, token değişimi, yenileme, iptal
Faturanın kestiği anda numarası olmaz; kütüphaneler de bunu uydurmaz — durum sorgulama ucundan okursunuz.
Python
pip install finansfatura
import os
from finansfatura import FinansfaturaClient, build_earsiv_payload
ff = FinansfaturaClient(api_key=os.environ["FF_KEY"])
# 1 — satış (KDV dahil, oran yüzde)
sale = ff.create_order({
"provider": "ECOMSOFT",
"external_id": "ORD-2026-00184",
"payment_status": "PAID",
"total_price": 1200,
"buyer": {"title": "Test Müşteri", "tckn": "11111111111"},
"lines": [{"sku": "SRV-001", "title": "Danışmanlık hizmeti",
"quantity": 1, "unit_price": 1200, "vat_rate": 20}],
})
# 2 — fatura (KDV hariç, oran ondalık)
payload = build_earsiv_payload(
recipient={"vkn_tckn": "11111111111", "title": "Test Müşteri"},
lines=[{"title": "Danışmanlık hizmeti", "product_code": "SRV-001",
"qty": 1, "unit_price": 1000, "vat_rate": 0.20}],
transaction_header_id=sale["transaction_id"],
)
invoice = ff.issue_invoice(payload, idempotency_key="ORD-2026-00184")
# 3 — durum
res = ff.order_status("ecomsoft", ["ORD-2026-00184"])
Node
npm install finansfatura
import { FinansfaturaClient, buildEarsivPayload } from "finansfatura";
const ff = new FinansfaturaClient({ apiKey: process.env.FF_KEY });
// 1 — satış (KDV dahil, oran yüzde)
const sale = await ff.createOrder({
provider: "ECOMSOFT",
external_id: "ORD-2026-00184",
payment_status: "PAID",
total_price: 1200,
buyer: { title: "Test Müşteri", tckn: "11111111111" },
lines: [{ sku: "SRV-001", title: "Danışmanlık hizmeti",
quantity: 1, unit_price: 1200, vat_rate: 20 }],
});
// 2 — fatura (KDV hariç, oran ondalık)
const payload = buildEarsivPayload(
{ vkn_tckn: "11111111111", title: "Test Müşteri" },
[{ title: "Danışmanlık hizmeti", product_code: "SRV-001",
qty: 1, unit_price: 1000, vat_rate: 0.20 }],
{ transactionHeaderId: sale.transaction_id },
);
const invoice = await ff.issueInvoice(payload, "ORD-2026-00184");
// 3 — durum
const { statuses } = await ff.orderStatus("ecomsoft", ["ORD-2026-00184"]);
Bağımlılığı yoktur (yerleşik fetch) ve TypeScript tipleriyle gelir.
PHP
composer require finansfatura/finansfatura
use Finansfatura\Client;
use Finansfatura\Payload;
$ff = new Client(['apiKey' => getenv('FF_KEY')]);
// 1 — satış (KDV dahil, oran yüzde)
$sale = $ff->createOrder([
'provider' => 'ECOMSOFT',
'external_id' => 'ORD-2026-00184',
'payment_status' => 'PAID',
'total_price' => 1200,
'buyer' => ['title' => 'Test Müşteri', 'tckn' => '11111111111'],
'lines' => [['sku' => 'SRV-001', 'title' => 'Danışmanlık hizmeti',
'quantity' => 1, 'unit_price' => 1200, 'vat_rate' => 20]],
]);
// 2 — fatura (KDV hariç, oran ondalık)
$payload = Payload::earsiv(
['vkn_tckn' => '11111111111', 'title' => 'Test Müşteri'],
[['title' => 'Danışmanlık hizmeti', 'product_code' => 'SRV-001',
'qty' => 1, 'unit_price' => 1000, 'vat_rate' => 0.20]],
['transactionHeaderId' => $sale['transaction_id']],
);
$invoice = $ff->issueInvoice($payload, 'ORD-2026-00184');
// 3 — durum
$res = $ff->orderStatus('ecomsoft', ['ORD-2026-00184']);
Satış gövdesinde fiyatlar KDV dahil ve oran yüzde (1200, 20); fatura
gövdesinde KDV hariç ve ondalık (1000, 0.20). Builder'lar fatura
tarafını doğru kurar, satış gövdesi sizde kalır.
Sandbox
Varsayılan adres üretimdir; sandbox'a geçmek için taban adresi değiştirin.
from finansfatura import FinansfaturaClient, SANDBOX_BASE_URL
ff = FinansfaturaClient(api_key="ff_test_...", base_url=SANDBOX_BASE_URL)
import { FinansfaturaClient, SANDBOX_BASE_URL } from "finansfatura";
const ff = new FinansfaturaClient({ apiKey: "ff_test_...", baseUrl: SANDBOX_BASE_URL });
$ff = new Client(['apiKey' => 'ff_test_...', 'baseUrl' => Client::SANDBOX_BASE_URL]);
Taban adres yalnızca sunucu adresidir (https://api.finansfatura.com);
yolları kütüphane kurar.
OAuth ile kullanım
Çok mükellefli ürünlerde anahtar yerine token kullanırsınız. Akışın tamamı Kimlik Doğrulama sayfasındadır; kütüphaneler PKCE üretimini ve üç ucu sarar.
from finansfatura import FinansfaturaClient, OAuth, generate_pkce
oauth = OAuth(client_id=..., client_secret=..., redirect_uri="https://siz.com/cb")
verifier, challenge = generate_pkce() # verifier oturumda kalsın
redirect(oauth.authorize_url(code_challenge=challenge, state=csrf))
token = oauth.exchange_code(code, code_verifier=verifier)
ff = FinansfaturaClient(access_token=token["access_token"])
token = oauth.refresh(token["refresh_token"]) # YENİ refresh token'ı saklayın
import { FinansfaturaClient, OAuth, generatePkce } from "finansfatura";
const oauth = new OAuth({ clientId, clientSecret, redirectUri: "https://siz.com/cb" });
const { verifier, challenge } = generatePkce();
res.redirect(oauth.authorizeUrl({ codeChallenge: challenge, state: csrf }));
const token = await oauth.exchangeCode(code, { codeVerifier: verifier });
const ff = new FinansfaturaClient({ accessToken: token.access_token });
use Finansfatura\OAuth;
$oauth = new OAuth(['clientId' => $id, 'clientSecret' => $secret,
'redirectUri' => 'https://siz.com/cb']);
['verifier' => $v, 'challenge' => $c] = OAuth::generatePkce();
header('Location: ' . $oauth->authorizeUrl(['codeChallenge' => $c, 'state' => $csrf]));
$token = $oauth->exchangeCode($_GET['code'], ['codeVerifier' => $v]);
$ff = new Client(['accessToken' => $token['access_token']]);
Her yenilemede önceki refresh token geçersizleşir — en son aldığınızı saklayın.
Hata yakalama
Her hata sınıfı bir HTTP durumuna karşılık gelir ve retryable alanı taşır:
429 ve 5xx artan aralıklarla tekrar denenir, gerisi istek düzeltilmeden
denenmez. Ayrıntı için Hata Kodları.
from finansfatura import FinansfaturaError, OnboardingRequired
try:
ff.issue_invoice(payload, idempotency_key=order.id)
except OnboardingRequired:
# satış duruyor; mükellef kurulumu tamamlayınca faturalanır
notify_merchant()
except FinansfaturaError as e:
if e.retryable:
retry_later(order.id)
else:
log.error("%s %s", e.status, e.body)
| Sınıf (Python / Node) | PHP | Durum |
|---|---|---|
ValidationError | ValidationException | 400, 422 |
AuthError | AuthException | 401 |
InsufficientCredits | InsufficientCreditsException | 402 |
ScopeError | ScopeException | 403 |
OnboardingRequired | OnboardingRequiredException | 412 |
RateLimitError | RateLimitException | 429 |
ProviderError | ProviderException | 5xx |
Sürüm ve destek
Kütüphaneler semantik sürümleme kullanır; kırıcı değişiklikler ana sürümde (PHP)
ya da ikinci hanede (Python/Node, 1.0 öncesi) gelir. Sürüm notları depolardaki
CHANGELOG.md dosyalarındadır — son kırıcı değişiklik zincirin zorunlu hâle
gelmesidir (PHP 3.0.0, Python/Node 0.3.0). Sorun ve öneriler için ilgili
GitHub deposunu ya da
[email protected] adresini kullanın.