Uygulamanız aylık ya da yıllık planlar satabilir. Tahsilatı Tecof yapar (iyzico); KDV hariç tutarın varsayılan %80'i iade penceresi dolduktan sonra partner defterinize yazılır ve partner programının aylık ödeme akışıyla size ödenir. Planı olmayan uygulama ücretsizdir.
Planlar#
Planlar tecof.app.json içindeki plans dizisinde tanımlanır (en fazla 4):
{
"plans": [
{
"key": "standart",
"name": { "tr": "Standart", "en": "Standard" },
"description": { "tr": "Küçük mağazalar için", "en": "For small stores" },
"price": 199,
"currency": "TRY",
"interval": "month",
"trialDays": 14,
"features": [
{ "tr": "Sınırsız fatura", "en": "Unlimited invoices" },
{ "tr": "Toplu faturalama", "en": "Bulk invoicing" }
]
},
{
"key": "yillik",
"name": { "tr": "Yıllık", "en": "Yearly" },
"description": { "tr": "İki ay hediye", "en": "Two months free" },
"price": 1990,
"currency": "TRY",
"interval": "year",
"trialDays": 0,
"features": [{ "tr": "Standart planın tüm özellikleri", "en": "Everything in Standard" }]
}
]
}| Alan | Kural |
|---|---|
key | Plan anahtarı (uygulama içinde tekil) |
name, description | { tr, en } |
price | KDV hariç, sıfırdan büyük |
currency | TRY, USD, EUR |
interval | month ya da year |
trialDays | 0–30 |
features | { tr, en } listesi; plan kartında gösterilir |
Onaylanmış uygulamada plan değişiklikleri canlıya hemen yansır. Ücretli plan içeren public bir uygulamayı incelemeye göndermek için partner doğrulamanız (KYC + IBAN) onaylı olmalıdır. private dağıtım incelemeye girmediği için yayında KYC istenmez; ancak hak ediş ödemesi her durumda onaylı KYC ve IBAN ister. Bkz. Yayınlama ve İnceleme.
KDV#
Mağazanın ödeyeceği tutar:
ödenecek = price × (1 + KDV oranı)| Para birimi | KDV oranı |
|---|---|
TRY | Tecof fatura ayarlarındaki KDV oranı (bugün %20) |
USD, EUR | Tecof fatura ayarlarındaki ihracat KDV oranı (varsayılan %0) |
Fiyatı her zaman KDV hariç girin; katalog ve ödeme ekranı KDV'yi ekleyerek gösterir.
Mağaza Satın Alma Akışı#
sequenceDiagram
participant M as Mağaza (panel)
participant T as Tecof
participant I as iyzico
participant A as Uygulamanız
M->>T: Kurulum: POST /api/merchant/apps/install { appId, acceptedScopes, planKey }
alt Ücretsiz plan ya da deneme süresi var
T-->>M: next.type = "open"
T->>A: app.installed (+ deneme varsa app.subscription.updated: trialing)
else Ücretli, denemesiz plan
T-->>M: next.type = "checkout" (billing.status = pending)
M->>T: POST /installations/:id/billing/checkout { planKey, customer }
T-->>M: iyzico ödeme formu
M->>I: Kart bilgisi
I->>T: Dönüş (callback) → iyzico'dan geri sorgu
T->>T: Dönem açılır / uzatılır
T->>A: app.subscription.updated (active)
T-->>M: /app/apps/my-apps/<kurulum>?billing=success
end- Ödeme iyzico'nun tek seferlik ödeme formuyla alınır; her ödeme bir dönem (ay ya da yıl) açar ya da uzatır.
- Ödeme dönüşü (callback) kaçırılırsa bir mutabakat işi
pendingkalan ödemeleri iyzico'dan sorgulayıp tamamlar. - Panel dönüşte
billing=success,billing=errorya dabilling=processinggösterir. - Mağaza plan seçim ekranını panelden açabilir; uygulamanızın arayüzünden açmak için App Bridge
openBilling()kullanın.
Mağazanın gördüğü uçlar (bilgi için): GET /api/merchant/apps/installations/:id/billing → { plans, subscription, charges }, POST /api/merchant/apps/installations/:id/billing/checkout.
Abonelik Durumları#
| Durum | Anlamı |
|---|---|
trialing | Deneme süresinde |
active | Ödenmiş dönem sürüyor |
past_due | Dönem bitti, yenileme ödemesi bekleniyor (3 günlük tolerans) |
expired | Tolerans doldu, ödeme yapılmadı |
cancelled | Uygulama kaldırıldı |
stateDiagram-v2
[*] --> trialing: Kurulum (denemeli plan)
[*] --> active: Ödeme
trialing --> active: Ödeme
trialing --> past_due: Deneme bitti, ödeme yok
active --> active: Yenileme ödemesi (dönem uzar)
active --> past_due: Dönem sonu
past_due --> active: Ödeme
past_due --> expired: 3 gün tolerans doldu
expired --> active: Ödeme
trialing --> cancelled: Kaldırma
active --> cancelled: Kaldırma
past_due --> cancelled: Kaldırma
expired --> cancelled: Kaldırmav1 yaşam döngüsü kuralları#
- Otomatik yenileme yoktur (v1). Dönem sonundan 7 gün önce (varsayılan) mağazaya hatırlatma gider; mağaza yenilemeyi elle öder.
- Dönem bitince abonelik
past_dueolur; 3 günlük (varsayılan) tolerans sonundaexpired'a geçer. - Deneme süresi ödeme yapılmadan biterse de aynı yol izlenir:
trialing→past_due(3 gün) →expired. - Bir mağaza aynı uygulamanın deneme süresini yalnız bir kez kullanabilir; kaldırıp yeniden kurmak ikinci deneme açmaz.
- Uygulama kaldırılınca abonelik
cancelledolur; otomatik iade yapılmaz. - Her durum geçişi uygulamanıza
app.subscription.updatedwebhook'u gönderir:
{
"event": "app.subscription.updated",
"data": {
"planKey": "standart",
"status": "active",
"trialEndsAt": null,
"currentPeriodEnd": "2026-11-10T09:16:10.000Z",
"chargeId": "6720dd00ee11ff22aa33bb66"
}
}Otomatik yenilenen abonelik (iyzico abonelik API'si) v2'de planlanmıştır.
Özellikleri Plana Göre Açmak#
Erişimi kısıtlamak uygulamanın kararıdır; Tecof süresi dolan abonelikte panelde yalnız bir uyarı bandı gösterir. Plan durumunu şu yerlerden öğrenirsiniz:
| Yer | Kullanım |
|---|---|
| App Bridge bağlamı | context.installation.plan = { key, status } ya da null — arayüzde göstermek/gizlemek için |
app.subscription.updated webhook'u | Sunucu tarafında durumu saklamak için |
api.installation() | Sunucu tarafında anlık durum (subscription) |
Sunucu tarafı örnek — webhook ile gelen durumu ayarlarda tutup her işte kontrol etmek:
// lib/billing.ts
import { tecof } from "@/lib/tecof";
type PlanState = { planKey: string | null; status: string; currentPeriodEnd: string | null };
const ALLOWED = new Set(["trialing", "active", "past_due"]); // past_due: 3 günlük toleransta çalışmayı sürdür
export async function savePlanState(installationId: string, data: PlanState) {
await tecof.client(installationId).settings.set({ billing: data }, { merge: true });
}
export async function hasPaidAccess(installationId: string): Promise<boolean> {
const { settings } = await tecof.client(installationId).settings.get();
const billing = settings.billing as PlanState | undefined;
return !!billing && ALLOWED.has(billing.status);
}// app/api/webhooks/route.ts — createWebhookHandler({ app: tecof, handlers: { … } }) içinde
"app.subscription.updated": async (event) => {
await savePlanState(event.installationId, event.data as PlanState);
},Anlık durumu webhook'a bağlı kalmadan da okuyabilirsiniz: api.installation() yanıtındaki subscription alanı (plan yoksa null). Bkz. API ile Veri Erişimi.
Arayüz tarafı örnek:
"use client";
import { useAppBridge, useAppContext } from "@tecof/app-bridge/react";
export function PaidFeature({ children }: { children: React.ReactNode }) {
const bridge = useAppBridge();
const { installation } = useAppContext();
const status = installation.plan?.status;
if (status === "trialing" || status === "active" || status === "past_due") return <>{children}</>;
return (
<div>
<p>Bu özellik ücretli planda kullanılabilir.</p>
<button onClick={() => bridge.openBilling()}>Planları gör</button>
</div>
);
}billing anahtarını yerel ayar formunuzdaki (settings şeması) anahtarlardan farklı seçin. past_due durumunda çalışmayı sürdürüp sürdürmemek ve deneme süresinde hangi özelliklerin açık olacağı sizin ürün kararınızdır.
Geliştirici Hak Edişi#
| Kural | Değer |
|---|---|
| Platform komisyonu | Varsayılan %20 → geliştirici payı %80 |
| Hesap tabanı | Tahsilatın KDV hariç tutarı |
| İade penceresi | Varsayılan 14 gün |
| Defter satırı | Ödemeden 14 gün sonra, iade edilmemişse partner defterine kind: "accrual", sourceType: "app-charge" satırı yazılır |
| Dönem | Satırın dönemi, ödenebilir tarihin (ödeme + 14 gün) ayıdır (İstanbul saati) |
| Pencere içi kısmi iade | İade edilen tutar tahakkuktan düşülür; satır kalan tutar üzerinden yazılır |
| Pencere sonrası iade | Partner defterine geri kesinti (kind: "clawback", sourceType: "app-refund") yazılır |
| Test mağazası satın alımı | Geliştiricinin kendi test mağazalarından yapılan satın alma gerçek satış sayılmaz: satır held (app-test-store) yazılır; Tecof yöneticisi serbest bırakabilir |
Bundan sonrası partner programının mevcut ödeme akışıdır:
Aylık kapanış. Dönemi önceki ay ya da daha eski olan, ödemeye girmemiş satırlar partner × para birimi bazında toplanır.
Ödeme açılma koşulları. Partner aktif, partner doğrulaması (KYC) onaylı, partner sözleşmesi onaylanmış ve toplam asgari tutarın üstünde olmalı. Aksi hâlde satırlar sonraki aya devreder.
Para birimi Asgari ödeme TRY 1.000 TL EUR 50 € USD 50 $ Partner faturası. Şahıs ve kurumsal partner, ödeme tutarı için KDV eklenmiş fatura yükler (Türkiye'de %20; yurt dışı partnerde 0). Bireysel partnerde fatura adımı yoktur.
Onay ve ödeme. Tecof yöneticisi faturayı onaylar (doğrulama ve IBAN şarttır) ve ödemeyi kaydeder. Fatura reddedilirse yeniden yüklenir.
Tahsilatları geliştirici API'sinden izleyebilirsiniz: GET /api/developer/apps/:id/charges.
Sayısal örnek#
Plan: Standart, 199 TL/ay (KDV hariç), Türkiye'deki kurumsal bir partner.
| Adım | Hesap | Tutar |
|---|---|---|
| Mağazanın ödediği | 199 × 1,20 | 238,80 TL |
| KDV hariç taban | — | 199,00 TL |
| Platform komisyonu (%20) | 199 × 0,20 | 39,80 TL |
| Geliştirici payı (%80) | 199 × 0,80 | 159,20 TL |
Zaman çizelgesi (ödeme 20 Ekim 2026):
| Tarih | Olay |
|---|---|
| 20.10.2026 | Mağaza öder; abonelik active, app.subscription.updated |
| 03.11.2026 | 14 günlük iade penceresi doldu; defterde 159,20 TL accrual, dönem 2026-11 |
| Aralık 2026 başı | Kasım dönemi kapanışa girer |
Aynı ay 7 mağazadan bu planla tahsilat yapıldığını varsayalım: 7 × 159,20 = 1.114,40 TL ≥ 1.000 TL asgari tutar → ödeme açılır. Kurumsal partner 1.114,40 TL + %20 KDV = 1.337,28 TL tutarında fatura yükler; yönetici onayından sonra ödeme yapılır. Toplam 1.000 TL'nin altında kalsaydı satırlar bir sonraki kapanışa devrederdi.
Mağaza 14 gün içinde tam iade alırsa defter satırı hiç yazılmaz; kısmi iadede tahakkuk iade oranında azalır: örneğin 238,80 TL'lik ödemenin 118,80 TL'si (KDV dahil) pencere içinde iade edilirse kalan KDV hariç tutar 199 × 120 / 238,80 = 100,00 TL, defter satırı 100,00 × 0,80 = 80,00 TL olur. Pencereden sonra tam iade yapılırsa iade dönemine −159,20 TL'lik clawback satırı düşer. İadeleri (tam ya da kısmi) Tecof yöneticisi yapar.
Açık Konular#
- Uygulama tahsilatının mağazaya Tecof tarafından faturalanması (e-Arşiv) henüz netleşmedi.
- Otomatik yenileme v2'ye bırakıldı.
- Birinci parti (partnersiz) uygulamalarda hak ediş satırı yazılmaz.