Kimlik Doğrulama
Payment Orchestrator API'si, çağrıyı kimin yaptığına (sunucunuz, alıcının tarayıcısı, herkese açık siteniz) ve işlemin ne kadar hassas olduğuna göre farklı kimlik doğrulama modelleri kullanır. Bu sayfa her modeli çalışan örneklerle anlatır, ardından her endpoint grubunu gerektirdiği modele eşler.
| Model | Nedir | Nerede kullanılır |
|---|---|---|
Bearer erişim token'ı (at_live_…) | Ed25519 anahtarınızla bastığınız kısa ömürlü token | Listeleme, sorgular, subscription & marketplace CRUD |
| Step-Up (Bearer + Ed25519 imza) | Para hareketi için imzalı istek | Intent'ler, direct çekimler, capture/void/refund |
| İmzalı istek (yalnız Ed25519 imza) | Bearer token olmadan, isteğin kendisini API anahtarınızla imzalarsınız | Ödeme linkleri (/payments/links/*) |
| Form token + session-proof cookie | Kısa ömürlü alıcı tarafı kimlik bilgileri | /payments/form/* (hosted checkout) |
Publishable key (mk_live_pk_…) + Origin allow-list | Tarayıcıya konması güvenli key | /api/public/v1/subscription/* (pricing catalog) |
Idempotency-Key header | Çift çekim koruması | Tüm ödeme POST'ları |
Tüm örnekler için base URL: https://api-gateway.lunixi.com/api/v1.
Bearer erişim token'ı
Sunucudan sunucuya çağrıları kısa ömürlü bir erişim token'ı doğrular. Token'ı statik bir anahtar olarak saklamazsınız — kayıtlı Ed25519 anahtarınızla imzalayıp POST /api/v1/auth/token'dan basarsınız.
Ed25519 özel anahtar ──imzala──▶ POST /api/v1/auth/token ──▶ at_live_… (~5 dk)Aldığınız token'ı Authorization header'ında gönderin:
curl "https://api-gateway.lunixi.com/api/v1/payments?limit=20" \
-H "Authorization: Bearer at_live_5f3e2b1a..."Yukarıdaki örnek yalnız limit gönderiyor. GET /api/v1/payments cursor da kabul eder — sayfalamak için önerilen yol odur. Endpoint hâlâ page kabul ediyor ama o deprecated'dir: kullanıldığında yanıt Deprecation ve Sunset başlıkları taşır. → Sayfalama
Uzun ömürlü secret'ınız token değil, Ed25519 özel anahtarınızdır — ve o hiçbir zaman telde gitmez. Anahtarı tarayıcıya, mobil uygulamaya veya herkese açık bir depoya asla koymayın. Sızarsa panelden kid'i iptal edip yeni bir çift üretin.
Token ömrü tipik olarak 5 dakikadır. Her çağrıda yeni token basmayın — expires_at'e bakarak önbellekte tutun. İmzalama ve kanonik dize ayrıntısı: Kimlik Doğrulama
Step-Up: para hareketi için imzalı istekler
Para hareketi yapan her endpoint — intent oluşturma, direct çekim, capture, void, refund — Step-Up auth ister: geçerli bir Bearer key ve isteğin üzerine bir Ed25519 imzası. Secret key'iniz sızsa bile, saldırgan özel imza anahtarınız olmadan para hareket ettiremez.
Bir Step-Up isteği şu header'ları taşır:
| Header | Değer |
|---|---|
Authorization | Bearer at_live_… |
X-Key-Id | Kayıtlı Ed25519 public key'inizin key id'si (kid) |
X-Date | ISO 8601 istek zaman damgası — sunucu saatine göre ±5 dakika içinde olmalı |
X-Nonce | İstek başına benzersiz değer (örn. UUID) — tek kullanımlık, tekrarlar reddedilir |
Digest | Ham JSON body'nin SHA-256=<base64> hash'i (body varsa zorunlu) |
X-Signature | Aşağıdaki kanonik string üzerine Base64 Ed25519 imzası |
İmzalayacağınız string; method, tam istek path'i ve header'lardan \n ile birleştirilerek oluşturulur:
POST
/api/v1/payments/intents
X-Date:2026-07-06T12:00:00.000Z
X-Nonce:9f8d2c4e-1a3b-4c5d-8e7f-0a1b2c3d4e5f
Digest:SHA-256=k6I5cUt...=import { createHash, createPrivateKey, sign, randomUUID } from 'node:crypto';
const body = JSON.stringify({
amount: 10050, // minor unit (kuruş) — ₺100,50
currency: 'TRY',
orderId: 'ORD-9988',
});
const digest = 'SHA-256=' + createHash('sha256').update(body).digest('base64');
const date = new Date().toISOString();
const nonce = randomUUID();
const canonical = [
'POST',
'/api/v1/payments/intents',
`X-Date:${date}`,
`X-Nonce:${nonce}`,
`Digest:${digest}`,
].join('\n');
const signature = sign(
null, // Ed25519 — digest algoritması yok
Buffer.from(canonical),
createPrivateKey(process.env.LUNIXI_SIGNING_KEY_PEM),
).toString('base64');
const res = await fetch('https://api-gateway.lunixi.com/api/v1/payments/intents', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.LUNIXI_SECRET_KEY}`,
'Content-Type': 'application/json',
'X-Key-Id': process.env.LUNIXI_KEY_ID,
'X-Date': date,
'X-Nonce': nonce,
'Digest': digest,
'X-Signature': signature,
'Idempotency-Key': randomUUID(),
},
body,
});Bearer key ile imza anahtarı aynı merchant'a ve aynı environment'a ait olmalıdır — uyuşmazlık 403 AUTH_MERCHANT_MISMATCH / AUTH_ENVIRONMENT_MISMATCH ile reddedilir.
Checkout form token & session-proof cookie (alıcı tarafı)
Hosted checkout formu, key'lerinizi hiç ifşa etmeden alıcının tarayıcısını doğrular:
- Sunucunuz Step-Up auth ile bir intent oluşturur. Yanıt,
allowedOrigin'inize bağlı, kısa ömürlü (~15 dakika) bir form token içerir. - Form bu token ile
POST /payments/form/live-analyzeçağırır; yanıt, tarayıcı oturumunu bağlayan bir session-proof cookie set eder. - Her
/payments/form/*çağrısı token'ı taşır; karta dokunan çağrılar (/form/tokenize,/form/2d,/form/3d) ek olarak session-proof cookie'yi ister.
curl -X POST "https://api-gateway.lunixi.com/api/v1/payments/form/live-analyze" \
-H "Content-Type: application/json" \
-c cookies.txt \
-d '{ "token": "<intent-ten-gelen-form-token>" }'https://cdn.lunixi.com üzerinden Lunixi checkout SDK'sını kullanıyorsanız token aktarımı, live-analyze çağrısı ve cookie yönetimi otomatik yapılır — bu kimlik bilgilerini hiç yönetmezsiniz. Bkz. Hızlı Başlangıç.
Publishable key + Origin allow-list
Publishable key (mk_live_pk_…) herkese açık sitenize gömülmesi güvenli olan key'dir. Yalnızca salt-okunur public catalog endpointlerini açar ve istekler ayrıca kayıtlı Origin allow-list'inize karşı denetlenir — çalınan bir key başka bir domain'den işe yaramaz.
curl "https://api-gateway.lunixi.com/api/public/v1/subscription/plans" \
-H "Authorization: Bearer mk_live_pk_xxxxxxxxxxxx" \
-H "Origin: https://shop.example.com"/api/public/v1/subscription/plans|products|branding tarafından kullanılır — sitenize pricing gömmek için. Bkz. Pricing & Portal SDK.
Idempotency
Her ödeme POST'unda bir Idempotency-Key header'ı gönderin (benzersiz herhangi bir string, örn. UUID). Aynı key tekrar gelirse — ağ zaman aşımı, çift tıklanan buton, tekrar deneyen bir job — API çifte çekim yapmak yerine orijinal sonucu döner. Tekilleştirme Redis ile, Redis erişilemezse veritabanı benzersizliğiyle desteklenir.
curl -X POST "https://api-gateway.lunixi.com/api/v1/payments/pay_01JZ8K4W9X2R/refund" \
-H "Authorization: Bearer at_live_5f3e2b1a..." \
-H "Idempotency-Key: refund-ORD-9988-1" \
... # Step-Up imza header'ları
-d '{ "amount": 5000 }'İsteği değil işlemi tanımlayan bir key kullanın — örn. refund-ORD-9988-1. Her denemede yeni rastgele key üretmek korumayı boşa çıkarır.
Hangi endpoint hangi modeli ister
| Endpoint grubu | Auth modeli |
|---|---|
POST /payments/intents, POST /payments/marketplace/intents | Step-Up |
POST /payments/direct/payment, GET /payments/methods | Step-Up |
POST /payments/:id/capture, /:id/void, /:id/refund | Step-Up |
GET /payments, GET /payments/:id, analytics | Bearer |
POST /bin/info, GET /bin/card-taxonomy, POST /bin/installments | Bearer |
/chargebacks/* | Bearer |
/payments/form/* (2d, 3d, tokenize, live-analyze, bin) | Form token (karta dokunan çağrılarda + session-proof cookie) |
GET /payments/threed/:token, /payments/threed/callback/:token | Public — path'teki tek kullanımlık token güvenlik sınırıdır |
/payments/links/* (oluşturma, listeleme, güncelleme, gönderme, QR) | İmzalı istek — Ed25519 imza başlıkları ve anahtarın payment-link:* yetkisi; Authorization gerekmez, panel oturumu kabul edilmez — bkz. Link Oluşturma |
/api/public/v1/pay/* (ödeme linki sayfası) | Public — alıcının tarayıcısı çağırır; anahtar taşımaz, bot kontrolü (Turnstile) ve kısa ömürlü ödeme oturumu çerezi ile korunur. Sizin çağırmanız gerekmez — bkz. Ödeme Sayfası |
/marketplace/* (dealers, komisyonlar, payout'lar) | Bearer |
/marketplace/portal/* (satıcı onboarding'i) | Marketplace onboarding token (X-Marketplace-Token) — bkz. Satıcı Onboarding |
/api/v1/subscriptions/* | Bearer |
/api/public/v1/subscription/* | Publishable key + Origin |
/api/portal/v1/* (son müşteri self-service) | Portal session (portal token → OTP → session JWT) — bkz. Müşteri Portalı |
Hatalar
| Status / kod | Anlamı | Ne yapmalı |
|---|---|---|
401 AUTH_HEADERS_MISSING | X-Key-Id, X-Date, X-Nonce, X-Signature'dan biri eksik | Dört Step-Up header'ının hepsini gönderin |
401 INVALID_DATE | X-Date ±5 dakikalık pencerenin dışında | Sunucu saatinizi senkronlayın (NTP) ve tekrar deneyin |
401 DIGEST_MISSING / INVALID_DIGEST | Body var ama Digest eksik veya yanlış | Gönderdiğiniz ham body byte'larını hash'leyin |
401 INVALID_SIGNATURE | İmza doğrulanamadı | Kanonik string'i yeniden kurun — method, path, header'lar, bu sırayla, \n ile |
401 (nonce tekrarı) | X-Nonce daha önce kullanıldı | Her istek için yeni nonce üretin |
403 AUTH_MERCHANT_MISMATCH | Bearer key ile imza anahtarı farklı merchant'lara ait | Aynı merchant hesabının key'lerini kullanın |
403 AUTH_ENVIRONMENT_MISMATCH | Test key ile live key karışmış | Test ve live kimlik bilgilerini ayrı tutun |
403 IP_NOT_ALLOWED | Çağıran IP, key'in IP allow-list'inde değil | Panelden allow-list'i güncelleyin |
Sonraki adımlar
- Hızlı Başlangıç — Step-Up akışını kullanıp ilk ödemenizi alın
- Checkout Formu — eksiksiz intent-create referansı
- Webhook'lar — imzalı event teslimatlarını doğrulayın