Panel — Kampanya & Sadakat
- Taban yol
/api/panel/v1/wallet- Kimlik
- Panel oturumu (JWT) —
Authorization: Bearer <panel access token>. Token panel girişinden gelir; s2s imza anahtarı bu uçları AÇMAZ. - Yetki
- RBAC izin kodu:
wallet:campaign:manage·wallet:loyalty:read·wallet:loyalty:manage·wallet:report:readDört-göz: isteği yapan ile onaylayan aynı kişi olamaz — rol kapısıyla değil, kimlik karşılaştırmasıyla zorlanır. - Çapraz yüzey
- Bu sayfadaki uçların s2s API'de karşılığı YOKTUR; kendi panelinizden çağıramazsınız. Bu yetenekler yalnız merchant panelde, panel oturumuyla kullanılabilir.
Müşteri tutundurma araçlarının yönetildiği bölüm. Kampanyalar para dağıtır, bu yüzden sürümlenir, simüle edilir ve onaydan geçer.
Kampanyalar
GET campaigns
POST campaigns
GET campaigns/:id
POST campaigns/:id/versions
PATCH campaigns/versions/:versionId
POST campaigns/versions/:versionId/submit
POST campaigns/versions/:versionId/approve
POST campaigns/:id/status
PATCH campaigns/:id/payer
POST campaigns/:id/simulate
GET campaigns/:id/reportSimülasyon — canlıya almadan önce
POST campaigns/:id/simulateKampanyayı her zaman simüle edin. Simülasyon, kural setini geçmiş işlemler üzerinde çalıştırıp kaç işlemin eşleşeceğini ve ne kadar bütçe yakacağını gösterir. Kural setindeki bir hata (ör. yanlış operasyon tipi filtresi) canlıda bütçeyi saatler içinde tüketebilir.
Simülasyon; tarih aralığı, örnek sayısı ve isterseniz henüz kaydedilmemiş bir kural seti/hesaplayıcı ile çalıştırılabilir.
Kural seti (ruleSet) bir JSON koşul ağacıdır (all / any / not + yaprak yüklemler: operationType, currency, category, amountRange, channel, timeWindow, firstNOperations, frequency, userSegment / segment). Kural editörünün altında kullanılabilir kategoriler listelenir (harcama kısıtıyla aynı kanonik sözlük).
category yaprağı yalnız işyeri taşıyan operasyonda (bugün PAYMENT_BUY) çözülür; sınıflandırılmamış işyeri/cüzdan işlemi için fail-closed (iade vermez). Tam eksen listesi ve örnekler: Sadakat & Cashback — Kural seti eksenleri. Simülasyon kategori beslemesini canlı yolla birebir yapar, yani kategori-hedefli kampanya simülasyonda gerçekçi görünür.
Bütçe ve finansman — ödeyen (payer)
PATCH campaigns/:id/payerKampanyayı kimin finanse ettiğini belirler. Üç ödeyen tipi vardır ve hepsi her kurulumda seçilemez:
payerType | Anlamı | Seçilebilir mi | Canlıya alınabilir mi |
|---|---|---|---|
TENANT | Tenant kendi fonlanmış cüzdan hesabından öder | Her kurulumda | ✅ Evet |
SYSTEM | Platformun fonlanmış hesabı öder | Yalnız ON_PREM | ✅ Evet |
SPLIT | Tenant + platform birlikte öder | Yalnız ON_PREM | ❌ Hayır — kaydedilir ve simüle edilir, aktive edilemez |
SaaS kurulumda yalnız TENANT kabul edilir. SYSTEM ve SPLIT gönderen istek servis katmanında reddedilir — panelin seçeneği gizlemesi bir güvenlik önlemi değildir; s2s ve doğrudan servis çağrıları o katmanı atlar. Karar programın kurulum (provisioning) sırasında sabitlenmiş deploymentMode alanından okunur; açma anahtarı veya ortam değişkeni yoktur ve bu alan sonradan değiştirilemez.
Gerekçe: SaaS'ta "platform" = Lunixi'nin kendisidir. SYSTEM de SPLIT de "tenant'ın kampanyasını Lunixi finanse eder" demektir.
SPLIT aktive edilemez — bu bir "henüz yazılmadı" değil, bilinçli bir karardır. Ledger v1.1 sözleşmesi donmuştur ve tek bir transfer tam olarak bir borç (DR) kaynağı taşır. Paylaşımlı finansmanı iki ayrı transfere bölmek, birinin yazılıp diğerinin yazılmadığı yarım ödenmiş bir cashback penceresi açardı. Ortak finansmanın muhasebe anlamı (kimin gideri, kime fatura) da ayrı bir karardır.
SPLIT konfigürasyonu kaydedilir ve simüle edilebilir; kampanyayı ACTIVE yapmaya çalıştığınızda aktivasyon reddedilir.
Otorite sunucudadır — kendi listenizi uydurmayın
Yanıt, iki ayrı soruyu iki ayrı alanla cevaplar:
| Alan | Soru | İçerik |
|---|---|---|
selectablePayerTypes | "Ne seçebilirim?" | Bu programda kaydedilebilir tiplerin listesi. null = bu yanıtta hesaplanmadı (dizi değil!) — o durumda program detayındaki selectableCampaignPayerTypes alanını okuyun |
deploymentMode | "Neden bu liste?" | SAAS | ON_PREM — salt-okuma, kurulumda sabitlenmiş |
activationAllowed | "Canlıya alabilir miyim?" | true / false |
activationBlockedReason | "Neden alamıyorum?" | Engel varsa gerekçe metni, yoksa null |
Seçilebilir ≠ aktive edilebilir. ON_PREM'de SPLIT selectablePayerTypes içindedir ama activationAllowed=false döner. İki alanı tek alana katlamak, panelin ya SPLIT'i hiç göstermemesine ya da kullanıcıya kaydedip aktive edemeyeceği bir seçenek sunmasına yol açar.
Panelinizde ödeyen seçicisini sabit üç seçenekle kurmayın: sunucu kuralı değişince listeniz sessizce bayatlar ve kullanıcıya kaydedemeyeceği bir seçenek gösterirsiniz. Programı okurken selectableCampaignPayerTypes, ödeyeni yazarken selectablePayerTypes alanını kullanın.
payerAccountRef her tipte zorunludur
Ödeyen bacağın cüzdan hesabı (payerAccountRef) her ödeyen tipinde zorunludur. SYSTEM'de eskiden opsiyoneldi ve bu sessiz bir ödememe defektiydi: hesap adlandırılmayınca motor tahakkuk üretiyor, ama tahakkuk hiçbir zaman post edilemiyor ve sonsuza dek RESERVED durumunda asılı kalıyordu. Kampanya "çalışıyor" görünüyor, kullanıcı "cashback kazandın" bildirimi alıyor, para hiç gelmiyordu.
Artık konfigürasyon anında reddedilir. Aktivasyonda ikinci kez doğrulanır: TENANT ödeyeninde hesabın bu tenant'a ait ve ACTIVE olduğu, onay transaction'ının içinde kanıtlanır — konfig ile aktivasyon arasında donmuş/kapatılmış bir hesap aktivasyonu durdurur.
| Ödeyen tipi | Zorunlu alanlar | Hesap sahipliği |
|---|---|---|
SYSTEM | payerAccountRef | Aranmaz — hesap tanım gereği platformundur, yalnız biçimi doğrulanır |
TENANT | payerAccountRef | Bu tenant'a ait, ACTIVE bir cüzdan hesabı olmalı |
SPLIT | payerAccountRef + payerSplitTenantBps (1–9999) + platformPayerAccountRef | Tenant bacağının sahipliği doğrulanır; iki bacak farklı hesap olmalı |
ACTIVE bir kampanyada ödeyen değiştirilemez — önce duraklatın.
Finansman hesabının bakiyesi biterse kampanya otomatik duraklatılır ve wallet.campaign.paused_insufficient_funds webhook'u düşer. Bu olayı dinleyin; duraklamış kampanya sessizce iade vermeyi keser ve size kullanıcı şikâyeti olarak döner.
Durum yönetimi
POST campaigns/:id/statusKampanyayı duraklatır, devam ettirir veya sonlandırır.
Segmentler
GET segments
POST segments
DELETE segments/:id
GET segments/:id/members
POST segments/:id/members # CSV ile üye yükleme, { csv, replace? }Segment, kampanyaları belirli bir müşteri kümesine hedeflemek için kullanılır.
replace: true üye listesini tamamen değiştirir; false ise ekler. Yanlış seçim, hedef kitleyi sessizce genişletir veya boşaltır — yüklemeden önce mevcut üye sayısını not edin.
Sadakat programı
GET loyalty/programs
PUT loyalty/programs
GET loyalty/earn-rules
PUT loyalty/earn-rules
GET loyalty/balance
GET loyalty/historySadakat programı; puan varlığı, çevrim oranı, minimum harcama miktarı, lot son kullanma süresi ve finansman hesabını tanımlar.
Lot son kullanma süresini (lotExpiryDays) belirlerken kullanıcıya bunu gösterebileceğinizden emin olun. Süresi dolan puan wallet.loyalty.expired olayını üretir; kullanıcı önceden uyarılmazsa bu doğrudan şikâyete dönüşür.
Seviye şemaları
GET loyalty/tier-schemes
PUT loyalty/tier-schemes
GET loyalty/tierKademe eşikleri ve her kademenin ayrıcalıkları: ücret şeması geçersiz kılma, limit artışı, kampanya çarpanı.
Seviyenin somut bir karşılığı olsun. Yalnız isim değişen bir kademe sistemi kullanıcıda karşılık bulmaz.
Rozetler
GET loyalty/badge-definitions
PUT loyalty/badges
GET loyalty/badges
PUT loyalty/badge-rulesRozet tanımı (kod, ad, ikon, gizli mi, tekrarlanabilir mi, ödül kampanyası) ve kuralı (tetikleyici olay, operasyon tipi, koşul).
Raporlama
GET campaigns/:id/report
GET reports/campaignsKampanyanın kaç işlemi etkilediği ve ne kadar bütçe yaktığı. Bkz. Panel — Raporlar.
Kontrol listesi
- Kural seti simüle edildi, eşleşen işlem sayısı makul
- Toplam bütçe, kullanıcı başı ve işlem başı tavanlar tanımlı
- Finansman hesabında yeterli bakiye var
-
paused_insufficient_fundsolayı dinleniyor - Diğer kampanyalarla çakışma (
stackable/exclusiveGroup) kontrol edildi - Başlangıç ve bitiş tarihleri doğru
- Onay farklı bir operatör tarafından verildi