Payment Orchestrator
Checkout Formu

Checkout Formu

Hosted checkout formu, kart ödemesi almanın önerilen yoludur: sunucunuz POST /payments/intents ile bir payment intent oluşturur, alıcı ödemeyi Lunixi'nin formunda tamamlar ve kart verisi altyapınıza hiç dokunmaz. Bu sayfa intent create'in eksiksiz referansıdır — tüm alanlar, istek bazlı politika override'ları, yanıt ve sonrasında tarayıcıda olanlar.

Tüm tutarlar minor-unit (kuruş) cinsinden tam sayıdır: "amount": 10050 = ₺100,50. Bu kural amount, basketItems[].price ve settings.threeD.forceAmountMinor için geçerlidir.

Nasıl çalışır

Intent oluşturun (sunucu)

Step-Up auth ile POST /payments/intents (Bearer + Ed25519 imza + Idempotency-Key). Yanıt, allowedOrigin'inize bağlı, ~15 dakika geçerli bir form token'ı döner.

Formu mount edin (tarayıcı)

Sayfanızda formun çizileceği boş bir <div> açın; SDK içini kendisi doldurur.

<div id="lunixi-checkout-form"></div>
 
<script src="https://cdn.lunixi.com/lunixi-checkout.min.js"></script>
<script>
  const checkout = Lunixi.checkout.create({
    type: 'payment',
    target: 'lunixi-checkout-form',
    options: { token: 'intent yanıtındaki token' },
  });
 
  checkout.mount('#lunixi-checkout-form');
</script>

mount() önce getElementById, bulamazsa querySelector dener — 'lunixi-checkout-form' ve '#lunixi-checkout-form' aynı işi yapar. DOM elemanı da geçirebilirsiniz.

⚠️

Hedef <div>'i boş bırakın ve sabit yükseklik vermeyin. SDK monte ederken içeriği temizler; form yüksekliği de kart girildikçe değişir (taksit tablosu açılır) ve SDK bunu kendisi ayarlar.

Yalnız kart alanını (tek satır, PCI kapsamı dar) istiyorsanız createCardField varyantını kullanın → Kart Alanı.

Fraud bootstrap & session proof

Form POST /payments/form/live-analyze çağırır; bu çağrı oturumu analiz eder ve bir session-proof cookie set eder. Karta dokunan çağrılar bu cookie olmadan reddedilir. Yaşam döngüsü sinyalleri /payments/form/live-event üzerinden akar.

BIN & taksit

Alıcı kart numarasını yazarken form; kartın marka ve ailesini (POST /form/bin/info) ve taksit tablosunu (POST /form/bin/installments) çözer. Taksit quote'u bağlayıcı bir quoteToken döner — alıcıya gösterilen tutar, çekilen tutarın ta kendisidir. Bkz. Taksit & BIN.

Tokenize

Kart alanları izole bir secure-fields iframe'inde yaşar. POST /payments/form/tokenize girilen kartı tek kullanımlık bir kart token'ına çevirir (paymentCards.secureCardToken olarak geri gönderilir) — PAN, merchant sayfasına asla açılmaz.

Çekim — 2D veya 3D

Form POST /payments/form/2d veya POST /payments/form/3d çağırır (token, session proof ve taksit seçildiyse installmentQuoteToken ile). Hangisinin çalışacağına geçerli 3D politikası karar verir — aşağıdaki force3D bölümüne bakın. Karar, intent oluşturulurken intent'e dondurulur; 3D zorunluysa doğrudan /form/2d denemesi 409 THREE_D_REQUIRED ile reddedilir (SDK bu durumda 3D endpoint'ini kullanır).

3D doğrulaması & sonuç

3D'de ödeme AWAITING_3D'ye geçer ve alıcı banka doğrulaması için GET /payments/threed/:token adresine (public, tek kullanımlık token) yönlendirilir. Ardından callback çözülür ve sonuç callbackUrl'inize bilgilendirici bir form POST (_signature + _timestamp platform bütünlük alanlarıyla) olarak iletilir; otorite kaynak olan webhook'lar da tetiklenir — bkz. 3D Form.

3D Secure gösterimi

Panelde Ödeme → Form Ayarları → 3D Secure → 3D Secure gösterimi ile bankanın doğrulama ekranının nasıl açılacağını seçersiniz:

SeçenekNe olur
Form içinde (varsayılan)Bankanın doğrulama ekranı formun üstünde bir pencerede açılır. Doğrulama bitince pencere kapanır ve form sıradaki adıma geçer; alıcı sayfanızdan ayrılmaz
Ayrı sayfadaAlıcı bankanın sayfasına yönlendirilir. Banka alıcıyı Lunixi'nin ödeme devam sayfasına döndürür; kalan adımlar orada yürür ve ödeme bitince alıcı sonuçla callbackUrl'inize döner
  • Otomatik ayrı sayfa: Banka doğrulama ekranının pencerede açılmasına izin vermezse 3D Secure aynı kart için ayrı sayfada otomatik olarak yeniden başlatılır. Bunun için bir şey yapmanız gerekmez.
  • Seçim parçalı ödemedeki kart doğrulamalarında uygulanır. Tek kartlı ödemede 3D Secure akışı 3D Form sayfasındaki gibidir.
  • Değişiklik yalnız yeni başlayan ödemeleri etkiler; süren bir ödeme başladığı seçimle tamamlanır.

Devam sayfası, callbackUrl'inize gelen alanlar ve hata kodları: Parçalı Ödeme › 3D Secure ve devam sayfası.

İstek

POST /payments/intents — Step-Up auth.

Alanlar

AlanTipZorunluAçıklama
amountinteger (minor unit)EvetTek tutar alanı, örn. 10050 = ₺100,50. Sepet toplamıdır: alıcının ödediği ürün ve hizmet bedeli, vade farkı hariç. Min 1. Bkz. Tutar ve taksit.
currencystring (ISO 4217)Evetörn. "TRY"
orderIdstringEvetBenzersiz sipariş referansınız
callbackUrlstringHayır3D / async sonucun POST edileceği adres (HMAC-imzalı)
localestringHayırForm dili. Varsayılan "tr".
buyerobjectHayırAlıcı bilgileri — aşağıya bakın
shippingAddressobjectHayırAdres objesi — aşağıya bakın
billingAddressobjectHayırAdres objesi — aşağıya bakın
basketItemsarrayHayırSepet satırları — aşağıya bakın
paymentGroupstringHayırörn. "PRODUCT"
paymentChannelstringHayırörn. "WEB"
methodenumHayırÖdeme tipi; varsayılan normal ödeme. Pazaryeri split ödemeleri kendi endpoint'ini kullanır — bkz. Pazaryeri.
descriptionstringHayırMüşteriye görünen çekim açıklaması
customerIdstringHayırMüşteri referansınız — Ödeme Listeleme'de filtreleme sağlar
metadataobjectHayırÖdemeyle birlikte geri dönen serbest key/value verisi
force3DbooleanHayırÖdeme bazlı 3D anahtarı — her politikayı ezer, aşağıya bakın
preauthbooleanHayırtrue → ön provizyon: tutar alıcının kartında bloke edilir, ödeme AUTHORIZED olur; sonra capture ya da void yaparsınız. Verilmezse ya da false ise tutar hemen çekilir. Aşağıya bakın
settingsobjectHayırİstek bazlı form ayarı override'ı — aşağıya bakın

buyer objesi

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

Checkout Formu'ndaki uzunluk sınırları ve alıcı bilgilerinin nerede kullanıldığı: Alıcı Bilgileri.

shippingAddress / billingAddress objesi

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 hangisinin ne zaman kullanıldığı: Adres Bilgileri.

basketItems[] objesi

AlanSatır içinde zorunluÖrnek
idEvet"BI101"
priceEvet — integer, minor unit10050
nameEvet"Binocular"
category1Evet"Collectibles"
category2Hayır"Accessories"
itemTypeEvet — "PHYSICAL" veya "VIRTUAL""PHYSICAL"

Kalemlerin price toplamı amount'a eşit olmalıdır. Kalem kuralları, basketItems.0.price gibi hata alan yolları ve isteğe bağlı sigorta alanları: Sepet Kalemleri.

Tutar ve taksit

  • amount tek tutar alanıdır. Tutarı yalnız amount ile gönderin; kaldırılan tutar alanları 400 payment.amount.field_removed alır.
  • Intent'te taksit alanı yoktur; gönderilirse istek 400 VALIDATION_ERROR alır. Alıcı taksiti formda seçer.
  • Vade farkını siz göndermezsiniz. Sistem vade farkını alıcının seçtiği bağlayıcı taksit teklifinden hesaplar ve çekilen tutara ekler: çekilen tutar = amount + vade farkı.
  • Yanıtlardaki ve webhook'lardaki tutar alanları (data.amount, capturedAmountMinor …) çekilen tutarı gösterir; taksitli ödemede vade farkı dahildir.

force3D — en üst düzey override

force3D, ödeme bazlı 3D anahtarıdır:

  • force3D: true → bu ödeme 3D Secure ile işlenir — panel politikasından ve settings.threeD içindeki her şeyden bağımsız olarak.
  • force3D: false → bu ödeme politika tarafından 3D'ye zorlanmaz.
  • Verilmezse → geçerli politika karar verir (panel ayarları; istek bazında settings.threeD ile override edilebilir).

Açıkça verilen force3D her şeyi ezer — panel 3D politikasını da, tutar eşiği dahil settings.threeD override'ını da.

preauth — ön provizyon

Formu oluştururken "preauth": true gönderirseniz bu ödeme ön provizyon olarak alınır:

  • Alıcı formda ödemeyi tamamlayınca tutar kartında bloke edilir, çekilmez; ödeme AUTHORIZED olur ve payment.authorized webhook'u gelir.
  • Formun yaptığı çekim (2D, 3D Secure ya da kart dışı yöntem) bu karara uyar; formda ayrıca bir şey göndermezsiniz.
  • Formda yalnız ön provizyonu destekleyen ödeme yöntemleri gösterilir.
  • Tutarı sonra capture ile çekersiniz ya da void ile serbest bırakırsınız; süresi içinde capture edilmeyen bloke EXPIRED olur.
{
  "amount": 10050,
  "currency": "TRY",
  "orderId": "ORDER-1001",
  "callbackUrl": "https://merchant.example.com/payment/callback",
  "preauth": true
}

Süre, desteklenen yöntemler ve hatalar: Ön Provizyon, Capture & İptal.

settings — istek bazlı form ayarı override'ı

settings, merchant panelinizdeki form ayarlarının üzerine yalnızca bu intent için uygulanır. Override kuralı alana göre değişir:

AlanTipDavranış
settings.paymentMethodsstring[] — örn. ["card"]Bu formda gösterilecek yöntemler. Yalnız daraltır: geçerli küme panel kümesiyle kesişimdir — panelde kapalı bir yöntem buradan açılamaz.
settings.threeD.mode"2d" | "3d" | "auto"Bu intent için 3D modu. Tam ikame: settings.threeD gönderilmişse, bu intent için panelin 3D yapılandırmasının yerine geçer (sizin imzalı, müşteri-bazlı kararınız). force3D verilmişse tamamen yok sayılır.
settings.threeD.forceAmountMinorstring (minor unit)Tutar eşiği: bu tutar ve üzeri ödemeler 3D'ye zorlanır. "0" = her ödeme 3D; null = eşik yok. settings.threeD gönderildiğinde mode ile birlikte ikame edilir.
settings.buyerProtection.enabledbooleanBu ödemede Alıcı Koruması çalışsın mı. Tam ikame: bu intent-bazlı karar panel varsayılanının yerine geçer — panelde kapalı olsa bile true göndermek bu formda Alıcı Koruması seçeneğini gösterir. Aşağıdaki kutuya bakın.

Güvenlik-hassas form ayarları (identityCheck, cardStorage, installmentTab) istek bazında override edilemez — her zaman panelden gelir.

Alıcı Koruması nedir? Alıcı Koruması bir onay-linki akışıdır: alıcı, satın almayı bir onay linki üzerinden teyit eder; ödemeye açık bir alıcı-onayı adımı eklenir. 3D Secure değildir ve onun yerine geçmez — 3D banka tarafında bir kimlik doğrulamasıdır; Alıcı Koruması Lunixi tarafında bir teyit katmanıdır. İkisi birbirinden bağımsız yapılandırılır.

Örnek istek

curl -X POST "https://api-gateway.lunixi.com/api/v1/payments/intents" \
  -H "Authorization: Bearer at_live_5f3e2b1a..." \
  -H "Content-Type: application/json" \
  -H "X-Key-Id: key_01JZ8H2M4Q" \
  -H "X-Date: 2026-07-06T12:00:00.000Z" \
  -H "X-Nonce: 9f8d2c4e-1a3b-4c5d-8e7f-0a1b2c3d4e5f" \
  -H "Digest: SHA-256=k6I5cUt...=" \
  -H "X-Signature: MEUCIQDx...==" \
  -H "Idempotency-Key: order-ORD-9988-attempt-1" \
  -d '{
    "amount": 10050,
    "currency": "TRY",
    "orderId": "ORD-9988",
    "callbackUrl": "https://shop.example.com/payment/result",
    "customerId": "c_98765432",
    "description": "Order #9988 payment",
    "buyer": {
      "name": "John", "surname": "Doe",
      "identityNumber": "12345678901",
      "email": "[email protected]", "gsmNumber": "+905350000000",
      "city": "İstanbul", "country": "Turkey",
      "zipCode": "34732", "ip": "85.34.78.112"
    },
    "basketItems": [
      { "id": "BI101", "price": 10050, "name": "Binocular",
        "category1": "Collectibles", "itemType": "PHYSICAL" }
    ],
    "settings": {
      "paymentMethods": ["card"],
      "threeD": { "mode": "auto", "forceAmountMinor": "500000" },
      "buyerProtection": { "enabled": true }
    }
  }'

Yanıt

201 Created:

{
  "status": "success",
  "code": "CHECKOUT_INITIALIZED",
  "data": {
    "paymentId": "9c6f2b1a-4e8d-4a3f-b5e6-2d7c1a9b8e30",
    "token": "eyJhbGciOiJIUzI1NiIs...",
    "checkoutFormContent": "<script>…</script>"
  }
}
AlanAçıklama
paymentIdÖdeme id'si — GET /payments/:id, capture, void, refund için kullanın
tokenForm token'ı. Tarayıcıda checkout SDK'sına verin. Tek amaçlıdır.
checkoutFormContentHosted checkout SDK'sını bu token'la yükleyip mount eden, sayfaya gömülmeye hazır bootstrap <script>

Token origin'e bağlıdır (metadata.allowedOrigin / callbackUrl origin'inize) ve süresi dolar — varsayılan 15 dakika. Süresi dolan token → yeni intent oluşturun.

Hatalar

StatusDurumNe yapmalı
400Validasyon hatası (eksik amount/currency/orderId, tam sayı olmayan tutar, bozuk settings)Hata mesajındaki alanı düzeltin; tutarların minor-unit tam sayı olduğunu unutmayın
401Eksik/geçersiz Step-Up header'ları, süresi geçmiş X-Date, tekrar kullanılan nonce, hatalı imzaBkz. Kimlik doğrulama hataları
403Bearer key ile imza anahtarı uyuşmazlığı (AUTH_MERCHANT_MISMATCH)Aynı merchant & environment key'lerini kullanın
401 (form çağrıları)Form token geçersiz veya süresi dolmuş (~15 dk)Yeni intent oluşturun ve formu yeniden mount edin
409 THREE_D_REQUIRED (/payments/form/2d üzerinde)Bu ödeme için 3D zorunlu (force3D, eşik veya mode gereği) ama 2D çekim denendi3D yolunu izleyin — form SDK'sı bunu otomatik yapar
/payments/form/2d'den 3D redirect döndü (customer-present SALE)Seçilen sağlayıcı/credential 2D yapamıyor; çekim otomatik olarak 3DS'e yükseltildi (escalationReason: "PROVIDER_2D_UNSUPPORTED")3D redirect alanlarını ele alın — bkz. 2D Form › sağlayıcı yeteneği
Tekrarlanan Idempotency-KeyOrijinal yanıt döner, ikinci çekim olmazBeklenen davranış — güvenle tekrar deneyebilirsiniz

Webhook'lar

Checkout formu akışı, sonuca göre şu eventleri üretir:

  • payment.captured — çekim tamamlandı, para çekildi (2D, veya doğrulama sonrası 3D)
  • payment.authorized — tutar bloke edildi, authorize-sonra-capture kurulumları için
  • payment.failed — nihai ret (yapılandırılmış ret detayı içerir)
  • payment.expired — yalnız-authorize bir hold, capture edilmeden süresi doldu

Teslimat ve imza doğrulaması: Webhook'lar.

Sigorta ekleme

Alıcınıza Checkout Formu'nda ürünle birlikte, sizin anlaştığınız sağlayıcının sigortasını sunabilirsiniz. Ödeme isteğinde ayrı bir sigorta parametresi yoktur:

  • Sigortayı panelden açarsınız: Sigorta menüsünde sigortayı ve sunacağınız tipi açar, Form Ayarları > Sigorta'da formdaki yerini seçersiniz. Bu ayarlar kapalıysa formda sigorta hiç görünmez; adımlar: Sigorta › Kurulum.
  • Hangi sigortanın sunulacağını sepet kalemlerinizdeki isteğe bağlı sigorta alanları belirler; bkz. Sepet Kalemleri › Sigorta alanları.
  • Sigortasız ödemeleriniz etkilenmez. Sigorta alanı göndermezseniz ya da sigorta sunulamazsa ödeme her zamanki gibi devam eder.

Ürünün nasıl çalıştığı ve yol seçimi: Sigorta.

Sonraki adımlar