Fiziksel POS
Kimlik Doğrulama ve Kapsamlar

Kimlik Doğrulama ve Kapsamlar

Bu uçları kim çağırır?Dış API (s2s)
Taban yol
/api/v1/physical-pos
Kimlik
Her istekte Ed25519 istek imzası — X-Key-Id, X-Date, X-Nonce, X-Signature; gövdeli isteklerde ayrıca Digest. Zaman penceresi ±5 dk, nonce tek kullanımlık. Bearer jetonu ya da panel oturumu bu uçlarda kabul edilmez.
Yetki
Anahtarınız Fiziksel POS ürününü (PHYSICAL_POS) ve bu sayfadaki uçların kapsamını taşımalıdır: physical_pos:view · physical_pos:manage. Ürünü olmayan anahtar 403 PRODUCT_NOT_ENABLED, kapsamı olmayan anahtar 403 API_INSUFFICIENT_SCOPE alır. Bkz. Kimlik Doğrulama ve Kapsamlar.
Çapraz yüzey
Bu uçlar s2s yüzeyindedir; kendi sunucunuzdan imzalı istekle çağırırsınız. Aynı kayıtların panelde ekranları var, ama panel uçları API anahtarıyla çağrılamaz; bu uçlar da panel oturumuyla çağrılamaz.

Fiziksel POS yönetim uçlarını kendi sunucunuzdan, API anahtarınızla imzaladığınız isteklerle çağırırsınız. Her istekte üç şey sırayla denetlenir: imza, ürün ve kapsam.

İstek imzası

Her istek API anahtarınızla imzalanır. Authorization: Bearer jetonu ve panel oturumu bu uçlarda kimlik yerine geçmez; imza başlıkları olmayan istek 401 alır.

BaşlıkDeğer
X-Key-IdAnahtarınızın kimliği: test için mk_test_…, canlı için mk_live_…
X-DateISO 8601 zaman damgası; sunucu saatine göre ±5 dakika içinde
X-Nonceİstek başına benzersiz değer; tek kullanımlık
DigestYalnız gövdeli isteklerde (POST, PATCH): gövdenin SHA-256 özeti, SHA-256=<base64> biçiminde
X-SignatureKanonik dizinin Base64 Ed25519 imzası

Kanonik dizi YÖNTEM, tam yol (sorgu dizesi dahil), X-Date:…, X-Nonce:… ve gövde varsa Digest:… satırlarının \n ile birleşimidir. Gövdesiz isteklerde Digest satırı hiç yazılmaz. Kuralların tamamı ve anahtar yönetimi: Kimlik Doğrulama › Kanonik dize · Digest başlığının biçimi.

⚠️

İmzalanan yol sorgu dizesini de içerir ve gönderdiğiniz yolla birebir aynı olmalıdır: GET /api/v1/physical-pos/stores?status=ACTIVE&limit=50 imzalanırken ikinci satır /api/v1/physical-pos/stores?status=ACTIVE&limit=50 olur.

İmza yardımcısı

Bu bölümdeki cURL örnekleri imzayı aşağıdaki kabuk fonksiyonuyla hesaplar (OpenSSL 3.0 veya üstü gerekir). Gövde verirseniz Digest de hesaplanır:

# lunixi-sign.sh — Kullanım:
#   source lunixi-sign.sh
#   lunixi_sign GET  "/api/v1/physical-pos/stores"
#   lunixi_sign POST "/api/v1/physical-pos/stores" "$BODY"
LUNIXI_KEY_ID="mk_test_..."
LUNIXI_KEY_FILE="lunixi-signing.key"
 
lunixi_sign() {
  local method="$1" req_path="$2" body="$3"
  DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
  NONCE=$(openssl rand -hex 16)
  if [ -n "$body" ]; then
    DIGEST="SHA-256=$(printf '%s' "$body" | openssl dgst -sha256 -binary | base64)"
    printf '%s\n%s\nX-Date:%s\nX-Nonce:%s\nDigest:%s' "$method" "$req_path" "$DATE" "$NONCE" "$DIGEST" > canonical.txt
  else
    DIGEST=""
    printf '%s\n%s\nX-Date:%s\nX-Nonce:%s' "$method" "$req_path" "$DATE" "$NONCE" > canonical.txt
  fi
  SIGNATURE=$(openssl pkeyutl -sign -inkey "$LUNIXI_KEY_FILE" -rawin -in canonical.txt | base64 | tr -d '\n')
}
⚠️

Digest, kompakt JSON gövdeden hesaplanır. Sunucu gövdeyi ayrıştırıp kompakt biçimde yeniden yazar ve özeti bu metinden hesaplar. Gövdeyi boşluksuz, ASCII dışı karakterleri kaçışlamadan ("Kadıköy", "Kad\u0131k\u00f6y" değil) ve / işaretini kaçışlamadan gönderin; özeti aynı metnin UTF-8 baytlarından hesaplayın. Başka biçimdeki gövde 401 INVALID_DIGEST alır. Ayrıntı: Kimlik Doğrulama › Digest başlığının biçimi.

Gövdeyi kendi kodunuzda üretirken:

// Node.js
const body = JSON.stringify(payload);
# Python
body = json.dumps(payload, separators=(",", ":"), ensure_ascii=False)
// PHP
$body = json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);

Okuma isteği örneği:

source lunixi-sign.sh
REQ_PATH="/api/v1/physical-pos/overview"
lunixi_sign GET "$REQ_PATH"
 
curl "https://api-gateway.lunixi.com$REQ_PATH" \
  -H "X-Key-Id: $LUNIXI_KEY_ID" \
  -H "X-Date: $DATE" \
  -H "X-Nonce: $NONCE" \
  -H "X-Signature: $SIGNATURE"

Gövdeli istek örneği:

source lunixi-sign.sh
REQ_PATH="/api/v1/physical-pos/stores"
BODY='{"code":"IST-KADIKOY","name":"Kadıköy Mağazası"}'
lunixi_sign POST "$REQ_PATH" "$BODY"
 
curl -X POST "https://api-gateway.lunixi.com$REQ_PATH" \
  -H "Content-Type: application/json" \
  -H "X-Key-Id: $LUNIXI_KEY_ID" \
  -H "X-Date: $DATE" \
  -H "X-Nonce: $NONCE" \
  -H "Digest: $DIGEST" \
  -H "X-Signature: $SIGNATURE" \
  -H "Idempotency-Key: $(uuidgen)" \
  --data-raw "$BODY"

Ürün

İmza doğrulandıktan sonra anahtarınızda Fiziksel POS ürününün (PHYSICAL_POS) tanımlı olup olmadığına bakılır. Tanımlı değilse istek 403 PRODUCT_NOT_ENABLED alır. → Hata Yönetimi › PRODUCT_NOT_ENABLED

Kapsamlar

Ürün denetiminden sonra anahtarın, ucun istediği kapsamı taşıması gerekir. Taşımıyorsa istek 403 API_INSUFFICIENT_SCOPE alır.

KapsamVerdiği yetkiUçlar
physical_pos:viewOkumaBütün GET uçları: katalog, mağaza ve kasa listeleri ve ayrıntıları, değişiklik geçmişleri, terminaller, banka satırları, cihazlar, atama ve bağ geçmişleri, genel bakış sayaçları
physical_pos:manageYazmaBütün POST ve PATCH uçları: mağaza ve kasa oluşturma, güncelleme, arşivleme ve yeniden açma; terminal oluşturma, güncelleme ve kapatma; banka satırı ekleme ve güncelleme; cihaz kaydetme, güncelleme, atama, depoya alma ve emeklilik; cihaz bağını değiştirme ve çözme
physical_pos:identityCihaz kimliği işlemleriBu bölümde anlatılan uçların hiçbiri bu kapsamı istemez.
⚠️

physical_pos:manage okuma yetkisi içermez. Hem okuyup hem yazacak bir entegrasyonun anahtarında iki kapsam da bulunmalıdır. Örneğin bir terminali güncellemeden önce güncel rowVersion değerini okumanız gerekir; bunun için physical_pos:view şarttır.

Kapsamlar panelde API anahtarınızın yetki ayarlarında, Fiziksel POS grubunda listelenir; anahtar başına ekleyip kaldırabilirsiniz. Bir anahtara yalnız işinin gerektirdiği kapsamları verin: yalnız raporlama yapan bir entegrasyona physical_pos:view yeterlidir.

Ortamı (test ya da canlı) anahtarınız belirler; kapsamlar iki ortamda da aynı anlamı taşır. Test anahtarı bütün kayıtları yalnız okur; yazma istekleri 403 physical_pos.environment.test_key_read_only alır. → Ortamlar

Kimlik ve kiracı

İsteğin hangi organizasyon adına yapıldığı ve ortamı yalnız imzalı anahtarınızdan çözülür. Gövdede ya da sorguda organizationId, merchantId ya da environment gönderilmez: organizationId ve merchantId 400 VALIDATION_ERROR, environment 400 physical_pos.input.environment_invalid alır. Başka bir organizasyona ait kayıt, olmayan kayıtla aynı 404 cevabını alır.

Sıradaki adım

  • Test ve canlı ortam farkları: Ortamlar
  • Sayfalama, Idempotency-Key, rowVersion ve yanıt biçimi: Ortak Kurallar