Payment Orchestrator
Payment

Payment — Tek Uçtan Ödeme

POST /payments/direct/payment, hesabınızda açık olan her ödeme yöntemiyle sunucunuzdan ödeme başlatır: kart, cüzdan, Faturana Yansıt ve Senetle Öde aynı uçtan, aynı sipariş alanlarıyla gelir. Yöntemi paymentMethod alanı seçer; yönteme özgü bilgiler o yöntemin blokunda gönderilir. Alıcının bir şey yapması gerekiyorsa (doğrulama kodu girmek, banka sayfasına gitmek) yanıt bir action taşır. Kesin sonuç her zaman webhook ile de bildirilir.

Bu sayfa, ödemeyi kendi sunucunuzdan başlattığınız Direct API yolu içindir. Ödemeyi Checkout Formu ile alıyorsanız yöntem çağrılarını form yapar → Checkout Formu — Payment. Kart ödemesinin 2D ve 3D Secure kuralları Kart sayfalarındadır.

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

Nasıl çalışır

Açık yöntemleri okuyun

GET /payments/methods hesabınızda açık yöntemleri, her yöntemin sağlayıcılarını, sağlayıcıyı kimin seçtiğini (providerSelectionMode) ve sağlayıcının alıcıdan istediği alanları (inputFields) döner.

Ödemeyi başlatın

POST /payments/direct/payment çağırın: paymentMethod, sipariş alanları ve yalnız o yöntemin bloğu. İstek Step-Up kimlik doğrulaması ve Idempotency-Key taşır.

Aksiyonu tamamlayın

Yanıtta action varsa alıcıdan bekleneni yapın: OTP'de kodu confirm ile gönderin, REDIRECT'te alıcıyı action.redirect.url adresine yönlendirin. action yoksa sonuç yanıttadır ya da sağlayıcıdan beklenir.

Webhook ile teyit edin

Kesin sonuç payment.captured, payment.authorized ya da payment.failed olarak webhook adresinize gelir. Siparişi payment.captured ile teslim edin.

Yöntemler

YöntempaymentMethodBlokAlıcı ne yaparSayfa
KartCARDcard3D Secure'da banka sayfasında doğrulanır (REDIRECT)Kart
CüzdanWALLETwalletTelefonuna gelen kodu girer (OTP)Cüzdanla Öde
Faturana YansıtMOBILE_BILLINGmobileBillingTelefonuna gelen kodu girer ve sözleşmeyi onaylar (OTP)Faturana Yansıt
Senetle ÖdePROMISSORY_NOTEpromissoryNoteBorçlu bilgilerini verir; senetler anında düzenlenir (aksiyon yok)Senetle Öde
  • Bu uçtan bugün yukarıdaki yöntemler başlatılabilir. Payment menüsündeki diğer yöntemler çok yakında eklenecek.
  • Bu uç tek yöntemlidir. Bir siparişi birden fazla karta ve yönteme bölmek için Parçalı Ödeme ucunu kullanın.
  • Hesabınızda kullanabileceğiniz yöntemler ve sağlayıcılar GET /payments/methods yanıtındadır.
  • Tanınmayan yöntem kodu 400 payment.method.unknown, bu uçta kullanılamayan yöntem 400 payment.method.not_supported alır. İstek hiçbir koşulda başka bir yönteme ya da karta çevrilmez.

Kimlik doğrulama

POST /payments/direct/payment ve GET /payments/methods Step-Up ister: Authorization: Bearer at_… token'ınız ve isteğin Ed25519 imzası.

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
DigestGövdeli isteklerde ham JSON gövdesinin SHA-256=<base64> özeti
X-SignatureKanonik dizgi üzerinde Base64 Ed25519 imzası
Idempotency-KeyPOST /payments/direct/payment'ta zorunlu, en fazla 200 karakter; bkz. Idempotency

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

Açık yöntemleri listeleme

GET /payments/methods hesabınızda açık yöntemleri, her yöntemin sağlayıcılarını, sağlayıcıyı kimin seçtiğini (providerSelectionMode) ve alıcıdan istenen alanları (inputFields) döner; ?paymentMethod= ile tek bir yöntemin satırını okursunuz. Yöntemler ve sağlayıcılar Form Ayarları'ndaki sıranızla gelir. Uç, yanıt alanları, sıra ve sağlayıcı seçim kuralları: Yöntemleri Listeleme.

Yöntem alanları (inputFields)

Bloktaki alanları sağlayıcının inputFields tanımı belirler; değerleri tanımdaki key adıyla gönderirsiniz. Tanımın alanları ve değer tipleri: Yöntemleri Listeleme › Yöntem alanları.

"mobileBilling": { "providerCode": "<providerCode>", "gsmNumber": "+905321234567" }
  • Tanımda olmayan bir anahtar, eksik zorunlu alan ya da tipe uymayan değer 400 payment.method.block_invalid alır. Sorunlu alan details.field (ör. mobileBilling.gsmNumber) ve details.reason içindedir; bütün ihlaller details.errors[] listesindedir. Gönderdiğiniz değer hata yanıtında yer almaz.
  • İç içe alanlarda yol alanın yerini gösterir: promissoryNote.address.districtCode, promissoryNote.guarantors[1].identityNumber.
  • details.reason değerleri: unknown_field, required, not_applicable (requiredWhen koşulu tutmuyorken gönderilen alan), invalid_type, invalid_format, too_short, too_long, invalid_option, too_few_items, too_many_items (GROUP öğe sayısı). Yöntemin kendine özgü sebepleri yöntem sayfasındadır; örneğin Senetle Öde.
  • Değerler yalnız sağlayıcıya iletilir; ödeme kaydında saklanmaz.

Adres sözlüğü

ADDRESS alanının il, ilçe ve mahalle kodları Lunixi adres sözlüğündendir. Sözlük uçları herkese açıktır: kimlik doğrulaması istemez ve kişisel veri döndürmez. Yanıtlar bir gün önbelleğe alınabilir.

UçSorguDöner
GET /api/v1/reference/tr-address/provinces—İller: code "01"–"81"
GET /api/v1/reference/tr-address/districtsprovinceCode (zorunlu, "01"–"81")İlin ilçeleri
GET /api/v1/reference/tr-address/neighborhoodsdistrictCode (zorunlu, rakamlar)İlçenin mahalleleri
GET https://api-gateway.lunixi.com/api/v1/reference/tr-address/districts?provinceCode=06
{
  "status": "success",
  "code": "SUCCESS",
  "message": "…",
  "data": {
    "items": [
      { "code": "<districtCode>", "name": "<ilçe adı>" }
    ]
  },
  "statusCode": 200,
  "requestId": "…"
}
  • Kodları sözlükten okuyun ve alıcıya adlarıyla seçtirin; kodu elle üretmeyin. Mahalle, ilçe ve il birbirine bağlı değilse istek 400 payment.method.block_invalid alır (….address.neighborhoodCode, invalid_option).
  • Geçersiz provinceCode ya da districtCode sorgusu 400 alır. Sözlükte kaydı olmayan bir il ya da ilçe için liste boş döner.

İstek

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

Alanlar

AlanTipZorunluAçıklama
paymentMethodstringEvetYöntem kodu: CARD, WALLET, MOBILE_BILLING, PROMISSORY_NOTE
cardobjectCARD'daKart bilgisi; bkz. card
walletobjectWALLET'taCüzdan bloğu; bkz. Cüzdanla Öde
mobileBillingobjectMOBILE_BILLING'deFaturana Yansıt bloğu; bkz. Faturana Yansıt
promissoryNoteobjectPROMISSORY_NOTE'taSenet bloğu: vade planı ya da senet sayısı ve borçlu alanları; bkz. Senetle Öde
force3DbooleanHayırYalnız CARD ile. true: 3D Secure; verilmezse ya da false ise 2D. Bkz. Kart
installmentintegerHayırYalnız CARD ile; taksit sayısı, varsayılan 1
installmentQuoteTokenstringHayırYalnız CARD ile; taksit quote'unun bağlayıcı token'ı
preauthbooleanHayırtrue: ön provizyon, ödeme AUTHORIZED olur. Bkz. Ön provizyon
callbackUrlstringHayırhttp ya da https, en fazla 2048 karakter. Alıcı tarayıcısının sonuçla döneceği adres (REDIRECT aksiyonu; ör. kart 3D Secure)

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, yöntem alanlarının prefill kaynağıdır: cüzdan ve Faturana Yansıt bloğunda telefon gönderilmezse kullanılır. metadata ödeme kararlarında okunmaz: örneğin metadata içine yazılan bir yöntem ya da ön provizyon değeri ödemeyi değiştirmez.

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.

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.

Kurallar

  • Tutar yalnız amount ile gönderilir; kaldırılan tutar alanları 400 payment.amount.field_removed alır. basketItems gönderilirse kalemlerin price toplamı amount'a eşit olmalıdır; eşit değilse istek 400 VALIDATION_ERROR alır.
  • Kartta taksit seçildiyse (installment + installmentQuoteToken) vade farkını sistem quote'tan hesaplar ve çekilen tutara ekler: çekilen tutar = amount + vade farkı. Sorgu ve webhook'taki tutar alanları bu çekilen tutarı gösterir.
  • Gövdede yalnız paymentMethod'a karşılık gelen blok bulunur. Başka bir yöntemin bloğu ya da kart dışı yöntemle card, force3D, installment, installmentQuoteToken gönderilirse istek 400 VALIDATION_ERROR alır.
  • Yöntemin bloğu zorunludur. Bloktaki alanlar sağlayıcının inputFields tanımıdır; providerCode dışında tanımda olmayan alan gönderilemez.
  • providerCode: yöntem için tek sağlayıcı bağlıysa gönderilmesi gerekmez. Birden fazla sağlayıcı bağlıysa kuralı yöntemin providerSelectionMode değeri belirler:
    • BUYER (ör. cüzdan): zorunludur; göndermezseniz 400 payment.provider.required döner ve bağlı kodlar details.boundProviderCodes içindedir.
    • PLATFORM (ör. Faturana Yansıt): isteğe bağlıdır. Göndermezseniz platform bağlı sağlayıcılardan birini para çekilmeden önce seçer; hiçbiri bu ödemeyi karşılamıyorsa 422 payment.provider.none_eligible döner.
  • Seçilen sağlayıcı sabitlenir: hata olursa başka sağlayıcıya, başka yönteme ya da karta geçilmez.
  • Form Ayarları'nda yalnız formda kapattığınız sağlayıcı bu uçta kabul edilir; kapatma yalnız Checkout Formu'nu etkiler. Sağlayıcıyı her yerde kapatmak için sağlayıcı bağlantısını kapatın.
  • Tanımlı olmayan bir alan (method, basketId, paymentSource …) 400 VALIDATION_ERROR alır.

Ö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" }
  }'

Yönteme özgü örnekler: Kart — 2D, Kart — 3D Secure, Cüzdanla Öde, Faturana Yansıt, Senetle Öde.

Yanıt

Yanıt ortak zarfla döner; ödemenin kendisi data içindedir. Ödeme başlatma, confirm ve resend aynı biçimi kullanır.

{
  "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": "…"
}
HTTPZarf statusAnlamı
200successÖdeme kesinleşti: data.status CAPTURED ya da (ön provizyonda) AUTHORIZED
202partialÖdeme sürüyor: action alıcıdan bekleneni anlatır ya da sonuç sağlayıcıdan doğrulanıyor (PAYMENT_PENDING_RECONCILIATION)
400failureÖdeme reddedildi: data.status FAILED; code ret sebebini taşır

Ret yanıtında details.retryability (RETRYABLE, NON_RETRYABLE, UNKNOWN) aynı isteği yeniden denemenin anlamlı olup olmadığını söyler. İstek hiç işlenmeden reddedildiyse (doğrulama, kimlik, yöntem ya da sağlayıcı hatası) data boştur ve code hatayı anlatır; bkz. Hatalar.

data alanları

AlanTipAçıklama
paymentIdstringÖdeme kimliği; confirm, resend, capture ve sorgu çağrılarında kullanılır
orderIdstringSizin sipariş numaranız
statusstringÖdemenin durumu; bkz. aşağıdaki tablo
paymentMethodstringYöntem kodu
providerCodestringÖdemeyi yürüten sağlayıcının kodu; henüz belli değilse yer almaz
actionobjectAlıcıdan beklenen etkileşim; yalnız açık aksiyon varken bulunur. Bkz. Aksiyonlar
savedCardobjectYalnız kartta, bu ödemede yeni kaydedilen kart; bkz. Kart — 3D Secure
data.statusNe zaman
INITIATEDİşletmenin cüzdan programıyla ödemede kod onayı bekleniyor; bkz. Cüzdanla Öde
PROCESSINGSağlayıcı alıcının işlemini bekliyor (ör. kod)
AWAITING_3DKartta 3D Secure doğrulaması bekleniyor
AUTHORIZEDÖn provizyon: tutar bloke edildi
CAPTUREDPara çekildi
FAILEDÖdeme reddedildi; para çekilmedi
NEEDS_RECONCILIATIONSonuç sağlayıcıyla doğrulanıyor; kesin sonuç webhook ile gelir
⚠️

202 yanıtında ya da NEEDS_RECONCILIATION durumunda yeni bir ödeme başlatmayın. Sonuç kesinleşince payment.captured ya da payment.failed gönderilir; durumu GET /payments/:id ile de okuyabilirsiniz.

Aksiyonlar

action, alıcının bir şey yapması gerektiğini anlatır. Bir ödemede aynı anda tek açık aksiyon bulunur. Bir yöntemin döndürebileceği tipler GET /payments/methods yanıtındaki actionTypes alanındadır.

TipAlıcı ne yaparSiz ne yaparsınız
OTPTelefonuna gelen kodu girer; consent.required ise sözleşmeyi onaylarKodu ve onayı confirm ile gönderin. Kodu yeniden göndermek için resend
REDIRECTSağlayıcının ya da bankanın sayfasına gider ve dönerAlıcıyı action.redirect.url adresine yönlendirin. Confirm gerekmez; sonuç callbackUrl adresinize ve webhook'a gelir
INPUTSağlayıcının ek istediği bilgileri girer (action.input.fields)Değerleri confirm gövdesinde fields ile gönderin

Tanımadığınız bir tip gelirse ödemeyi ödenmiş saymayın; sonucu webhook ile bekleyin.

AlanTipAçıklama
idstringAksiyon kimliği; confirm ve resend yolunda kullanılır
typestringOTP, REDIRECT, INPUT
expiresAtstringAksiyonun son geçerlilik zamanı (ISO 8601)
otp.maskedTargetstringKodun gönderildiği numaranın maskeli hâli. Örnek: 53****67
consent.requiredbooleantrue ise kod sözleşme onayıyla birlikte gönderilmelidir
consent.urlstringAlıcıya gösterilecek sözleşmenin adresi
input.fieldsarrayINPUT aksiyonunda istenen alanlar; biçimi inputFields ile aynı
chargeobjectOnaydan önce alıcıya gösterilecek tutar kırılımı (minor unit): amount, feeTotal, taxTotal, buyerTotalCharge, currency. buyerTotalCharge = amount + feeTotal + taxTotal
maskedBusinessNamestringÖdemenin gideceği işletmenin maskeli adı
stepUpRequiredbooleanYalnız true iken bulunur: sağlayıcı güçlü doğrulama istedi. Ek girdi beklenmez
redirect.urlstringREDIRECT aksiyonunda alıcının gideceği adres

Sağlayıcıya ait oturum bilgileri, referanslar ve doğrulama kodu hiçbir yanıtta, sorguda ya da webhook'ta yer almaz.

Aksiyonu onaylama — confirm

POST https://api-gateway.lunixi.com/api/v1/payments/{paymentId}/actions/{actionId}/confirm

Açık aksiyonu sonuçlandırır; yeni bir çekim başlatmaz. Sunucunuzdan çağırırken Kimlik Doğrulama sayfasındaki imza başlıklarını (X-Key-Id, X-Date, X-Nonce, Digest, X-Signature) gönderin; gövdeye token koymayın. Ödeme hesabınıza ait değilse ya da aksiyon bulunamazsa 404 payment.action.not_found döner.

AlanTipAçıklama
otpstringAlıcının girdiği kod; yalnız rakam, en fazla 16 karakter
consentAcceptedbooleanSözleşme onayı. action.consent.required true ise true gönderilmelidir
fieldsobjectINPUT aksiyonunda istenen alanlar. OTP aksiyonunda kod { "otp": "123456" } olarak da gönderilebilir
{ "otp": "123456", "consentAccepted": true }

Yanıt ödeme yanıtıyla aynı biçimdedir:

SonuçHTTPcodeNe yapmalı
Ödeme tamamlandı200PAYMENT_CAPTURED ya da PAYMENT_AUTHORIZEDSiparişi payment.captured ile teslim edin
Kod reddedildi, hak var422payment.action.input_rejectedAksiyon açık kalır; kalan hak details.attemptsRemaining içindedir. Alıcı kodu yeniden girer
Hak bitti400payment.action.attempts_exhaustedÖdeme FAILED olur
Sağlayıcı reddetti400Ret koduÖdeme FAILED olur
Sonuç doğrulanıyor202PAYMENT_PENDING_RECONCILIATIONYeni ödeme açmayın; webhook'u bekleyin
  • Aynı confirm'ü tekrar gönderirseniz ikinci kez sağlayıcıya gidilmez; kaydedilmiş sonuç döner. Bağlantınız koptuysa aynı isteği güvenle tekrarlayabilirsiniz.
  • Deneme hakkı aksiyon başınadır; sağlayıcı aksi belirtmedikçe 3'tür.
  • Aksiyonun süresi (expiresAt) dolarsa aksiyon kapanır. Sağlayıcının gönderdiği doğrulama kodunda ödeme FAILED olur ve payment.failed gönderilir; işletmenin cüzdan programındaki davranış için bkz. Cüzdanla Öde.
  • Kod ya da onay eksikse istek deneme hakkı yakmadan reddedilir: payment.action.otp_required, payment.action.consent_required.

Kodu yeniden gönderme — resend

POST https://api-gateway.lunixi.com/api/v1/payments/{paymentId}/actions/{actionId}/resend

Sağlayıcı destekliyorsa yeni bir kod gönderir. Eski aksiyon kapanır, yanıt (202) yeni action'ı taşır; confirm'de yeni action.id'yi kullanın. Gövde boştur ({}); kimlik doğrulama confirm ile aynıdır.

Ön provizyon

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

Capture, void, süre dolumu ve hatalar: Ön Provizyon, Capture & İptal.

Idempotency

Idempotency-Key bu uçta 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 ORDER-1002-1).

DurumSonuç
Aynı anahtar, aynı istekİlk denemenin sonucu döner; ikinci ödeme başlatılmaz. Açık aksiyon varsa yanıtta yine yer alır
Aynı anahtar, farklı istek409 payment.idempotency.conflict
Aynı anahtarla ilk istek hâlâ işleniyor429 payment.idempotency.processing; kısa süre sonra aynı anahtarla tekrar deneyin

Reddedilen bir siparişi yeniden denemek için yeni bir Idempotency-Key gönderin.

Sonuç ve webhook'lar

EventNe zaman
payment.capturedPara çekildi. Siparişi bunun üzerine teslim edin
payment.authorizedÖn provizyonda tutar bloke edildi; para henüz çekilmedi
payment.failedÖdeme başarısız oldu; para çekilmedi (sağlayıcı kodunun süresinin dolması ya da hakkın bitmesi dahil)

Ödeme olaylarının data nesnesi paymentMethod ve providerCode alanlarını taşır:

{
  "id": "2f6c1b9e-…",
  "type": "payment.captured",
  "data": {
    "intentId": "7b0e4c2a-1f3d-4e5b-8a6c-9d0e1f2a3b4c",
    "merchantId": "m_…",
    "orderId": "ORDER-1002",
    "currency": "TRY",
    "status": "CAPTURED",
    "paymentMethod": "MOBILE_BILLING",
    "providerCode": "<providerCode>",
    "capturedAmountMinor": "5000"
  }
}
AlanAçıklama
data.paymentMethodYöntem kodu (CARD, WALLET, MOBILE_BILLING, PROMISSORY_NOTE …)
data.providerCodeÖdemeyi yürüten sağlayıcının kodu; ödemenin henüz sağlayıcısı yoksa yer almaz

Ödemeyi GET /payments/:id ile sorguladığınızda yanıt paymentMethod alanını ve açık bir aksiyon varsa action alanını da taşır. Teslimat, imza doğrulama ve diğer alanlar için bkz. Webhook'lar.

Hatalar

Hata yanıtları ortak hata zarfını kullanır; message'a göre değil code'a göre dallanın → Hata Yönetimi.

DurumYanıtNe yapmalı
Eksik, hatalı ya da tanımsız alan; yanlış blok400 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
Yöntem tanınmıyor ya da bu uçta kullanılamıyor400 payment.method.unknown, payment.method.not_supportedGET /payments/methods listesindeki bir yöntemi kullanın
Bloktaki alanlar sağlayıcının tanımına uymuyor400 payment.method.block_invaliddetails.field alanını düzeltin
Yöntem panelde (form ayarlarında) kapalı422 payment.method.disabledYöntemi panelde açın; açık yöntemleri GET /payments/methods ile okuyun
BUYER yönteminde birden fazla sağlayıcı bağlı, seçim yok400 payment.provider.required<blok>.providerCode gönderin
PLATFORM yönteminde bağlı sağlayıcıların hiçbiri ödemeyi karşılamıyor422 payment.provider.none_eligibledetails.candidates içindeki sonuçlara bakın; daha sonra tekrar deneyin ya da providerCode ile sağlayıcı seçin
Seçilen sağlayıcı kullanılamıyor422 payment.provider.not_availableListedeki bir sağlayıcıyı seçin
Yöntem ön provizyonu desteklemiyor422 payment.preauth.unsupported_for_methodpreauth olmadan gönderin
Kimlik, imza ya da ürün yetkisi hatası401, 403, 503Bkz. Kart — 2D › Hatalar
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
Sağlayıcı ya da risk reddi400, ödeme FAILEDReddi gösterin; yeni deneme için yeni anahtar kullanın
Sonuç kesinleşmedi202 PAYMENT_PENDING_RECONCILIATIONYeni ödeme açmayın; webhook'u bekleyin

Yönteme özgü hatalar yöntem sayfalarındadır.

Hata kodları

Aşağıdaki kodlar ödeme yöntemi, sağlayıcı seçimi ve aksiyon uçlarına özgüdür.

KodHTTPAnlamı ve ne yapmalı
payment.method.unknown400paymentMethod tanınmıyor. Geçerli bir yöntem kodu gönderin
payment.method.not_supported400Yöntem kodu tanınıyor ama bu işlemde kullanılamıyor. GET /payments/methods listesindeki yöntemleri kullanın
payment.method.block_invalid400Yöntem bloğu sağlayıcının inputFields tanımına uymuyor. Sorunlu alan details.field, sebep details.reason, bütün ihlaller details.errors[] içindedir
payment.method.disabled422Yöntem işletmenin form ayarlarında kapalı. Panelde kapatılan yöntem formda, listede ve bu uçta kapalıdır; ödeme başlamadan reddedilir
payment.method.wallet_bridge_not_available422Seçilen cüzdanın doğrulama akışı bu uçta desteklenmiyor; bu uç cüzdan onayını tek seferlik kodla alır
payment.method.customer_identity_conflict400Cüzdanla ödemede alıcı customerId alanıyla tanımlanır. metadata.customerId bu alan olmadan gönderilemez ve ondan farklı olamaz
payment.provider.required400Bu yöntemde sağlayıcıyı alıcı seçer (BUYER) ve birden fazla sağlayıcı bağlı. <blok>.providerCode ile seçin; bağlı kodlar details.boundProviderCodes içindedir. Ayrıntı: Hata Yönetimi
payment.provider.none_eligible422PLATFORM yönteminde providerCode gönderilmedi ve bağlı sağlayıcıların hiçbiri bu ödemeyi karşılamıyor; ödeme başlatılmadı, tutar çekilmedi. Ayrıntı: Hata Yönetimi
payment.provider.not_available422Seçilen sağlayıcı bu yöntem için kullanılamıyor. Ödeme başka sağlayıcıya yönlendirilmez
payment.provider.pin_violation500Ödeme şu anda tamamlanamıyor; para çekilmedi. Daha sonra tekrar deneyin
payment.operation.idempotency_key_required400Idempotency-Key başlığı bu uçta zorunlu
payment.action.not_found404Ödeme ya da aksiyon bulunamadı (başka hesaba ait ödeme dahil). paymentId ve action.id değerlerini kontrol edin
payment.action.replaced409Aksiyonun yerine resend ile yenisi açıldı. details.replacedByActionId aksiyonuyla ve son gönderilen kodla devam edin
payment.action.expired409Aksiyonun süresi doldu. Yeni bir ödeme başlatın
payment.action.in_progress409Aynı aksiyon için başka bir istek işleniyor. Birkaç saniye sonra aynı isteği tekrarlayın; kaydedilmiş sonuç döner
payment.action.closed409Aksiyon kapanmış; üzerinde işlem yapılamaz
payment.action.payment_not_pending409Ödeme artık bu adımı beklemiyor. Durumu GET /payments/:id ile okuyun
payment.action.otp_required400Kod gönderilmedi ya da biçimi geçersiz (yalnız rakam). Deneme hakkı düşmez
payment.action.consent_required422Sözleşme onayı gerekli: consentAccepted: true gönderin. Deneme hakkı düşmez
payment.action.input_invalid400fields, action.input.fields tanımına uymuyor; sorunlu alan details.field içindedir. Deneme hakkı düşmez
payment.action.input_rejected422Sağlayıcı kodu reddetti. Aksiyon açık kalır; kalan hak details.attemptsRemaining içindedir. Bu bir ödeme yanıtıdır: data ödemeyi ve açık action'ı taşır
payment.action.attempts_exhausted400Deneme hakkı bitti; ödeme FAILED oldu. Bu bir ödeme yanıtıdır
payment.action.confirm_not_applicable409Bu aksiyon confirm ile tamamlanmaz; alıcı action.redirect.url adresine gider, sonuç dönüşte doğrulanır ve webhook ile bildirilir
payment.action.resend_not_supported422Bu yöntemde kod yeniden gönderilemez
payment.action.resend_too_soon429Önceki gönderimin üzerinden yeterli süre geçmedi. details.retryAfterSeconds saniye bekleyin
payment.action.resend_limit_reached422Bu ödeme için yeniden gönderme hakkı doldu. Mevcut kodla devam edin ya da yeni ödeme başlatın
payment.action.resend_failed502Yeni kod şu anda gönderilemedi; mevcut aksiyon açık ve kod geçerli olabilir. Tekrar deneyin
payment.action.auth_ambiguous400İstek hem API imzası hem checkout token'ı taşıyor. Sunucunuzdan yalnız imzayla çağırın

Sonraki adımlar