Kimlik Doğrulama

Kaptan Partner API'nin veri düzlemi (/partner/1.0/...) her isteğe per-request HMAC-SHA256 imzası uygular. İmza; timestamp, HTTP metodu, istek yolu ve body içeriğine bağlıdır — böylece hem kimlik doğrulama hem de replay koruması sağlanır.

Base URL

https://<host>/partner/1.0/...

Tüm veri-düzlemi çağrıları POST + JSON gövdedir. /api gibi bir önek yoktur; yol doğrudan /partner/1.0/ ile başlar (ör. /partner/1.0/pos/card/pay).

Header'lar

HeaderAçıklama
X-Api-KeyEntegrasyonun public anahtarı. Önek ok_live_ (canlı) veya ok_test_ (sandbox). ok_test_ işlemi sandbox olarak etiketler; sağlayıcı yönlendirmesini değiştirmez.
X-Timestampİstek zamanı, epoch milisaniye (unix-millis). Sunucu saatinden ±5 dakika dışındaki değerler stale timestamp ile reddedilir.
X-SignatureAşağıdaki algoritmayla üretilen, küçük harf hex HMAC-SHA256 imzası.

İmza Algoritması

1. bodyHash  = hex( SHA-256( ham istek body byte'ları ) )
              (boş body → boş byte dizisinin SHA-256'sı)

2. canonical = X-Timestamp + "\n" + HTTP_METHOD + "\n" + requestPath + "\n" + bodyHash
              (requestPath örn. "/partner/1.0/pos/card/pay")

3. X-Signature = hex( HmacSHA256( secret, canonical ) )   // küçük harf
  • secret, entegrasyon oluşturulduğunda yalnızca bir kez gösterilir; sonradan tekrar alınamaz. Güvenli saklamak entegratörün sorumluluğundadır.
  • HTTP_METHOD büyük harf (POST).
  • requestPath query string içermez; yalnızca yol kısmıdır.
  • Hex çıktılar küçük harf olmalıdır.

İmzayı elle doğrulamak için HMAC İmza Üretici aracını kullanabilirsiniz.

Replay Koruması

İmza; timestamp + body'ye bağlı olduğundan 5 dakikalık pencere içinde tekildir. Aynı X-Signature pencere içinde ikinci kez görülürse istek replay detected ile reddedilir. Her istekte yeni bir X-Timestamp kullanın (bu, imzayı da değiştirir).

IP Allowlist & Geçerlilik

Bir entegrasyon, izin verilen IP adreslerini kısıtlayabilir ve bir son kullanım (expiry) tarihi tanımlayabilir. İzinli olmayan bir IP'den gelen veya süresi geçmiş anahtarla yapılan istekler reddedilir.

Yeniden Kullanılabilir İstemci

Aşağıdaki yardımcılar imzayı hesaplar ve isteği gönderir. KAPTAN_API_KEY, KAPTAN_API_SECRET ve KAPTAN_BASE_URL ortam değişkenlerinden okurlar; böylece endpoint örnekleri kısa kalır. Endpoint sayfalarındaki JavaScript, PHP, Java ve C# örnekleri bu yardımcıları varsayar.

import crypto from 'node:crypto';

const BASE = process.env.KAPTAN_BASE_URL;       // https://<host>
const API_KEY = process.env.KAPTAN_API_KEY;     // ok_live_... / ok_test_...
const SECRET = process.env.KAPTAN_API_SECRET;   // yalnızca create anında görülür

// path örn. "/partner/1.0/pos/card/pay"
// idempotencyKey: yazma uçlarında ZORUNLU (bkz. /reference/idempotency)
export async function kaptanRequest(path, bodyObj, idempotencyKey) {
  const body = bodyObj === null ? '' : JSON.stringify(bodyObj);
  const timestamp = Date.now().toString();

  // 1) bodyHash
  const bodyHash = crypto.createHash('sha256').update(body, 'utf8').digest('hex');
  // 2) canonical string
  const canonical = `${timestamp}\nPOST\n${path}\n${bodyHash}`;
  // 3) HMAC-SHA256 (lowercase hex)
  const signature = crypto.createHmac('sha256', SECRET).update(canonical, 'utf8').digest('hex');

  const headers = {
    'X-Api-Key': API_KEY,
    'X-Timestamp': timestamp,
    'X-Signature': signature,
    'Content-Type': 'application/json',
  };
  // Idempotency-Key imzaya dahil DEĞİLDİR; yalnız header olarak gider.
  if (idempotencyKey) {
    headers['Idempotency-Key'] = idempotencyKey;
  }

  const res = await fetch(BASE + path, {method: 'POST', headers, body});
  if (!res.ok) {
    throw new Error(`Kaptan API ${res.status}: ${await res.text()}`);
  }
  return res.json();
}