Payment Orchestrator
Faturana Yansıt

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 422 payment.provider.not_available alı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 providerCode alanındadır.
  • Bağlı sağlayıcıların hiçbiri bu ödemeyi karşılamıyorsa istek 422 payment.provider.none_eligible alı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.

AlanAçıklama
providerCodeSağlayıcının kodu
outcomeINELIGIBLE: 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
reasonSebep 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 UNAVAILABLE ya da NOT_CHECKED ise aynı isteği daha sonra tekrar deneyebilirsiniz.
  • Sağlayıcıyı mobileBilling.providerCode ile kendiniz de seçebilirsiniz.
  • Bütün sonuçlar INELIGIBLE ise 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ı

AlanTipZorunluAçıklama
paymentMethodstringEvetMOBILE_BILLING
mobileBillingobjectEvetFaturana Yansıt bloğu; alanları aşağıdaki satırlardadır
mobileBilling.gsmNumberstringEvet*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.providerCodestringHayırSağ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öreSağlayıcının inputFields tanımındaki diğer alanlar; bkz. Yöntem alanları. Tanımda olmayan alan gönderilemez
preauthbooleanHayırtrue: ön provizyon; sağlayıcının desteklemesi gerekir. Bkz. Ön provizyon
callbackUrlstringHayırhttp 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ı

AlanTipZorunluAçıklama
amountintegerEvetTutar, 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
currencystring (enum)EvetISO 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
orderIdstringEvetSizin sipariş numaranız, en fazla 128 karakter. Örnek: ORD-84722
customerIdstringHayırSizin 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
descriptionstringHayırÖdeme açıklaması
localestringHayırMesaj dili, varsayılan tr
paymentChannelstringHayırÖdeme kanalı. Örnek: WEB
paymentGroupstringHayırÜrün grubu. Örnek: PRODUCT
buyerobjectHayırAlıcı bilgisi; bkz. buyer
shippingAddressobjectHayırTeslimat adresi; bkz. Adres
billingAddressobjectHayırFatura adresi; bkz. Adres
basketItemsarrayHayırSepet kalemleri; bkz. basketItems[]
metadataobjectHayırKendi 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.

AlanTipZorunluÖrnek
idstringHayırCUST-1
namestringEvetAda
surnamestringEvetYılmaz
identityNumberstringEvet11111111111
emailstring (e-posta)Evet[email protected]
gsmNumberstringEvet+905000000000
citystringEvetİstanbul
countrystringEvetTurkey
zipCodestringEvet34732
ipstringEvetAlıcının IP adresi
registrationDatestringHayır2024-04-21 15:12:09
lastLoginDatestringHayır2026-10-05 12:43:35
registrationAddressstringHayırKayı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.

AlanTipÖrnek
contactNamestringAda Yılmaz
addressstringAltunizade Mah. …
citystringİstanbul
countrystringTurkey
zipCodestring34742

İki adresin farkı ve hata alan yolları: Adres Bilgileri.

basketItems[]

AlanTipZorunluAçıklama
idstringEvetKalem kodu
namestringEvetKalem adı
category1stringEvetAna kategori
category2stringHayırAlt kategori
itemTypestring (enum)EvetPHYSICAL ya da VIRTUAL
priceintegerEvetKalem 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.expiresAt alanındadır.
  • consent.url sağ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ıtNe yapmalı
Ödeme tamamlandı200, data.status CAPTUREDSiparişi payment.captured ile teslim edin
Sözleşme onayı yok422 payment.action.consent_requiredAlıcının onayını alıp consentAccepted: true ile tekrar gönderin. Deneme hakkı düşmez
Kod eksik ya da biçimi bozuk400 payment.action.otp_requiredKodu yalnız rakamlarla gönderin. Deneme hakkı düşmez
Kod yanlış422 payment.action.input_rejectedAksiyon açık; kalan hak details.attemptsRemaining. Hak 3'tür
Hak bitti400 payment.action.attempts_exhaustedÖdeme FAILED; yeni ödeme başlatın
Sonuç sağlayıcıyla doğrulanıyor202 PAYMENT_PENDING_RECONCILIATIONYeni ö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.status FAILED. Alıcıya başka bir yöntem önerin.
  • Birden fazla sağlayıcı bağlıyken providerCode göndermezseniz uygunluk ödeme başlamadan sağlayıcılara sorulur. Hiçbiri uygun değilse yanıt 422 payment.provider.none_eligible olur; ödeme kaydı açılmaz.
  • Tutar sınırları ve para birimleri GET /payments/methods yanıtındaki minAmount, maxAmount ve currencies alanları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

DurumYanıt
Hat yok ya da biçimi bozuk; tanımda olmayan alan400 payment.method.block_invalid (details.field: mobileBilling.gsmNumber)
providerCode yok ve bağlı sağlayıcıların hiçbiri ödemeyi karşılamıyor422 payment.provider.none_eligible
Seçilen sağlayıcı bağlı değil422 payment.provider.not_available
Ön provizyon desteklenmiyor422 payment.preauth.unsupported_for_method
Hat uygun değil ya da limit yetersiz400, ödeme FAILED

Aksiyon uçlarının kodları: Payment — Hata kodları.

Webhook'lar

EventNe zaman
payment.capturedTutar 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