Discord botunuz için premium özellik satmak istiyorsanız harici bir ödeme sayfasına ve Discord kullanıcı ID'leriyle eşleştirme yapan bir panele ihtiyacınız olmayabilir. Discord'un Monetization API'si, ödeme akışını Discord içinde tamamlar ve hangi kullanıcının ya da sunucunun hangi ürüne erişimi olduğunu doğrudan size bildirir. Bu sistem botlar ve Activities için geçerli.

Bu yazıda SKU, entitlement ve subscription kavramlarını, uygunluk şartlarını, premium butonla satın alma akışını, abonelik yaşam döngüsü olaylarını ve ödeme yapmadan nasıl test edeceğinizi resmî belgelere dayanarak anlatıyoruz. Gelir paylaşımı oranı gibi bu belgelerde yer almayan rakamlara girmiyoruz; güncel ticari koşullar için Discord'un Monetization Terms metnine bakmalısınız.

Üç temel kavram: SKU, entitlement, subscription

Üç temel kavram: SKU, entitlement, subscription: Sattığınız tek bir ürün veya abonelik seçeneği, Entitlement, Subscription
KavramNe anlatırNe için kullanılır
SKUSattığınız tek bir ürün veya abonelik seçeneğiDeveloper Portal'da oluşturulur, fiyat ve fayda listesi taşır
EntitlementBir kullanıcının veya sunucunun bir SKU'ya erişimi olduğuPremium özelliği açıp açmama kararı (doğruluk kaynağı)
SubscriptionKullanıcının bir SKU için yinelenen ödeme yapmasıRaporlama ve yaşam döngüsü takibi

Belgelerin defalarca vurguladığı kural şu: erişim kararını entitlement'a göre verin. Subscription API ve olayları raporlama ile yaşam döngüsü yönetimi içindir, kullanıcının premium özelliğe erişip erişmediğinin doğruluk kaynağı olarak kullanılmamalıdır.

SKU türleri

Developer Portal'da "Create SKU" dediğinizde dört seçenek görürsünüz:

Portal seçeneğiAPI typeAçıklama
User Subscription5 (SUBSCRIPTION) + USER_SUBSCRIPTION bayrağıBir kullanıcıya, bulunduğu tüm sunucularda fayda sağlayan otomatik yenilenen abonelik
Guild Subscription5 (SUBSCRIPTION) + GUILD_SUBSCRIPTION bayrağıBir sunucudaki tüm kullanıcılara fayda sağlayan otomatik yenilenen abonelik
Durable2 (DURABLE)Bir kez alınıp kalıcı olarak kullanılan ürün (ör. ömür boyu premium)
Consumable3 (CONSUMABLE)Bir kez alınıp kullanılınca biten ürün (ör. geçici güçlendirme)

Her abonelik SKU'su için sistem otomatik olarak type: 6 (SUBSCRIPTION_GROUP) türünde ikinci bir SKU üretir. Belgelere göre bu grup SKU'ları şu an kullanılmıyor; entegrasyon ve test için type: 5 olan SKU'yu kullanmalısınız. List SKUs çağrısında bir abonelik için iki SKU görmenizin nedeni budur.

Kullanıcı ve sunucu aboneliğini flags alanında bitwise & ile ayırt edersiniz: GUILD_SUBSCRIPTION değeri 1 << 7, USER_SUBSCRIPTION değeri 1 << 8, satın alınabilirliği gösteren AVAILABLE ise 1 << 2.

SKU sınırları

  • Uygulama başına en fazla 50 SKU oluşturabilirsiniz. Daha fazlası gerekiyorsa belgeler, uygulama içi para birimi gibi çalışan bir consumable SKU önerir.
  • Aynı anda ya kullanıcı aboneliği ya sunucu aboneliği SKU'ları sunabilirsiniz, ikisini birden değil.
  • Fiyat serbest girilmez, hazır fiyat listesinden seçilir ve kullanıcının yerel para birimine otomatik çevrilir.
  • SKU adı en fazla 80, açıklaması en fazla 160 karakter. En fazla 6 fayda (benefit) eklenebilir; her faydanın adı 80, açıklaması 160 karakterle sınırlı.
  • Aynı türden birden fazla abonelik SKU'su yayınlayarak katmanlı (tier) abonelik sunabilirsiniz; kullanıcılar katmanlar arasında yükseltme ve düşürme yapabilir.

Uygunluk şartları ve kurulum adımları

Monetization açılmadan önce bir takım (team) ve bu takıma ait doğrulanmış bir uygulama gerekir. Takım sahibi monetization'ı etkinleştirirken belgede listelenen şu kontrollerden geçer:

  • Uygulama doğrulanmış olmalı ve bir geliştirici takımına ait olmalı.
  • Takım sahibi en az 18 yaşında olmalı.
  • Takım üyelerinin e-postaları doğrulanmış ve 2FA açık olmalı.
  • Uygulama slash komutları kullanmalı ya da privileged Message Content intent'i için onay almış olmalı.
  • Uygulamanın Kullanım Şartları (Terms of Service) bağlantısı olmalı.
  • Uygulamanın Gizlilik Politikası bağlantısı olmalı ve topladığınız kullanıcı verisini, bu veriyi nasıl kullandığınızı ve paylaştığınızı açıkça anlatmalı.
  • Uygulama adı, açıklaması, komutları ve role connection metadata'sı zararlı veya kötü dil içermemeli.
  • Geçerli bir ödeme yöntemiyle payout ayarlanmış olmalı.
  • Monetization Terms ve Discord Developer Policy kabul edilmiş olmalı.

Payout tarafında Discord tüm ödemeleri Stripe üzerinden işler ve payout ayarlarını yalnızca takım sahibi açabilir. Belgelere göre uygulama ilk 100 dolarlık gelirine ulaştığında payout için uygun hâle gelir ve bir inceleme yapılır. Doğrulama süreci için bot doğrulama ve privileged intent yazımıza, şartların politika tarafı için Developer Policy özetimize bakabilirsiniz.

SKU oluşturma, yayınlama ve yayından kaldırma

SKU oluşturma, yayınlama ve yayından kaldırma: Available via the Store and API, Available via the API Only

Developer Portal'da uygulamanızı seçin, "Monetization" altındaki "Manage SKUs" sekmesine gidin ve "Create SKU" düğmesine basın. Yeni SKU Unavailable durumunda başlar; fiyat, görsel ve faydaları ekledikten sonra yayınlarsınız. Yayınlarken iki seçenek var:

  • Available via the Store and API: Uygulamanızın Store sayfasında görünür ve satın alınabilir.
  • Available via the API Only: Yalnızca API çağrıları veya Embedded App SDK ile entitlement verilebilir.

Satın alma akışı: premium buton ve Store bağlantıları

Kullanıcıyı satın almaya yönlendirmenin üç yolu var: premium stilli buton, Store sayfası bağlantısı ve belirli bir SKU bağlantısı. Store bağlantısı https://discord.com/application-directory/:appID/store, belirli SKU bağlantısı https://discord.com/application-directory/:appID/store/:skuID biçimindedir; sohbette paylaşıldığında zengin bir embed olarak görünür.

Premium buton, style: 6 (Premium) ve bir sku_id taşıyan bir butondur. Component referansına göre premium butonlar custom_id, label, url veya emoji içeremez ve tıklandığında botunuza interaction göndermez; satın alma akışını Discord yürütür. Eski PREMIUM_REQUIRED (10) interaction yanıt türü kullanımdan kaldırıldı (deprecated); değişiklik günlüğü yerine premium butona geçmeyi öneriyor. Butonların genel kullanımı için buton ve select menu rehberimize bakabilirsiniz.

Aşağıdaki discord.js örneği, komutu kullanan kişinin aktif bir entitlement'ı yoksa premium buton gösteriyor. Entitlement'lar interaction nesnesinde entitlements koleksiyonu olarak gelir:

javascript
const { Events, ButtonStyle, ComponentType, MessageFlags } = require('discord.js');

const PREMIUM_SKU_ID = process.env.PREMIUM_SKU_ID;

client.on(Events.InteractionCreate, async (interaction) => {
  if (!interaction.isChatInputCommand() || interaction.commandName !== 'rapor') return;

  const premium = interaction.entitlements.some(
    (e) => e.skuId === PREMIUM_SKU_ID && e.isActive(),
  );

  if (!premium) {
    return interaction.reply({
      content: 'Bu komut premium üyelere özel.',
      components: [{
        type: ComponentType.ActionRow,
        components: [{ type: ComponentType.Button, style: ButtonStyle.Premium, sku_id: PREMIUM_SKU_ID }],
      }],
      flags: MessageFlags.Ephemeral,
    });
  }

  await interaction.reply({ content: 'Premium raporunuz hazırlanıyor...', flags: MessageFlags.Ephemeral });
});

discord.py 2.x'te aynı kontrol interaction.entitlement_sku_ids ile, buton ise ButtonStyle.premium ve sku_id parametresiyle yapılır:

python
import os
import discord

PREMIUM_SKU_ID = int(os.getenv('PREMIUM_SKU_ID'))

async def premium_kontrol(interaction: discord.Interaction) -> bool:
    if PREMIUM_SKU_ID in interaction.entitlement_sku_ids:
        return True
    view = discord.ui.View()
    view.add_item(discord.ui.Button(style=discord.ButtonStyle.premium, sku_id=PREMIUM_SKU_ID))
    await interaction.response.send_message('Bu komut premium üyelere özel.', view=view, ephemeral=True)
    return False

Entitlement'ları takip etmenin dört yolu

  • Gateway olayları: ENTITLEMENT_CREATE, ENTITLEMENT_UPDATE ve ENTITLEMENT_DELETE. discord.js'te Events.EntitlementCreate, discord.py'de on_entitlement_create.
  • HTTP API: List Entitlements uç noktası aktif ve süresi dolmuş entitlement'ları döndürür; user_id, guild_id, sku_ids, exclude_ended gibi filtreler alır. Arka plan işleri ve zamanlanmış görevler için uygundur.
  • Interaction payload: Kullanıcı botla etkileşime girdiğinde entitlements alanı gelir; en pratik kontrol yolu budur.
  • Embedded App SDK: Activities için getEntitlements.

Abonelik yaşam döngüsü

Abonelik yaşam döngüsü: Yeni abonelik, Yenileme, İptal, Dönem sonunda bitiş

Abonelik satın alındığında Discord kullanıcı (veya sunucu) için bir entitlement oluşturur. Bu entitlement abonelik iptal edilene kadar süresizdir, ends_at alanı null olur ve yenilemelerde entitlement olayı gelmez. Yenileme, iptal ve sona erme gibi değişiklikleri subscription olaylarından izlersiniz:

DurumGelen olayDeğişen alan
Yeni abonelikSUBSCRIPTION_CREATE, ENTITLEMENT_CREATE, SUBSCRIPTION_UPDATEstatus 0 (active)
YenilemeSUBSCRIPTION_UPDATEcurrent_period_start, current_period_end
İptalSUBSCRIPTION_UPDATEcanceled_at dolar, status 2 (ending)
Dönem sonunda bitişENTITLEMENT_UPDATE, SUBSCRIPTION_UPDATEends_at dolar, status 1 (inactive)
İptalden vazgeçmeSUBSCRIPTION_UPDATEstatus 0, canceled_at null
YükseltmeENTITLEMENT_UPDATE, ENTITLEMENT_CREATE, SUBSCRIPTION_UPDATEEski katman hemen biter, dönem sıfırlanır
DüşürmeÖnce SUBSCRIPTION_UPDATE, dönem sonunda entitlement olaylarırenewal_sku_ids

İptal eden kullanıcı current_period_end zamanına kadar erişimde kalır. Yükseltmede kullanıcı iki katman arasındaki fiyat farkını öder ve dönem yükseltme anında sıfırlanır; düşürmede ise mevcut dönem bitene kadar üst katman geçerlidir.

Tek seferlik satışlar: durable ve consumable

Durable bir SKU satın alındığında oluşan entitlement süresizdir; iade dışında kullanıcı erişimi kaybetmez. Consumable SKU'da ise kullanıcı aynı anda yalnızca bir tüketilmemiş entitlement'a sahip olabilir. Satın alımı kendi veritabanınıza işledikten sonra Consume Entitlement uç noktasını (POST /applications/{application.id}/entitlements/{entitlement.id}/consume) çağırmalısınız; aksi hâlde kullanıcı aynı ürünü tekrar alamaz. Tüketilen entitlement'ın consumed alanı true olur. discord.js'te bunun karşılığı entitlement.consume() metodudur.

Kullanıcının bakiyesi gibi bilgileri saklamak için küçük projelerde SQLite yeterli olabilir; birden fazla süreç çalıştırıyorsanız paylaşılan bir veritabanı düşünün.

Ödeme yapmadan test etme

Abonelikler için test entitlement

Create Test Entitlement uç noktası (POST /applications/{application.id}/entitlements) belirli bir kullanıcıya veya sunucuya bir SKU için test erişimi verir. Gövdede sku_id, owner_id ve owner_type (sunucu için 1, kullanıcı için 2) gönderilir. Test entitlement'ının starts_at ve ends_at alanı yoktur, silinene kadar geçerlidir. Oluşturduktan sonra Discord istemcisini yeniden yüklemeniz gerekir. discord.js'te client.application.entitlements.createTest({ sku, user }) ve deleteTest() metotları bu iş içindir.

Tam ödeme akışını görmek isterseniz Store sayfasından veya premium butondan satın alma yapabilirsiniz: uygulamanızla ilişkili takım üyeleri abonelik fiyatında otomatik olarak yüzde 100 indirim görür. Böylece canlı ödeme yöntemi kullanmadan yenilenen gerçek bir abonelik oluşur.

Tek seferlik satışlar için Application Test Mode

Sık Sorulan Sorular

Türkiye'den Discord botumla para kazanabilir miyim?

Belgelere göre Premium Apps payout'ları şu anda ABD, AB ve Birleşik Krallık merkezli takımlar için kullanılabiliyor. Diğer bölgeler için belge "yakında" diyor ama tarih vermiyor. Güncel durumu Enabling Monetization sayfası ve Premium Apps Payouts yardım makalesinden kontrol edin.

Abonelik durumunu mu, entitlement'ı mı kontrol etmeliyim?

Entitlement'ı. Belgeler subscription nesnesinin ve durumunun premium erişim vermek için kullanılmaması gerektiğini, doğruluk kaynağının entitlement olduğunu açıkça söylüyor.

Premium butona tıklanınca botuma bir olay gelir mi?

Hayır, premium butonlar interaction göndermez. Satın alma tamamlandığında ENTITLEMENT_CREATE olayı gelir ve sonraki etkileşimlerde entitlement interaction payload'unda yer alır.

Hem kullanıcı hem sunucu aboneliği satabilir miyim?

Aynı anda hayır. SKU sınırlarına göre ya kullanıcı aboneliği ya sunucu aboneliği SKU'ları sunabilirsiniz. Ancak aynı türden birden fazla katman oluşturabilirsiniz.

Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.

İlgili içerikler: Buton, select menu ve modal · Slash komut oluşturma · Bot doğrulama · Developer Policy özeti · HTTP interactions · User-install uygulama · SQLite nedir