Cüzdan
Panel Kılavuzu
Kampanya & Sadakat

Panel — Kampanya & Sadakat

Bu uçları kim çağırır?Merchant panel
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/report

Simülasyon — canlıya almadan önce

POST campaigns/:id/simulate
⚠️

Kampanyayı 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/payer

Kampanyayı kimin finanse ettiğini belirler. Üç ödeyen tipi vardır ve hepsi her kurulumda seçilemez:

payerTypeAnlamıSeçilebilir miCanlıya alınabilir mi
TENANTTenant kendi fonlanmış cüzdan hesabından öderHer kurulumda✅ Evet
SYSTEMPlatformun fonlanmış hesabı öderYalnız ON_PREM✅ Evet
SPLITTenant + platform birlikte öderYalnı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:

AlanSoruİç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 tipiZorunlu alanlarHesap sahipliği
SYSTEMpayerAccountRefAranmaz — hesap tanım gereği platformundur, yalnız biçimi doğrulanır
TENANTpayerAccountRefBu tenant'a ait, ACTIVE bir cüzdan hesabı olmalı
SPLITpayerAccountRef + payerSplitTenantBps (1–9999) + platformPayerAccountRefTenant 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/status

Kampanyayı 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/history

Sadakat 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/tier

Kademe 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-rules

Rozet 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/campaigns

Kampanyanı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_funds olayı 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