Payment Orchestrator
Taksit & BIN

Taksit & BIN

Alıcı kartının ilk hanelerini yazar yazmaz kartı tanıyabilir (marka, kart ailesi, banka) ve ödeme gönderilmeden önce — vade farkı dahil — gerçek bir taksit tablosu gösterebilirsiniz. Modelin merkezinde quote binding vardır: bilinen bir BIN için belirli bir taksit seçeneği istediğinizde yanıt bir quoteToken taşır ve ödeme, o quote'un gösterdiği tutarları birebir çeker. Alıcının gördüğü ile kartından çekilen arasında sapma olmaz.

Tüm tutarlar minor-unit (kuruş) değerdir: istekteki amount integer'dır, quote fiyatları ise minor-unit string döner — "totalPrice": "10500" = ₺105,00. Asla ondalık veya float göndermeyin.

Nasıl çalışır

Kartı tanıyın

6–8 hane hazır olduğunda BIN info çağırarak marka, aile ve bankayı — ve kartın taksite uygun olup olmadığını — öğrenin.

Taksit tablosunu alın

Tutarla (BIN biliniyorsa BIN ile) birlikte BIN installments çağırın. Mevcut seçenekleri (1×, 3×, 6×…) ve her birinin aylık/toplam tutarlarını alırsınız.

Tabloyu gösterin

Seçenekleri döndüğü gibi render edin. Toplamlar vade farkını zaten içerir — asla client tarafında yeniden hesaplamayın.

Seçilen seçeneği bağlayın

Alıcı 1×'ten büyük bir seçenek seçtiğinde BIN installments'ı bu kez binOrPan ve seçilen installment ile çağırın — yanıt artık binding: true ve imzalı bir quoteToken taşır. Bunu ödeme isteğinde (Kart — 2D veya Kart — 3D Secure) installmentQuoteToken olarak geçirin. Platform quote'lanan tutarları çeker — gösterilen == çekilen.

Sunucu tarafı endpointler (Bearer)

Bunlar backend'inizde at_live_… erişim token'ınızla çalışır.

POST /bin/info — kart sorgusu

İlk 6 veya 8 haneyi gönderin. Yanlışlıkla daha uzun bir PAN gönderirseniz yalnızca prefix kullanılır ve numara saklanmaz.

curl https://api-gateway.lunixi.com/api/v1/bin/info \
  -H "Authorization: Bearer at_live_5f3e2b1a..." \
  -H "Content-Type: application/json" \
  -d '{ "binOrPan": "54000000" }'
{
  "status": "success",
  "code": "BIN_FOUND",
  "data": {
    "found": true,
    "binNumber": "54000000",
    "bankName": "Example Bank",
    "bankCode": "0001",
    "cardBrand": "MASTERCARD",
    "cardFamily": "World",
    "cardProgram": "",
    "cardType": "CREDIT",
    "cardLevel": "CLASSIC",
    "force3d": false,
    "isCommercial": false,
    "supportedInstallment": true,
    "enabledInstallments": [2, 3, 6, 9]
  }
}

Bilinmeyen BIN çağrıyı düşürmez: code: "BIN_PATTERN_FALLBACK" ve found: false ile marka-deseninden türetilmiş alanlar döner; form asla kırılmaz.

GET /bin/card-taxonomy — referans listeleri

Platformun tanıdığı marka, kart ailesi ve banka listelerini canlı olarak döndürür. Dropdown'lar kurmak, BIN sonuçlarını kendi görünen adlarınıza eşlemek veya konfigürasyon doğrulamak için kullanın — bayatlayan sabit listeler yerine.

curl https://api-gateway.lunixi.com/api/v1/bin/card-taxonomy \
  -H "Authorization: Bearer at_live_5f3e2b1a..."

POST /bin/installments — taksit tablosu & bağlayıcı quote

Tutarı (veya intentId) gönderin; BIN opsiyoneldir. Tek endpoint, iki mod:

  • Gösterge tablo — amount (+ opsiyonel binOrPan): sunulan seçenekler binding: false ile döner, quoteToken yoktur.
  • Bağlayıcı quote — binOrPan ve tekil installment > 1: binding: true, imzalı quoteToken ve expiresAt döner.

format parametresi sonucun biçimini belirler:

formatDöndürdüğü
data (varsayılan)Ham JSON seçenekler — UI'ı siz render edersiniz
htmlGömülmeye hazır HTML taksit tablosu ekler (html alanı)
mobileNative mobil render için biçimlendirilmiş payload
curl https://api-gateway.lunixi.com/api/v1/bin/installments \
  -H "Authorization: Bearer at_live_5f3e2b1a..." \
  -H "Content-Type: application/json" \
  -d '{
    "binOrPan": "54000000",
    "amount": 10050,
    "installment": 3,
    "format": "data"
  }'
{
  "status": "success",
  "code": "INSTALLMENT_QUOTE_ISSUED",
  "data": {
    "binding": true,
    "quoteToken": "iq_5b8d03aa…",
    "expiresAt": "2026-07-06T12:20:00Z",
    "methods": {
      "CARD": {
        "installmentDetails": [
          {
            "cardFamily": "World",
            "bankName": "Example Bank",
            "installmentPrices": [
              { "installment": 1, "totalPrice": "10050", "monthlyPrice": "10050", "offered": true, "markupPct": null },
              { "installment": 3, "totalPrice": "10500", "monthlyPrice": "3500",  "offered": true, "markupPct": "4.48" },
              { "installment": 6, "totalPrice": null,    "monthlyPrice": null,    "offered": false, "markupPct": null }
            ]
          }
        ]
      }
    }
  }
}

totalPrice / monthlyPrice, string olarak minor-unit tutarlardır; sunulmayan seçenek offered: false ve null fiyatlarla döner (yanıltıcı hesaplanmış fiyat asla basılmaz). markupPct, gösterim etiketi ("+%X vade farkı") içindir — fiyatlar vade farkını zaten içerir. Çok taksitli toplamlar baz tutarı aşabilir — aradaki fark vade farkıdır ve quote'a dahildir.

Form içi endpointler (checkout form token)

Hosted checkout form oturumunun içinde aynı iki sorgu, secret key yerine checkout form token ile doğrulanan /form/… altında da vardır — token header'da değil, gövdede token alanı olarak gönderilir; böylece alıcının tarayıcısı doğrudan çağırabilir:

EndpointEşdeğeriFark
POST /form/bin/info/bin/infoGövde-token auth (token alanı)
POST /form/bin/installments/bin/installmentsGövde-token auth (token alanı); merchant, intent ve tutar token'dan çözülür (gövde yalnız binOrPan, paymentMethod, installment taşır); html format YOK
// Alıcının tarayıcısında, checkout oturumu içinde
const res = await fetch(
  'https://api-gateway.lunixi.com/api/v1/form/bin/installments',
  {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      token: checkoutFormToken, // auth — POST /payments/intents'ten
      binOrPan: '54000000',
      installment: 3,           // gösterge tablo için göndermeyin
    }),
  },
);
const quote = await res.json();

Quote binding — gösterilen == çekilen

Taksit fiyatı alıcıya verilmiş bir sözdür; platform bunu sözleşmeye dönüştürür:

  1. Aldığınız quote, o anki canlı sağlayıcı credential'ları ve vade farkı konfigürasyonuna göre hesaplanır ve süreli bir quoteToken altında mühürlenir.
  2. Yalnızca o quote'tan gelen seçenekleri gösterirsiniz — kendi hesapladığınız tutarları asla.
  3. Ödeme isteği (form/2d, form/3d, direct/payment) token'ı installmentQuoteToken olarak geri taşır.
  4. Çekim anında platform token'ı doğrular ve tam olarak quote'lanan tutarları çeker. Quote'un süresi dolmuşsa veya ödemeyle uyuşmuyorsa (farklı kart BIN'i, farklı tutar, mevcut olmayan seçenek) ödeme reddedilir — asla sessizce yeniden fiyatlanmaz.
⚠️

Taksit tablolarını oturumlar arası cache'lemeyin, vade farkını client tarafında yeniden hesaplamayın. Oranlar her an değişebilir; alıcının gördüğü tutarın çekilmesini yalnızca quoteToken garanti eder. Alıcı kararsız kalırken quote'un süresi dolarsa, taze bir quote alıp tabloyu yeniden render edin.

Ödeme isteğindeki amount sepet toplamıdır (baz tutar); 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ı. Yanıtlardaki ve webhook'lardaki tutar alanları bu çekilen tutarı gösterir.

Taksitsiz mi ödenecek? installmentQuoteToken'ı hiç göndermeyin — ödeme baz tutarı tek çekimde tahsil eder.

Hatalar

DurumNe görürsünüzNe yapmalı
BIN çok kısa / 6–8 kullanılabilir hane değil400 doğrulama hatasıEn az 6 hane yazılana kadar bekleyin
Bilinmeyen BINfound: false ile BIN_PATTERN_FALLBACKTaksitsiz (tek çekim) akışa düşün
Kart taksite uygun değilSeçenekler offered: false (veya yalnız-1×) dönerYalnızca tek çekim gösterin
Çekim anında süresi dolmuş quoteTokenÖdeme reddedilir — quote artık geçerli değilTaze quote alın, yeniden render edin, yeniden gönderin
Quote/ödeme uyumsuzluğu (farklı BIN veya tutar)Ödeme reddedilir — quote uyuşmuyorGerçek kart ve tutar için yeni quote alın
/form/bin/installments üzerinde html formatYok sayılır — form kapsamında HTML embed yokturdata payload'unu formun kendi UI'ıyla render edin
/bin/installments üzerinde amount da intentId de yokAMOUNT_REQUIREDMinor-unit amount (veya intentId) gönderin

Webhook'lar

BIN ve quote sorguları salt-okurdur ve webhook üretmez. Alacağınız event'ler ödemenin kendisinden gelir (payment.captured, payment.failed, …) — bkz. Webhooks.

Sonraki adımlar