Ana içeriğe geç

İ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.

DilPaketGüncel sürümKurulumKaynak
Python 3.8+finansfatura0.4.0pip install finansfaturaff-python
Node 18+finansfatura0.4.0npm install finansfaturaff-node
PHP 8.1+finansfatura/finansfatura3.2.0composer require finansfatura/finansfaturaff-php
.NET (netstandard2.0 / net8.0)Finansfatura0.4.0dotnet add package Finansfaturaff-dotnet
0.4.0 / 3.2.0 ile gelenler

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.

Zincir istemcide de zorunlu

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:

PlatformKurulum / İndirKaynak
WooCommerce 8.0+ / PHP 8.1+zipwoocommerce-plugin
ikasikas App StoreResmî 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 da transaction_header_id sunucuya gitmeden hata olur
  • canonical alan 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, PHP bcmath, Node BigInt)
  • Tipli hatalar — her hata sınıfı bir HTTP durumuna karşılık gelir ve retryable alanı 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']);
İki uç KDV'yi farklı ister

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)PHPDurum
ValidationErrorValidationException400, 422
AuthErrorAuthException401
InsufficientCreditsInsufficientCreditsException402
ScopeErrorScopeException403
OnboardingRequiredOnboardingRequiredException412
RateLimitErrorRateLimitException429
ProviderErrorProviderException5xx

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.