Faturana Yansıt — Payment
paymentMethod: "MOBILE_BILLING" ile POST /payments/direct/payment, tutarı alıcının cep telefonu faturasına yansıtır. Alıcı hattına gelen kodu girer ve sağlayıcının sözleşmesini onaylar; ikisini siz confirm ile gönderirsiniz. Bu sayfa Faturana Yansıt'ın 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.
Yöntemin hesabınızda açık olup olmadığı, sağlayıcısı, tutar sınırları ve alıcıdan istenen alanlar GET /payments/methods yanıtında MOBILE_BILLING satırındadır.
Nasıl çalışır
Ödemeyi başlatın
mobileBilling.gsmNumber alanında tutarın yansıtılacağı hattı gönderin. Sağlayıcıyı alıcıya seçtirdiyseniz kodunu mobileBilling.providerCode ile gönderin; göndermezseniz sağlayıcıyı platform seçer. Bkz. Sağlayıcıyı seçme.
Kodu ve sözleşmeyi gösterin
Yanıt (202) bir OTP aksiyonu taşır: kod action.otp.maskedTarget hattına SMS ile gider. action.consent.required true ise action.consent.url adresindeki sözleşmeyi alıcıya gösterin ve onayını alın.
Onaylayın
Kodu ve onayı confirm ile gönderin: { "otp": "…", "consentAccepted": true }. Ödeme tamamlanınca yanıt 200 döner ve payment.captured gönderilir.
Hat bu yöntemle daha önce onaylanmışsa sağlayıcı kod istemeden ödemeyi sonuçlandırabilir: o durumda yanıtta action yoktur ve sonuç doğrudan döner.
Sağlayıcıyı seçme
Bu uçta Faturana Yansıt'ın sağlayıcısını seçmek zorunlu değildir: MOBILE_BILLING satırında providerSelectionMode PLATFORM, providerSelection OPTIONAL'dır. mobileBilling.providerCode isteğe bağlıdır:
- Göndermezseniz platform, hesabınıza bağlı sağlayıcılardan bu ödemeyi karşılayabilen birini para çekilmeden önce seçer ve ödemeye sabitler. Tek sağlayıcı bağlıysa o kullanılır.
- Gönderirseniz o sağlayıcı kullanılır. Kod hesabınızda bu yönteme bağlı değilse istek
422payment.provider.not_availablealır. - Seçimden sonra başka sağlayıcıya, başka yönteme ya da karta geçilmez. Ödemeyi yürüten sağlayıcı yanıtta ve webhook'ta
providerCodealanındadır. - Bağlı sağlayıcıların hiçbiri bu ödemeyi karşılamıyorsa istek
422payment.provider.none_eligiblealır; bkz. Hiçbir sağlayıcı uygun değil.
Platformun hangi kontrollerle seçtiği: Yöntemleri Listeleme › Platformun seçimi.
Sağlayıcıları GET /payments/methods yanıtındaki sırayla (displayName, logoUrl) kendi ödeme sayfanızda alıcıya gösterebilir ve seçtiği kodu gönderebilirsiniz. Checkout Formu'nda alıcı sağlayıcıyı her zaman kendisi seçer → Checkout Formu — Payment › Sağlayıcı seçimi.
Hiçbir sağlayıcı uygun değil
Birden fazla sağlayıcı bağlıyken providerCode göndermezseniz ve hiçbir sağlayıcı bu ödemeyi karşılamıyorsa ödeme başlatılmaz, tutar faturaya yansıtılmaz ve doğrulama kodu gönderilmez:
{
"status": "failure",
"code": "payment.provider.none_eligible",
"message": "Bağlı sağlayıcıların hiçbiri bu ödemeyi karşılamıyor; ödeme başlatılmadı ve tutar çekilmedi. …",
"statusCode": 422,
"timestamp": "2026-10-12T09:00:00.000Z",
"service": "api-gateway",
"systemTime": 1791795600000,
"requestId": "…",
"docsUrl": "https://docs.lunixi.com/tr/getting-started/errors#payment.provider.none_eligible",
"details": {
"paymentMethod": "MOBILE_BILLING",
"candidates": [
{ "providerCode": "<providerCode>", "outcome": "INELIGIBLE", "reason": "AMOUNT_OUT_OF_RANGE" },
{ "providerCode": "<providerCode-2>", "outcome": "UNAVAILABLE", "reason": "ELIGIBILITY_TIMEOUT" }
]
}
}details.candidates[] her sağlayıcı için bir satır taşır. Satırlarda kişisel veri yer almaz.
| Alan | Açıklama |
|---|---|
providerCode | Sağlayıcının kodu |
outcome | INELIGIBLE: sağlayıcı bu ödemeyi karşılamıyor. UNAVAILABLE: sağlayıcıdan uygunluk yanıtı alınamadı. NOT_CHECKED: seçim süresi dolduğu için sağlayıcı denenmedi |
reason | Sebep kodu ya da null. Örnekler: CURRENCY_NOT_SUPPORTED, AMOUNT_OUT_OF_RANGE, PREAUTH_UNSUPPORTED, INPUT_INVALID, ELIGIBILITY_ERROR, ELIGIBILITY_TIMEOUT, SELECTION_BUDGET_EXHAUSTED; sağlayıcının kendi ret kodu da olabilir |
- Sonuçlardan biri
UNAVAILABLEya daNOT_CHECKEDise aynı isteği daha sonra tekrar deneyebilirsiniz. - Sağlayıcıyı
mobileBilling.providerCodeile kendiniz de seçebilirsiniz. - Bütün sonuçlar
INELIGIBLEise alıcıya başka bir yöntem önerin.
İ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 | MOBILE_BILLING |
mobileBilling | object | Evet | Faturana Yansıt bloğu; alanları aşağıdaki satırlardadır |
mobileBilling.gsmNumber | string | Evet* | Tutarın yansıtılacağı hat; isteğe bağlı + ve 10–15 rakam. Kod bu hatta gönderilir. *Gönderilmezse buyer.gsmNumber kullanılır; ikisi de yoksa istek 400 payment.method.block_invalid alır |
mobileBilling.providerCode | string | Hayır | Sağlayıcı kodu (GET /payments/methods). Gönderilmezse sağlayıcıyı platform seçer; bkz. Sağlayıcıyı seçme |
mobileBilling.<alan> | — | Tanıma göre | Sağlayıcını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; sağlayıcını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 mobileBilling 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.
buyer.gsmNumber, mobileBilling.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: 8d4f2c1e-0a7b-4b3c-9e5d-6f1a2b3c4d5e" \
-H "Digest: SHA-256=..." \
-H "X-Signature: ..." \
-H "Idempotency-Key: ORDER-1002-1" \
-d '{
"paymentMethod": "MOBILE_BILLING",
"orderId": "ORDER-1002",
"amount": 5000,
"currency": "TRY",
"basketItems": [
{ "id": "DIGITAL-1", "name": "Dijital ürün", "category1": "Dijital", "itemType": "VIRTUAL", "price": 5000 }
],
"mobileBilling": { "gsmNumber": "+905321234567" }
}'Yanıt ve aksiyon
{
"status": "partial",
"code": "CUSTOMER_ACTION_REQUIRED",
"message": "…",
"data": {
"paymentId": "7b0e4c2a-1f3d-4e5b-8a6c-9d0e1f2a3b4c",
"orderId": "ORDER-1002",
"status": "PROCESSING",
"paymentMethod": "MOBILE_BILLING",
"providerCode": "<providerCode>",
"action": {
"id": "act_5c2e9f0a1b3d4e6f7a8b9c0d1e2f3a4b",
"type": "OTP",
"expiresAt": "2026-10-11T09:03:00.000Z",
"otp": { "maskedTarget": "53****67" },
"consent": { "required": true, "url": "https://…" }
}
},
"statusCode": 202,
"requestId": "…"
}<providerCode>bir yer tutucudur.- Kodun geçerlilik süresi
action.expiresAtalanındadır. consent.urlsağlayıcının sözleşme adresidir; alıcıya açılabilir bir bağlantı olarak gösterin.
Onay
POST https://api-gateway.lunixi.com/api/v1/payments/{paymentId}/actions/{actionId}/confirm{ "otp": "123456", "consentAccepted": true }| Sonuç | Yanıt | Ne yapmalı |
|---|---|---|
| Ödeme tamamlandı | 200, data.status CAPTURED | Siparişi payment.captured ile teslim edin |
| Sözleşme onayı yok | 422 payment.action.consent_required | Alıcının onayını alıp consentAccepted: true ile tekrar gönderin. Deneme hakkı düşmez |
| Kod eksik ya da biçimi bozuk | 400 payment.action.otp_required | Kodu yalnız rakamlarla gönderin. Deneme hakkı düşmez |
| Kod yanlış | 422 payment.action.input_rejected | Aksiyon açık; kalan hak details.attemptsRemaining. Hak 3'tür |
| Hak bitti | 400 payment.action.attempts_exhausted | Ödeme FAILED; yeni ödeme başlatın |
| Sonuç sağlayıcıyla doğrulanıyor | 202 PAYMENT_PENDING_RECONCILIATION | Yeni ödeme başlatmayın; webhook'u bekleyin |
Kodun süresi dolarsa ödeme FAILED olur ve payment.failed gönderilir.
Kodu yeniden gönderme
Alıcı kodu almadıysa POST /payments/{paymentId}/actions/{actionId}/resend ile yeni kod gönderin. Yanıt yeni bir aksiyon taşır; confirm'de yeni action.id'yi kullanın. Ödeme başına en fazla 3 kez ve iki gönderim arasında en az 30 saniye beklenerek gönderilebilir; kurallar Payment — resend ile aynıdır.
Hat uygunluğu ve sınırlar
- Hat bu yönteme kapalıysa, uygun değilse ya da fatura limiti tutara yetmiyorsa ödeme reddedilir: yanıt
400,data.statusFAILED. Alıcıya başka bir yöntem önerin. - Birden fazla sağlayıcı bağlıyken
providerCodegöndermezseniz uygunluk ödeme başlamadan sağlayıcılara sorulur. Hiçbiri uygun değilse yanıt422payment.provider.none_eligibleolur; ödeme kaydı açılmaz. - Tutar sınırları ve para birimleri
GET /payments/methodsyanıtındakiminAmount,maxAmountvecurrenciesalanlarındadır.
Ön provizyon
Ön provizyon desteği GET /payments/methods yanıtındaki preauth alanındadır. Desteklenmiyorsa preauth: true ile istek ödeme başlamadan 422 payment.preauth.unsupported_for_method alır; tutar faturaya yansıtılmaz.
Hatalar
| Durum | Yanıt |
|---|---|
| Hat yok ya da biçimi bozuk; tanımda olmayan alan | 400 payment.method.block_invalid (details.field: mobileBilling.gsmNumber) |
providerCode yok ve bağlı sağlayıcıların hiçbiri ödemeyi karşılamıyor | 422 payment.provider.none_eligible |
| Seçilen sağlayıcı bağlı değil | 422 payment.provider.not_available |
| Ön provizyon desteklenmiyor | 422 payment.preauth.unsupported_for_method |
| Hat uygun değil ya da limit yetersiz | 400, ödeme FAILED |
Aksiyon uçlarının kodları: Payment — Hata kodları.
Webhook'lar
| Event | Ne zaman |
|---|---|
payment.captured | Tutar faturaya yansıtıldı. 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 (ret, süresi dolan kod ya da biten deneme hakkı) |
Olayların data'sında paymentMethod: "MOBILE_BILLING" ve sağlayıcının providerCode'u bulunur. Bkz. Webhook'lar.
Sonraki adımlar
- Payment — ortak istek, yanıt ve hata kodları
- Yöntemleri Listeleme — bağlı sağlayıcılar ve sağlayıcı seçimi
- Checkout Formu — Payment — Faturana Yansıt'ın formdaki akışı