Cüzdanla Öde — Payment
paymentMethod: "WALLET" ile POST /payments/direct/payment, alıcının cüzdanından ödeme alır. Alıcı telefonuna gelen tek seferlik kodla ödemeyi onaylar; kodu siz confirm ile gönderirsiniz. Bu sayfa cüzdanla ödemenin bütün istek alanlarını, yanıtını, onayını ve hatalarını gösterir; bütün yöntemlerde ortak olan aksiyon, confirm ve hata kodu kuralları Payment sayfasındadır.
Hesabınızda kullanılabilen cüzdanlar GET /payments/methods yanıtında WALLET satırının providers listesindedir. İşletmenizin kendi cüzdan programı bağlıysa o da bu listede, programınızın adı ve logosuyla yer alır.
Nasıl çalışır
Cüzdanı seçin
Tek cüzdan bağlıysa wallet.providerCode gönderilmesi gerekmez. Birden fazla cüzdan bağlıysa alıcının seçtiği cüzdanın kodunu gönderin; göndermezseniz 400 payment.provider.required döner. Bkz. Sağlayıcıyı seçme.
Ödemeyi başlatın
wallet bloğunda alıcının cüzdan hesabının telefon numarasını (gsmNumber) ve cüzdanın inputFields tanımındaki diğer alanları gönderin.
Kodu alın
Yanıt (202) bir OTP aksiyonu taşır. Kod action.otp.maskedTarget numarasına gönderilir. Aksiyon charge taşıyorsa alıcıya onaydan önce toplam tutarı gösterin.
Onaylayın
Alıcının girdiği kodu POST /payments/{paymentId}/actions/{actionId}/confirm ile gönderin. Sonuç 200 ile döner ve payment.captured gönderilir.
Sağlayıcıyı seçme
Cüzdanda sağlayıcıyı alıcı seçer: WALLET satırında providerSelectionMode BUYER'dır. Platform alıcı adına cüzdan seçmez.
- Tek cüzdan bağlıysa
wallet.providerCodegönderilmesi gerekmez; o cüzdan kullanılır. Yöntem satırındaproviderSelectionOPTIONAL'dır. - Birden fazla cüzdan bağlıysa
WALLETsatırınınproviders[]listesini (displayName,logoUrl) alıcıya gösterin ve seçtiği cüzdanınproviderCode'unuwallet.providerCodeile gönderin. Yöntem satırındaproviderSelectionREQUIRED'dır. Kodu göndermezseniz istek400payment.provider.requiredalır; bağlı kodlardetails.boundProviderCodesiçindedir. - Gönderdiğiniz kod hesabınızda bu yönteme bağlı değilse istek
422payment.provider.not_availablealır. - Seçilen cüzdan ödemeye sabitlenir: hata olursa başka cüzdana, başka yönteme ya da karta geçilmez.
Seçim modları ve providerSelection ile ilişkisi: Yöntemleri Listeleme › Sağlayıcı seçimi.
İstek
POST https://api-gateway.lunixi.com/api/v1/payments/direct/payment
Content-Type: application/jsonİstek Step-Up kimlik doğrulaması (Bearer token ve Ed25519 imza başlıkları; bkz. Kimlik Doğrulama) ve zorunlu Idempotency-Key başlığı (en fazla 200 karakter) taşır; kurallar Payment — Idempotency ile aynıdır.
Yöntem alanları
| Alan | Tip | Zorunlu | Açıklama |
|---|---|---|---|
paymentMethod | string | Evet | WALLET |
wallet | object | Evet | Cüzdan bloğu; alanları aşağıdaki satırlardadır |
wallet.providerCode | string | Birden fazla cüzdan bağlıysa | Alıcının seçtiği cüzdanın sağlayıcı kodu (GET /payments/methods); bkz. Sağlayıcıyı seçme |
wallet.gsmNumber | string | Cüzdanın tanımı istiyorsa | Cüzdan hesabının telefonu; doğrulama kodu bu numaraya gider. Gönderilmezse buyer.gsmNumber kullanılır |
wallet.<alan> | — | Tanıma göre | Cüzdanın inputFields tanımındaki diğer alanlar; bkz. Yöntem alanları. Tanımda olmayan alan gönderilemez |
preauth | boolean | Hayır | true: ön provizyon; seçilen cüzdanın desteklemesi gerekir. Bkz. Ön provizyon |
callbackUrl | string | Hayır | http ya da https, en fazla 2048 karakter. Sağlayıcı REDIRECT aksiyonu döndürürse alıcının tarayıcısı sonuçla bu adrese döner |
Gövdede yalnız wallet bloğu bulunur: başka bir yöntemin bloğu ya da card, force3D, installment, installmentQuoteToken gönderilirse istek 400 VALIDATION_ERROR alır.
Sipariş alanları
| Alan | Tip | Zorunlu | Açıklama |
|---|---|---|---|
amount | integer | Evet | Tutar, minor unit tam sayı; en az 1. Sepet toplamıdır: alıcının ödediği ürün ve hizmet bedeli, vade farkı hariç. basketItems gönderirseniz kalemlerin price toplamına eşit olmalıdır. Kartta taksit seçilirse vade farkını sistem ekler. Örnek: 10050 |
currency | string (enum) | Evet | ISO 4217 kodu: TRY, USD, EUR, GBP, RUB, AED, SAR, QAR, KWD, JPY, CHF, CAD, AUD, CNY, AZN. Hesabınızda açık olmayan para birimi reddedilir |
orderId | string | Evet | Sizin sipariş numaranız, en fazla 128 karakter. Örnek: ORD-84722 |
customerId | string | Hayır | Sizin müşteri anahtarınız. Cüzdanla ödemede alıcıyı tanımlar; 3D Secure ile kart kaydında kart bu anahtarın altına yazılır. Örnek: cust_7788 |
description | string | Hayır | Ödeme açıklaması |
locale | string | Hayır | Mesaj dili, varsayılan tr |
paymentChannel | string | Hayır | Ödeme kanalı. Örnek: WEB |
paymentGroup | string | Hayır | Ürün grubu. Örnek: PRODUCT |
buyer | object | Hayır | Alıcı bilgisi; bkz. buyer |
shippingAddress | object | Hayır | Teslimat adresi; bkz. Adres |
billingAddress | object | Hayır | Fatura adresi; bkz. Adres |
basketItems | array | Hayır | Sepet kalemleri; bkz. basketItems[] |
metadata | object | Hayır | Kendi kayıtlarınız için serbest anahtar-değer nesnesi. Ön provizyonu metadata ile değil preauth alanıyla isteyin |
Tutar yalnız amount ile gönderilir; kaldırılan tutar alanları 400 payment.amount.field_removed alır. Tanımlı olmayan bir alan gönderirseniz istek 400 VALIDATION_ERROR ile reddedilir.
Cüzdanla ödemede customerId alıcıyı tanımlar ve işletmenin cüzdan programında önerilir; bkz. Alıcı kimliği. buyer.gsmNumber, wallet.gsmNumber gönderilmezse kullanılır.
buyer
buyer opsiyoneldir. Gönderirseniz aşağıdaki "Evet" alanlarının hepsi dolu olmalıdır. Checkout Formu intent'inde (POST /payments/intents, POST /payments/marketplace/intents) bu zorunluluk yoktur: alanların hepsi isteğe bağlıdır, gönderdiğiniz alanların tipi ve uzunluğu doğrulanır.
| Alan | Tip | Zorunlu | Örnek |
|---|---|---|---|
id | string | Hayır | CUST-1 |
name | string | Evet | Ada |
surname | string | Evet | Yılmaz |
identityNumber | string | Evet | 11111111111 |
email | string (e-posta) | Evet | [email protected] |
gsmNumber | string | Evet | +905000000000 |
city | string | Evet | İstanbul |
country | string | Evet | Turkey |
zipCode | string | Evet | 34732 |
ip | string | Evet | Alıcının IP adresi |
registrationDate | string | Hayır | 2024-04-21 15:12:09 |
lastLoginDate | string | Hayır | 2026-10-05 12:43:35 |
registrationAddress | string | Hayır | Kayıtlı adres |
Zorunluluk kuralı, customerId ile farkı ve hata alan yolları: Alıcı Bilgileri.
Adres
shippingAddress ve billingAddress aynı yapıdadır. Nesneyi gönderirseniz beş alan da zorunludur.
| Alan | Tip | Örnek |
|---|---|---|
contactName | string | Ada Yılmaz |
address | string | Altunizade Mah. … |
city | string | İstanbul |
country | string | Turkey |
zipCode | string | 34742 |
İki adresin farkı ve hata alan yolları: Adres Bilgileri.
basketItems[]
| Alan | Tip | Zorunlu | Açıklama |
|---|---|---|---|
id | string | Evet | Kalem kodu |
name | string | Evet | Kalem adı |
category1 | string | Evet | Ana kategori |
category2 | string | Hayır | Alt kategori |
itemType | string (enum) | Evet | PHYSICAL ya da VIRTUAL |
price | integer | Evet | Kalem tutarı, minor unit tam sayı, en az 0 |
Kalemlerin price toplamı amount'a eşit olmalıdır; eşit değilse istek 400 VALIDATION_ERROR ile reddedilir. Vade farkı kalemlere yazılmaz.
Örnek istek
# Step-Up imza başlıklarının nasıl hesaplandığı için Kimlik Doğrulama sayfasına bakın.
curl -X POST https://api-gateway.lunixi.com/api/v1/payments/direct/payment \
-H "Authorization: Bearer at_test_5f3e2b1a..." \
-H "Content-Type: application/json" \
-H "X-Key-Id: mk_test_sk_..." \
-H "X-Date: 2026-10-11T09:00:00.000Z" \
-H "X-Nonce: 4a7e1c92-3b5d-4f60-8e2a-9c1d7b3e5f08" \
-H "Digest: SHA-256=..." \
-H "X-Signature: ..." \
-H "Idempotency-Key: ORDER-1004-1" \
-d '{
"paymentMethod": "WALLET",
"orderId": "ORDER-1004",
"amount": 12500,
"currency": "TRY",
"customerId": "CUST-2",
"wallet": { "providerCode": "<providerCode>", "gsmNumber": "+905321234567" }
}'<providerCode> bir yer tutucudur; cüzdanın kodunu GET /payments/methods yanıtından okuyun.
Alıcı kimliği
İşletmenizin cüzdan programıyla ödemede cüzdan iki bilgiyle bulunur:
customerId: Alıcıyı cüzdan programınızdaki müşteri kaydıyla eşler. Gönderdiğinizde telefon yalnız doğrulama için kullanılır; telefon o müşterinin kayıtlı numarasıyla eşleşmezse istek reddedilir.wallet.gsmNumber: Telefon her durumda gereklidir. Doğrulama kodu bu numaraya gider; kod, ödeyen kişinin cüzdanın sahibi olduğunu kanıtlar. Alan gönderilmezsebuyer.gsmNumberkullanılır. İkisi de yoksa ya da numaranın biçimi bozuksa istek400payment.method.block_invalidalır vedetails.fieldwallet.gsmNumberolur.
Alıcının kimliği yalnız customerId alanından okunur. metadata.customerId tek başına gönderilirse ya da customerId'den farklıysa istek 400 payment.method.customer_identity_conflict alır.
Yanıt ve aksiyon
{
"status": "partial",
"code": "CUSTOMER_ACTION_REQUIRED",
"message": "…",
"data": {
"paymentId": "3a8d5f1c-6b2e-4c9a-8e7d-1f0b2c3d4e5f",
"orderId": "ORDER-1004",
"status": "INITIATED",
"paymentMethod": "WALLET",
"providerCode": "<providerCode>",
"action": {
"id": "act_8e1f2a3b4c5d6e7f8091a2b3c4d5e6f7",
"type": "OTP",
"expiresAt": "2026-10-11T09:03:00.000Z",
"otp": { "maskedTarget": "53****67" },
"charge": {
"amount": 12500,
"feeTotal": 250,
"taxTotal": 50,
"buyerTotalCharge": 12800,
"currency": "TRY"
},
"maskedBusinessName": "Ör*** Ma*****"
}
},
"statusCode": 202,
"requestId": "…"
}| Alan | Açıklama |
|---|---|
action.otp.maskedTarget | Kodun gönderildiği numaranın maskeli hâli. otp alanı yoksa kod istenmez; confirm'ü otp olmadan gönderin |
action.charge | Alıcının ödeyeceği toplam ve kırılımı, minor unit. Ücret ya da vergi alıcıya yansıtılıyorsa buyerTotalCharge, sipariş tutarından (amount) büyüktür. Onaydan önce alıcıya buyerTotalCharge'ı gösterin |
action.maskedBusinessName | Ödemenin gideceği işletmenin maskeli adı |
action.stepUpRequired | Yalnız true iken bulunur: cüzdan güçlü doğrulama istedi. Sizden ek girdi beklenmez |
İşletmenizin cüzdan programıyla ödemede ödeme, kod onaylanana kadar INITIATED durumunda kalır.
Onay
{ "otp": "123456" }POST /payments/{paymentId}/actions/{actionId}/confirm ile gönderin; kimlik doğrulama ve sonuç tablosu Payment — confirm ile aynıdır.
- Yanlış kod
422payment.action.input_rejectedalır; aksiyon açık kalır ve kalan hakdetails.attemptsRemainingiçindedir. İşletmenizin cüzdan programında hak 3'tür. - İşletmenizin cüzdan programında kod yeniden gönderilemez: resend
422payment.action.resend_not_supportedalır. Kodun süresi dolarsa yeni bir ödeme başlatın.
Sonuç
| Durum | Yanıt | Ne yapmalı |
|---|---|---|
| Ödeme tamamlandı | 200, data.status CAPTURED | Siparişi payment.captured ile teslim edin |
| Cüzdan ödemeyi reddetti (bakiye, limit, doğrulama …) | 400 ya da 402, code payment.wallet_payment.* | Para hareket etmedi. Alıcıya başka bir yöntem önerin |
| Onay gönderildi ama sonuç henüz kesinleşmedi | 409 payment.wallet_payment.not_settled | Siparişi ödenmiş saymayın; aynı confirm isteğini kısa süre sonra tekrarlayın. Ödeme yerleşince aynı onay sonucu döner ve payment.captured gönderilir |
İşletmenizin cüzdan programıyla ödemede:
- Ret yanıtında
data.statusINITIATEDkalabilir; para hareket etmemiştir vepayment.failedgönderilmez. Yeniden denemek için yeni birIdempotency-Keyile yeni ödeme başlatın. Tamamlanmayan ödeme kaydı 24 saat sonraEXPIREDolur. - Aksiyonun süresi onay gönderilmeden dolarsa aksiyon kapanır, ödeme
INITIATEDkalır.
Sık görülen cüzdan kodları:
| Kod | Anlamı |
|---|---|
payment.wallet_payment.insufficient_balance | Cüzdan bakiyesi yetersiz |
payment.wallet_payment.limit_exceeded | Cüzdan harcama limiti bu ödeme için yetersiz |
payment.wallet_payment.kyc_insufficient | Cüzdanın kimlik doğrulama seviyesi bu ödeme için yetersiz |
payment.wallet_payment.customer_not_matched | customerId ile eşleşen cüzdan bulunamadı |
payment.wallet_payment.identity_mismatch | Telefon, bu müşterinin cüzdanında kayıtlı numarayla eşleşmiyor |
payment.wallet_payment.provider_unavailable | Seçilen cüzdan hesabınızda kullanılabilir değil |
payment.wallet_payment.rejected | Cüzdan ödemeyi tamamlamadı; ayrıntı paylaşılmaz |
payment.wallet_payment.not_settled | Onay gönderildi, sonuç henüz kesinleşmedi |
Ön provizyon
Bir cüzdanın ön provizyonu destekleyip desteklemediği GET /payments/methods yanıtındaki preauth alanındadır. Desteklemeyen cüzdanla preauth: true gönderilirse istek ödeme başlamadan 422 payment.preauth.unsupported_for_method alır. İşletmenizin cüzdan programı ön provizyonu desteklemez.
Hatalar
| Durum | Yanıt |
|---|---|
Birden fazla cüzdan bağlı, providerCode yok | 400 payment.provider.required |
| Seçilen cüzdan bağlı değil | 422 payment.provider.not_available |
| Telefon yok ya da biçimi bozuk | 400 payment.method.block_invalid |
metadata.customerId ile customerId çelişiyor | 400 payment.method.customer_identity_conflict |
| Seçilen cüzdanın doğrulama akışı bu uçta desteklenmiyor | 422 payment.method.wallet_bridge_not_available |
| Ön provizyon desteklenmiyor | 422 payment.preauth.unsupported_for_method |
Diğer kodlar: Payment — Hata kodları.
Webhook'lar
| Event | Ne zaman |
|---|---|
payment.captured | Cüzdan ödemesi tamamlandı. Siparişi bunun üzerine teslim edin |
payment.authorized | Ön provizyonlu ödemede tutar bloke edildi (AUTHORIZED); para henüz çekilmedi. Bkz. Ön Provizyon |
payment.failed | Ödeme başarısız oldu (işletmenin cüzdan programında ret, ödemeyi FAILED yapmaz) |
Olayların data'sında paymentMethod: "WALLET" ve cüzdanın providerCode'u bulunur. Bkz. Webhook'lar.
Sonraki adımlar
- Payment — ortak istek, yanıt ve hata kodları
- Yöntemleri Listeleme — bağlı cüzdanlar ve sağlayıcı seçimi
- Checkout Formu — Payment — cüzdanla ödemenin formdaki akışı