Payment Orchestrator
2D

Kart — 2D

POST /payments/direct/payment ile paymentMethod: "CARD" gönderdiğinizde ve force3D göndermediğinizde (ya da false gönderdiğinizde) kart kendi sunucunuzdan tek istekte çekilir. Banka tarafında 3D Secure doğrulaması ve yönlendirme yoktur; sonuç (başarı ya da red) aynı yanıtta döner. Kayıtlı kartla tekrar çekim, sunucu tarafı tahsilat ve yönlendirmenin mümkün olmadığı akışlar için kullanın. 3D doğrulaması olmadığı için sorumluluk devri (liability shift) yoktur; 2D çekimi kendi risk kontrollerinizle birlikte kullanın.

Checkout Formu kullanıyorsanız bu sayfa sizin için değildir; kart çekimini form yapar → 2D Form · 3D Form.

Tüm tutarlar minor unit (kuruş) tam sayıdır: "amount": 10050 = ₺100,50. Ondalık ya da float göndermeyin.

⚠️

PCI DSS gerektirir. Ham kart numarasını (PAN) sunucunuzda alıp gönderdiğiniz için sistemleriniz PCI DSS kapsamına (SAQ D) girer. Kart verisi işlemek için sertifikalı değilseniz Checkout Formu kullanın. Daha önce kaydedilmiş bir kartı çekmek için PAN gerekmez; bkz. Kayıtlı kart çekimi.

Nasıl çalışır

İmzalı isteği gönderin

Sunucunuzdan POST /payments/direct/payment çağırın: paymentMethod: "CARD", sipariş alanları ve card. İstek Step-Up kimlik doğrulaması ve Idempotency-Key taşır.

Platform kontrol eder, yönlendirir ve çeker

İşlem risk ve limit kontrollerinden geçer, uygun sağlayıcıya yönlendirilir ve anında çekilir.

Senkron sonucu okuyun

Yanıt nihai durumu taşır: başarıda CAPTURED, redde FAILED. Risk ya da limit kuralı ödemeyi 3D Secure'a çevirdiyse yanıt bir REDIRECT aksiyonu taşır; bkz. 2D isteği ne zaman 3D'ye döner.

Webhook ile teyit edin

payment.captured ya da payment.failed kalıcı kayıt olarak webhook adresinize gönderilir.

Kimlik doğrulama

Uç Step-Up ister: Authorization: Bearer at_… token'ınız ve isteğin Ed25519 imzası. Her istek şu başlıkları taşır:

BaşlıkDeğer
AuthorizationBearer at_test_… (test) ya da Bearer at_live_… (canlı)
X-Key-IdKayıtlı Ed25519 public key'inizin kimliği
X-DateISO 8601 istek zamanı; sunucu saatine göre ±5 dakika içinde
X-Nonceİstek başına benzersiz, tek kullanımlık değer
DigestHam JSON gövdesinin SHA-256=<base64> özeti
X-SignatureKanonik dizgi üzerinde Base64 Ed25519 imzası
Idempotency-KeyZorunlu, en fazla 200 karakter; bkz. Idempotency

İmzanın nasıl kurulacağı Kimlik Doğrulama sayfasındadır. Uç hesabınızda Payment Gateway ürününün açık olmasını ister.

İstek

POST https://api-gateway.lunixi.com/api/v1/payments/direct/payment
Content-Type: application/json

Kart alanları

AlanTipZorunluAçıklama
paymentMethodstringEvetCARD
cardobjectEvetKart bilgisi; bkz. card
force3DbooleanHayır2D için gönderilmez ya da false. true 3D Secure ister → Kart — 3D Secure
installmentintegerHayırTaksit sayısı, varsayılan 1. 2 ve üzeri için installmentQuoteToken gerekir
installmentQuoteTokenstringHayırTaksit quote'undan aldığınız bağlayıcı token; bkz. Taksit
callbackUrlstringHayırhttp ya da https adresi, en fazla 2048 karakter. Ödeme risk ya da limit kuralıyla 3D Secure'a dönerse alıcının tarayıcısı sonuçla bu adrese POST edilir
preauthbooleanHayırtrue: tutar bloke edilir, ödeme AUTHORIZED olur; bkz. Ön provizyon. Verilmezse ya da false ise tutar anında çekilir

card, force3D, installment ve installmentQuoteToken yalnız paymentMethod: "CARD" ile gönderilebilir. Kartta sağlayıcıyı yönlendirme seçer; providerCode gönderilmez.

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.

card

AlanTipZorunluAçıklama
cardHolderNamestringHam karttaKart üzerindeki ad soyad
cardNumberstringHam karttaKart numarası
expireMonthstringHam karttaİki haneli ay, 01–12
expireYearstringHam karttaİki haneli yıl. Örnek: 30
cvcNumberstringHam kartta3 ya da 4 haneli güvenlik kodu. Kayıtlı kart çekiminde de bankaların çoğu ister
cardUserKeystringKayıtlı karttaKartın kayıtlı olduğu müşteri anahtarı
cardTokenstringKayıtlı karttaKayıtlı kartın kalıcı referansı (storedCardToken). Checkout Formu'nun tek kullanımlık kart token'ı burada kullanılamaz
cardSavebooleanHayırtrue: kart, ödeme başarılı olursa customerId anahtarının altına kaydedilir. Yalnız 3D Secure istekte (force3D: true) gönderilebilir; 2D istekte 400 payment.card.save_requires_3ds alır
cardNamestringHayırKaydedilen karta verdiğiniz ad; cardSave: true ile birlikte. Örnek: İş kartım
  • expireMonth ve expireYear gönderildiğinde iki haneli olmalıdır.
  • Ham kartla çekimde cardHolderName, cardNumber, expireMonth, expireYear ve cvcNumber gönderilir. Kayıtlı kartla çekimde ham kart alanları yerine cardUserKey ve cardToken gönderilir.

2D istekte cardSave gönderilmez: kart kaydı yalnız 3D Secure ile yapı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: 0b9a6c52-6d1e-4f0e-9a51-4c3f9e2d7a10" \
  -H "Digest: SHA-256=..." \
  -H "X-Signature: ..." \
  -H "Idempotency-Key: ORD-84722-1" \
  -d '{
    "paymentMethod": "CARD",
    "amount": 10050,
    "currency": "TRY",
    "orderId": "ORD-84722",
    "customerId": "cust_7788",
    "card": {
      "cardHolderName": "Ada Yilmaz",
      "cardNumber": "5400000000000004",
      "expireMonth": "12",
      "expireYear": "30",
      "cvcNumber": "123"
    }
  }'

Yanıt

Başarılı çekim HTTP 200 ile döner:

{
  "status": "success",
  "code": "PAYMENT_CAPTURED",
  "message": "…",
  "data": {
    "paymentId": "9c6f2b1a-4e8d-4a3f-b5e6-2d7c1a9b8e30",
    "orderId": "ORD-84722",
    "status": "CAPTURED",
    "paymentMethod": "CARD",
    "providerCode": "<providerCode>"
  },
  "statusCode": 200,
  "requestId": "…"
}
AlanAçıklama
paymentIdÖdeme kimliği; capture, iade ve sorgu çağrılarında kullanılır
orderIdSizin sipariş numaranız
statusCAPTURED; ön provizyonda AUTHORIZED
paymentMethodCARD
providerCodeÖdemeyi yürüten sağlayıcının kodu; kartta sağlayıcıyı yönlendirme seçer. <providerCode> bir yer tutucudur

Reddedilen çekim HTTP 400 ile döner. Zarf status: "failure", ödeme data.status: "FAILED" olur ve code ret sebebini taşır. Varsa details.retryability (RETRYABLE, NON_RETRYABLE, UNKNOWN) aynı isteği yeniden denemenin anlamlı olup olmadığını söyler.

{
  "status": "failure",
  "code": "RISK_BLOCKED",
  "message": "…",
  "data": {
    "paymentId": "5d1e7a0c-2b9f-4c61-8f3e-0a4b6c8d2e91",
    "orderId": "ORD-84722",
    "status": "FAILED",
    "paymentMethod": "CARD"
  },
  "statusCode": 400,
  "requestId": "…"
}

İstek hiç işlenmeden reddedildiyse (doğrulama ya da kimlik hatası) data boştur ve code hatayı anlatır.

Sonucu o an kesinleşmeyen bir çekim HTTP 202 ile döner: zarf status: "partial", code: "PAYMENT_PENDING_RECONCILIATION", data.status: "NEEDS_RECONCILIATION". Platform sonucu sağlayıcıya sorarak kesinleştirir ve payment.captured ya da payment.failed webhook'unu gönderir. Bu durumda yeni bir çekim açmayın; sonucu webhook ile ya da GET /payments/:id ile bekleyin.

code alanına göre dallanın; message metni değişebilir. Zarfın alanları için bkz. Hata Yönetimi.

2D isteği ne zaman 3D'ye döner

3D Secure kararı sizin force3D seçiminizdir. Checkout Formu için tanımlanan 3D ayarları (intent'teki force3D, settings.threeD ve panel 3D politikası) bu isteğe uygulanmaz.

İki istisna vardır. Risk değerlendirmesi ya da hesabınıza tanımlı bir limit kuralı ödemenin 3D Secure ile yapılmasını isteyebilir. O zaman yanıt CAPTURED yerine 3D yanıtıdır: HTTP 202, zarf status: "partial", code: "AWAITING_3D", data.status: "AWAITING_3D" ve data.action bir REDIRECT aksiyonudur.

Bu yanıtı 3D Secure akışıyla aynı biçimde ele alın: alıcının tarayıcısını action.redirect.url adresine yönlendirin, sonuç callbackUrl adresinize ve webhook'unuza gelir. Yanıt alanları için bkz. Kart — 3D Secure › Yanıt; callbackUrl adresinize gelen sonucun alanları ve nasıl ele alınacağı için bkz. imzalı callback.

⚠️

Alıcı ekran başında değilse (sunucu tarafı tahsilat) yönlendirme yapamazsınız. Bu durumda siparişi ödenmiş saymayın ve alıcıdan ödemeyi ekran başında tamamlamasını isteyin. Yönlendirilmeyen ödeme bir süre sonra FAILED olarak kapanır ve payment.failed gönderilir. Alıcı ekran başındaysa callbackUrl gönderin ki 3D'ye dönen ödemenin sonucu alıcıyla birlikte sayfanıza gelsin.

Sağlayıcı 2D yapamadığında

Ödemeyi yönlendiren sağlayıcının anlaşması 2D (non-secure) satışı kapsamıyorsa çekim 2D tamamlanamaz. Sunucudan başlatılan 2D çekim müşterisiz (merchant-initiated) sayılır ve 3D'ye otomatik yükseltilmez:

  • 2D yapabilen aday sağlayıcı kalmazsa ödeme FAILED olur ve ret kodu NO_2D_CAPABLE_PROVIDER'dır.
  • Bu kalıcı bir sonuçtur. Aynı isteği tekrar göndermek aynı sonucu verir; abonelik ya da tahsilat tekrar denemeleri bunu kalıcı red olarak ele almalıdır.
  • Ödemeyi alıcı ekran başındayken 3D Secure ile alın.

Anlaşma yetkileri (supported_operations)

Her sağlayıcı kimlik bilgisi, anlaşmasının izin verdiği işlemlerle sınırlandırılabilir. Bu, kimlik bilgisi üzerinde kalıcı bir anlaşma bilgisidir ve panelde kimlik bilgisi formunda yönetilir.

İşlemAnlamı
PURCHASE2D (non-secure) satış
PURCHASE_3D3D Secure satış (3DS ve 3D da kabul edilir)
AUTHORIZEÖn provizyon
CAPTUREProvizyonu çekme
REFUND / PARTIAL_REFUNDTam / kısmi iade
VOIDİptal
TOKENIZEKart saklama (TOKENIZATION da kabul edilir)

supported_operations boşsa (null) kısıt yoktur. Liste verildiğinde yalnız listedeki işlemler yapılır. 2D satışı geçici olarak kapatmak için yönlendirme kısıtlarındaki "2D (non-secure) satışı kapat — yalnız 3D" ayarı da aynı sonucu verir; fark, bu ayarın geri alınabilir bir operasyon kararı olmasıdır.

Kayıtlı kart çekimi

Ayrı bir kayıtlı kart ucu yoktur. Aynı istekte card nesnesine ham kart alanları yerine kartın kayıtlı olduğu müşteri anahtarını (cardUserKey) ve kayıtlı kart referansını (cardToken) koyun:

{
  "paymentMethod": "CARD",
  "amount": 10050,
  "currency": "TRY",
  "orderId": "ORD-84723",
  "card": {
    "cardUserKey": "cust_7788",
    "cardToken": "9f3c1a7e-…",
    "cvcNumber": "123"
  }
}
  • Kart kaydı yalnız 3D Secure ile yapılır. 2D istekte card.cardSave: true gönderirseniz istek 400 payment.card.save_requires_3ds ile reddedilir; kartı Kart — 3D Secure ile kaydedin.
  • cardToken, kart kaydedildiğinde size dönen storedCardToken değeridir. Checkout Formu'nun tek kullanımlık kart token'ı burada kullanılamaz.
  • Kart saklamanın açılması, token'ın alınması ve kartların listelenmesi için bkz. Kart Saklama.

Taksit

Alıcı bir taksit seçeneği seçtiyse installment ile birlikte taksit quote'undan aldığınız installmentQuoteToken'ı gönderin.

  • installment 2 ve üzeriyse installmentQuoteToken zorunludur.
  • amount sepet toplamı olarak kalır; vade farkını siz göndermezsiniz. Sistem vade farkını bağlayıcı quote'tan hesaplar ve çekilen tutara ekler: çekilen tutar = amount + vade farkı. Gösterdiğiniz tutar neyse çekilen tutar odur.
  • Sorgudaki ve webhook'taki tutar alanları bu çekilen tutarı gösterir.
  • Token yoksa, süresi dolmuşsa ya da istekle uyuşmuyorsa ödeme FAILED olur ve yanıt 400 INSTALLMENT_QUOTE_REJECTED döner. Yeni bir quote alıp yeni bir Idempotency-Key ile tekrar gönderin.

Ön provizyon

Tutarı çekmeden önce bloke etmek için istekte "preauth": true gönderin. Ödeme başarılı olursa data.status CAPTURED yerine AUTHORIZED olur ve payment.authorized gönderilir. Tutarı daha sonra capture ile çeker ya da void ile blokeyi kaldırırsınız.

  • Ön provizyonu desteklemeyen sağlayıcılar adaylardan çıkarılır. Uygun sağlayıcı kalmazsa ödeme FAILED olur ve ret kodu PREAUTH_NOT_SUPPORTED'dır. Talimat hiçbir koşulda anında çekime dönüştürülmez.
  • Capture, kısmi capture, void, süre dolumu ve hatalar: Ön Provizyon, Capture & İptal.

Idempotency

Idempotency-Key zorunludur (en fazla 200 karakter). Yoksa istek işlenmeden 400 payment.operation.idempotency_key_required alır. Ödemeyi değil denemeyi tanımlayan bir değer kullanın (örneğin ORD-84722-1).

DurumSonuç
Aynı anahtar, aynı istekİlk denemenin sonucu döner; ikinci çekim yapılmaz
Aynı anahtar, farklı istek (ör. farklı tutar)409 payment.idempotency.conflict
Aynı anahtarla ilk istek hâlâ işleniyor429 payment.idempotency.processing; kısa bir süre sonra aynı anahtarla tekrar deneyin
⚠️

Reddedilen bir siparişi başka bir kartla yeniden denemek için yeni bir Idempotency-Key gönderin. Aynı anahtarı kullanırsanız önceki denemenin sonucu döner ve yeni kart denenmez.

Hatalar

DurumYanıtNe yapmalı
Eksik, hatalı ya da tanımsız alan400 VALIDATION_ERRORdetails içindeki alanı düzeltin
Kaldırılan bir tutar alanı gönderildi400 payment.amount.field_removedTutarı yalnız amount ile gönderin
Sepet toplamı amount'a eşit değil400 VALIDATION_ERRORKalemlerin price toplamını amount'a eşitleyin
Idempotency-Key yok400 payment.operation.idempotency_key_requiredHer deneme için bir anahtar gönderin
2D istekte kart kaydı400 payment.card.save_requires_3dsKartı Kart — 3D Secure ile kaydedin
Bearer token yok ya da süresi dolmuş401 UNAUTHENTICATEDYeni token alın
İmza doğrulanamadı401 INVALID_SIGNATUREKanonik dizgiyi Kimlik Doğrulama'daki sırayla kurun
Nonce daha önce kullanıldı401 NONCE_REPLAYHer istek için yeni X-Nonce üretin
X-Date ya da Digest hatalı401 INVALID_DATE, DIGEST_MISSING, INVALID_DIGESTBkz. Hata Yönetimi
Token ile imza anahtarı farklı merchant'a ait403 AUTH_MERCHANT_MISMATCHAynı hesabın anahtarlarını kullanın
IP izinli listede değil403 IP_NOT_ALLOWEDPanelden IP listesini güncelleyin
Hesap askıda403 MERCHANT_SUSPENDEDDestekle iletişime geçin
Ürün açık değil403 PRODUCT_NOT_ENABLEDPayment Gateway ürününün hesabınızda ve API anahtarınızda açık olduğunu doğrulayın
Ürün yetkisi o an doğrulanamadı503 PRODUCT_ENTITLEMENT_UNAVAILABLEGeçicidir; kısa süre sonra tekrar deneyin
Taksit quote'u geçersiz ya da eksik400 INSTALLMENT_QUOTE_REJECTED, ödeme FAILEDYeni quote alıp yeni Idempotency-Key ile gönderin
Ön provizyonu destekleyen sağlayıcı yokÖdeme FAILED, ret kodu PREAUTH_NOT_SUPPORTEDPara bloke edilmedi; bkz. Ön Provizyon
Limit kuralı reddetti400 payment.limit.exceeded, ödeme FAILEDLimitlerinizi kontrol edin
Risk değerlendirmesi reddetti400 RISK_BLOCKED, ödeme FAILEDÖdemeyi teslim etmeyin
Sağlayıcı 2D yapamıyorÖdeme FAILED, ret kodu NO_2D_CAPABLE_PROVIDERKalıcı red; ödemeyi 3D Secure ile alın
Banka reddi (yetersiz bakiye, geçersiz kart …)400, ödeme FAILEDReddi gösterin; başka kart için yeni Idempotency-Key kullanın
Risk ya da limit kuralı 3D istedi202 AWAITING_3D, REDIRECT aksiyonuBkz. 2D isteği ne zaman 3D'ye döner
Sonuç kesinleşmedi202 PAYMENT_PENDING_RECONCILIATIONYeni çekim açmayın; webhook'u bekleyin
Aynı anahtar, farklı istek409 payment.idempotency.conflictYeni deneme için yeni anahtar kullanın
Aynı anahtarla istek sürüyor429 payment.idempotency.processingKısa süre sonra aynı anahtarla tekrar deneyin
Geçici kesinti503GET /payments/:id ile durumu kontrol edin; aynı Idempotency-Key ile tekrar denemek çift çekim yapmaz

Yöntem ve sağlayıcı seçimine ait ortak kodlar: Payment — Hata kodları.

Webhook'lar

EventNe zaman
payment.capturedÇekim tamamlandı, para çekildi. Siparişi bunun üzerine teslim edin
payment.failedÇekim başarısız oldu, para çekilmedi
payment.authorizedÖn provizyonda tutar bloke edildi (AUTHORIZED); para henüz çekilmedi. Bkz. Ön Provizyon

Olayların data'sında paymentMethod: "CARD" ve ödemeyi yürüten sağlayıcının providerCode'u bulunur. Teslimat ve imza doğrulama için bkz. Webhook'lar.

Sonraki adımlar