Cüzdan
Bakiye Yükleme

Bakiye Yükleme

Bu uçları kim çağırır?Dış API (s2s)
Taban yol
/api/v1/wallet
Kimlik
Ed25519 istek imzası — X-Key-Id, X-Date, X-Nonce, Digest (body varsa), X-Signature. Zaman penceresi ±5 dk, nonce tek kullanımlık, anahtarda IP allow-list olabilir.
Yetki
Anahtarınız cüzdan ürününü ve çağrının gerektirdiği cüzdan iznini taşımalıdır; izni olmayan çağrı 403 WALLET_INSUFFICIENT_SCOPE alır. Uç başına izinler: Anahtar izinleri.
Çapraz yüzey
Bu uçlar s2s yüzeyindedir. Son kullanıcı tarafı /api/portal/v1/wallet/me/topups/*; panelde yükleme iadesi ve askıda fon eşleştirme dört-göz talebidir (wallet:operation:intervene; talebi açan ve onaylayan farklı kişiler, ikisi de panel oturumundan).

Cüzdana para üç yoldan girer: kartla, temsilci eliyle nakit ve havale/EFT ile. Üçü de aynı operasyon modelini kullanır — her yükleme bir operasyon kaydı üretir ve sonuç webhook ile bildirilir. Kartla ve temsilci eliyle yükleme başlatılırken Idempotency-Key zorunludur.

Tutarlar minor-unit string'dir: "amount": "25000" = ₺250,00.

Kartla yükleme

Kart yüklemesi ödeme altyapısına delege edilir; kart verisi sizin sunucunuza hiç uğramaz. Yönlendirme, 3D Secure ve sağlayıcı seçimi ödeme tarafında yapılır, sonuç cüzdana yansır.

Yüklemeyi başlatın

POST /api/v1/wallet/topups/card
AlanTipZorunluAçıklama
creditWalletAccountIdstring✅Kredilenecek hesap (cüzdan değil, hesap id'si)
amountstring✅Minor-unit tutar
currencystring✅Hesabın para birimiyle aynı olmalı
returnUrlstring—Ödeme sonrası kullanıcının döneceği adres
savedConsumerTokenstring—Kayıtlı kart kullanılacaksa tüketici token'ı
savedPublicCardStorageTokenstring—Kayıtlı kart token'ı
fundingMerchantIdstring—Çoklu merchant yapılandırmasında tahsilatı yapacak merchant
curl -X POST "https://api-gateway.lunixi.com/api/v1/wallet/topups/card" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: topup-crm-88213-1" \
  -H "X-Key-Id: …" -H "X-Signature: …" \
  -d '{
    "creditWalletAccountId": "c2a5e8f1-9d3b-4c7a-8e6f-5b1d2a9c0e47",
    "amount": "25000",
    "currency": "TRY",
    "returnUrl": "https://app.acme.com/wallet/topup/result"
  }'
{
  "status": "success",
  "code": "SUCCESS",
  "data": {
    "operationId": "4f1b8d2e-6a9c-4b3e-8f7d-1c5e9a2b6d08",
    "paymentId": "9c6f2b1a-4e8d-4a3f-b5e6-2d7c1a9b8e30",
    "status": "INITIALIZED",
    "checkoutFormContent": "<script …>",
    "threeDsHtml": "",
    "redirectUrl": ""
  }
}

Yanıtta üç olası devam yolu vardır; hangisi doluysa onu kullanın:

AlanNe yaparsınız
checkoutFormContentKullanıcının tarayıcısında mount edersiniz — hosted checkout formu açılır
threeDsHtml3D Secure sayfasını render edersiniz
redirectUrlKullanıcıyı bu adrese yönlendirirsiniz

Sonucu öğrenin

GET /api/v1/wallet/topups/{operationId}
⚠️

Sonucu, returnUrl'e dönen kullanıcıdan öğrenmeye çalışmayın — tarayıcı hiç dönmeyebilir (uygulama kapanır, ağ kopar). Doğru kaynak webhook'tur; GET /wallet/topups/{operationId} teyit içindir.

Durum akışı:

Bakiye yükleme yaşam döngüsüDurum makinesi: yükleme açılır, kullanıcı ödemeyi tamamlayınca defter kaydı yazılır ve bakiyeye yansır. Ödeme düşerse başarısız olur; tamamlanmış bir yükleme iade edilirse ters kaydedilir.KULLANICI ÖDERDEFTERE YAZILDIÖDEME DÜŞTÜİADEINITIALIZEDPOSTINGCOMPLETEDFAILEDREVERSEDAÇIKLAMATERMİNALPARA GERİ ALINDI
REVERSED yalnız tamamlanmış bir yüklemeden gelir — yükleme hiç tamamlanmadıysa iade yoktur, FAILED vardır ve rezerve fon zaten serbest bırakılmıştır.

İlgili webhook'lar

OlayNe zaman
wallet.topup.completedPara bakiyeye yansıdı
wallet.topup.failedKart tahsilatı başarısız, bakiye değişmedi
wallet.topup.refund_pendingİade yapılamadı: cüzdan bakiyesi iade tutarına yetmiyor; yükleme COMPLETED kalır
wallet.topup.refundedİade tamamlandı
wallet.topup.reversedTamamlanmış yükleme ters kaydedildi

Yükleme iadesi

Tamamlanmış bir kart yüklemesi iade edilebilir — para karta geri gider ve cüzdan bakiyesinden düşer.

POST /api/v1/wallet/topups/{operationId}/refund
AlanTipZorunluAçıklama
reasonstring✅Denetim kaydına yazılan gerekçe
requesterPrincipalstring✅İsteği yapan operatörün kimliği
approverPrincipalstring✅Onaylayan operatör — isteyenden farklı olmalı
⚠️

Bu uç dört-göz kuralına tabidir: approverPrincipal, requesterPrincipal ile aynı olamaz. Bu s2s uçta iki kimlik de sizin sisteminizden gelir; onları gerçekten iki ayrı kişiye bağlamak sizin onay akışınızın sorumluluğundadır. Panelden yapılan iade ise kalıcı bir dört-göz talebidir ve kimlikler panel oturumlarından alınır: Dört-göz talepleri.

İade şu sırayla yürür:

  1. Yükleme REVERSING durumuna alınır. Aynı yükleme için eşzamanlı ikinci bir iade ya da geri alma bu adımı kazanamaz ve hiçbir para hareketi yapmaz.
  2. Tutar cüzdan bakiyesinden düşülür.
  3. Tutar karta iade edilir.
  4. Yükleme REVERSED olur ve wallet.topup.refunded webhook'u düşer.

Adım 2 ya da 3'ün sonucu o an kesinleşmezse (zaman aşımı, sağlayıcıya erişilemiyor) yükleme REVERSING durumunda kalır. Sistem iadeyi aynı anahtarlarla otomatik olarak tamamlar; tutar ne cüzdandan ne karttan ikinci kez hareket eder. Bu durumda iadeyi yeniden başlatmanız gerekmez; aynı isteği tekrarlarsanız kaldığı yerden devam eder.

⚠️

Kullanıcı yüklediği parayı harcadıysa iade yapılmaz: bakiye negatife düşürülmez, kart iade edilmez. İstek WALLET_REFUND_INSUFFICIENT_BALANCE ile reddedilir, yükleme COMPLETED kalır ve wallet.topup.refund_pending webhook'u düşer. Bakiye yeterli hâle geldiğinde iadeyi yeniden isteyebilirsiniz.

Temsilci ile yükleme

Bayi/temsilci ağınız varsa, temsilci nakdi alır ve kendi float hesabından müşterinin cüzdanına kredi geçer. Para tenant içinde yer değiştirir; dışarıdan giriş yoktur.

POST /api/v1/wallet/agent-topups
AlanTipZorunlu
agentIdstring✅
creditWalletAccountIdstring✅
amountstring✅
currencystring✅
curl -X POST "https://api-gateway.lunixi.com/api/v1/wallet/agent-topups" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: agent-4471-20260807-0012" \
  -H "X-Key-Id: …" -H "X-Signature: …" \
  -d '{
    "agentId": "6b2e9f4a-3c8d-4e1b-9a7f-5d0c3e8b2a61",
    "creditWalletAccountId": "c2a5e8f1-9d3b-4c7a-8e6f-5b1d2a9c0e47",
    "amount": "50000",
    "currency": "TRY"
  }'

Yanıttaki status normalde COMPLETED olur. Defter kaydının sonucu o an kesinleşmezse INDETERMINATE döner: kredi yapılmış olabilir, sistem işlemi kendiliğinden sonuçlandırır. Bu durumda temsilciye "yükleme olmadı" demeyin ve yeni bir Idempotency-Key ile tekrar denemeyin; aynı anahtarla tekrarlarsanız işlemin güncel durumu döner. Bkz. Belirsiz sonuç.

⚠️

Temsilci float hesabı yetmiyorsa işlem reddedilir. Temsilcinin günlük kredi limiti (dailyCreditLimit) panelden tanımlanır ve aşılamaz — bu, temsilcinin karşılığı olmayan bakiye üretmesini engelleyen kapıdır.

Temsilci tanımlama ve float yönetimi merchant panelden yapılır: Panel — Programlar.

Havale/EFT ile yükleme

Yakında — banka entegrasyonu gerektirir

Bu akışın API sözleşmesi tamamlanmıştır ve aşağıda anlatıldığı gibi kalacaktır. Üretimde çalışması için programınıza bir banka entegrasyonu bağlanmalıdır: yatırma referanslarının üretilmesi ve gelen paranın eşleştirilmesi bu entegrasyonun üzerinde yürür. Entegrasyon bağlı değilken bu uçlar istek kabul etmez. Durum: Yol Haritası.

Havale yükleme, kullanıcıya kendisine özel bir yatırma referansı verilmesi esasına dayanır. Kullanıcı bu referansla para gönderir; gelen para referansa göre eşleştirilip cüzdana kredilenir.

Yatırma talimatı oluşturun

POST /api/v1/wallet/end-users/{endUserId}/deposit-instructions
AlanTipZorunluAçıklama
walletAccountIdstring✅Gelen paranın kredileneceği hesap
currencystring—Belirtilmezse hesabın para birimi

Talimatları listeleyin

GET /api/v1/wallet/end-users/{endUserId}/deposit-instructions

Kullanıcıya gösterdiğiniz IBAN ve referansı her seferinde bu uçtan okuyun; sabit kodlamayın.

⚠️

Kullanıcı referansı yanlış yazarsa ya da hiç yazmazsa para askıya alınır (suspense) — kaybolmaz. Askıdaki para panelden ya bir talimata eşleştirilir ya da gönderene iade edilir. Bkz. Temel Kavramlar → Askıda fon.

Eşleşme tamamlandığında wallet.topup.completed webhook'u fundingSourceType alanıyla havale kaynağını belirterek düşer.

Yaygın hatalar

DurumSebepÇözüm
Aynı yükleme iki kez oluştuHer denemede yeni Idempotency-Key üretildiAnahtarı iş anlamınıza bağlayın (sipariş/deneme no)
currency uyuşmazlığıHesabın para birimi farklıHesabı GET /wallet/end-users/:id/balances ile doğrulayın
Yükleme INITIALIZED'da kaldıKullanıcı ödemeyi tamamlamadıSüre dolunca EXPIRED olur; yeni yükleme başlatın
Limit reddiKYC seviyesine göre yükleme tavanı aşıldıLimitler ve KYC Seviyeleri
WALLET_KYC_BALANCE_CAP_EXCEEDEDKimliği doğrulanmamış (NONE) hesabın bakiyesi 5.000 TL tavanını aşacakLimitler ve KYC Seviyeleri