Bakiye Yükleme
- 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_SCOPEalı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| Alan | Tip | Zorunlu | Açıklama |
|---|---|---|---|
creditWalletAccountId | string | ✅ | Kredilenecek hesap (cüzdan değil, hesap id'si) |
amount | string | ✅ | Minor-unit tutar |
currency | string | ✅ | Hesabın para birimiyle aynı olmalı |
returnUrl | string | — | Ödeme sonrası kullanıcının döneceği adres |
savedConsumerToken | string | — | Kayıtlı kart kullanılacaksa tüketici token'ı |
savedPublicCardStorageToken | string | — | Kayıtlı kart token'ı |
fundingMerchantId | string | — | Ç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:
| Alan | Ne yaparsınız |
|---|---|
checkoutFormContent | Kullanıcının tarayıcısında mount edersiniz — hosted checkout formu açılır |
threeDsHtml | 3D Secure sayfasını render edersiniz |
redirectUrl | Kullanı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ışı:
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
| Olay | Ne zaman |
|---|---|
wallet.topup.completed | Para bakiyeye yansıdı |
wallet.topup.failed | Kart 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.reversed | Tamamlanmış 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| Alan | Tip | Zorunlu | Açıklama |
|---|---|---|---|
reason | string | ✅ | Denetim kaydına yazılan gerekçe |
requesterPrincipal | string | ✅ | İsteği yapan operatörün kimliği |
approverPrincipal | string | ✅ | 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:
- Yükleme
REVERSINGdurumuna 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. - Tutar cüzdan bakiyesinden düşülür.
- Tutar karta iade edilir.
- Yükleme
REVERSEDolur vewallet.topup.refundedwebhook'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| Alan | Tip | Zorunlu |
|---|---|---|
agentId | string | ✅ |
creditWalletAccountId | string | ✅ |
amount | string | ✅ |
currency | string | ✅ |
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
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| Alan | Tip | Zorunlu | Açıklama |
|---|---|---|---|
walletAccountId | string | ✅ | Gelen paranın kredileneceği hesap |
currency | string | — | Belirtilmezse hesabın para birimi |
Talimatları listeleyin
GET /api/v1/wallet/end-users/{endUserId}/deposit-instructionsKullanı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
| Durum | Sebep | Çözüm |
|---|---|---|
| Aynı yükleme iki kez oluştu | Her denemede yeni Idempotency-Key üretildi | Anahtarı 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 reddi | KYC seviyesine göre yükleme tavanı aşıldı | Limitler ve KYC Seviyeleri |
WALLET_KYC_BALANCE_CAP_EXCEEDED | Kimliği doğrulanmamış (NONE) hesabın bakiyesi 5.000 TL tavanını aşacak | Limitler ve KYC Seviyeleri |