İçeriğe geç

İmzaları doğrulama

Her teslimat bir Ciqra-Signature header’ı taşır. İmzası doğrulanmayan her isteği reddedin — endpoint’iniz herkese açıktır ve ona herkes POST atabilir.

Ciqra-Signature: t=1758535200,v1=530e6f8f…4596
Parça Anlamı
t CIQRA’nın teslimatı imzaladığı Unix zamanı (saniye).
v1 HMAC-SHA256(key = signing secret, message = t + "." + raw body) değerinin küçük harfli hex gösterimi. Birden fazla kez geçebilir — aşağıya bakın.

Anahtar, kurulumunuzun imzalama secret’ının (ciqra_ss_…) UTF-8 baytlarıdır — önek dahil dizenin tamamı. Mesaj ise zaman damgası, düz bir . ve istek gövdesinin alındığı haliyle ham (raw) baytlarıdır. Ayrıştırmadan önce doğrulayın: ayrıştırılmış JSON’u yeniden serileştirmek baytları değiştirir ve imza tutmaz.

İmzalama secret’ınız döndürüldüğünde (rotate) önceki secret bir geçiş penceresi (24 saat) boyunca geçerli kalır. Bu pencerede her teslimat, geçerli her secret için bir v1 taşır; önce güncel olan:

Ciqra-Signature: t=1758535200,v1=<yeni secret ile imza>,v1=<önceki secret ile imza>

Böylece yeni secret’a istediğiniz an geçebilirsiniz: elinizde hangisi varsa o doğrular. Hesapladığınız değer HERHANGİ bir v1 ile eşleşiyorsa teslimatı kabul edin; yalnızca ilkine ya da sonuncusuna bakmayın. Bir header en fazla 4 imza taşır; dördüncüden sonrakileri yok sayabilirsiniz. Rotasyon dışında, eskisi gibi tam bir v1 vardır.

CIQRA bir secret’ı ele geçirildiği için emekliye ayırırsa geçiş penceresi olmaz: yalnızca yeni secret imzalar ve yeni secret size verilene kadar teslimatlar doğrulanmaz.

  1. Header’ı , ile, her parçayı da ilk = ile bölün; t’yi ve her v1’i (en fazla 4) alın.
  2. t saatinizden 5 dakikadan fazla uzaksa reddedin — bu, yakalanmış teslimatların yeniden oynatılmasını (replay) engeller.
  3. hex(HMAC-SHA256(secret, t + "." + rawBody)) değerini hesaplayın.
  4. Her v1 ile sabit zamanlı (constant time) karşılaştırın; herhangi biri eşleşirse kabul edin.
verify-signature.mjs
import { createHmac, timingSafeEqual } from "node:crypto";
// Verify a CIQRA webhook. rawBody: the request body exactly as received (string), before any JSON parsing.
// The header may carry more than one v1 (during a signing-secret rotation): accept if ANY of them matches.
export function verifyCiqra(rawBody, header, secret, toleranceSec = 300, nowSec = Date.now() / 1000) {
let t = null;
const given = [];
for (const part of String(header).split(",")) {
const eq = part.indexOf("=");
if (eq <= 0) continue;
const key = part.slice(0, eq).trim();
const value = part.slice(eq + 1).trim();
if (key === "t") t = Number(value);
else if (key === "v1" && given.length < 4) given.push(value);
}
if (!Number.isInteger(t) || Math.abs(nowSec - t) > toleranceSec) return false;
const expected = Buffer.from(createHmac("sha256", secret).update(`${t}.${rawBody}`, "utf8").digest("hex"));
let ok = false;
for (const v1 of given) {
const candidate = Buffer.from(v1);
if (candidate.length === expected.length && timingSafeEqual(candidate, expected)) ok = true;
}
return ok;
}

Yukarıdaki Node.js ve Python kodu, bu sitenin test takımının aşağıdaki test vektörüne karşı çalıştırdığı dosyanın ta kendisidir.

Gerçek bir mağazaya bağlanmadan önce uygulamanızı bununla kontrol edin.

Girdi Değer
secret ciqra_ss_test
ham gövde {"orderId":"0f8e","status":"Paid"}
t 1758535200
imzalanan mesaj 1758535200.{"orderId":"0f8e","status":"Paid"}
header t=1758535200,v1=530e6f8fc05a8e47dd1befcbdf45fa89b16b4491362f5e7c0427b44965bb4596

Bu değer platformun kendi içindeki bir testle sabitlenmiştir; dolayısıyla CIQRA’nın gerçekte gönderdiğinden sapamaz. Test ederken sabit bir “şimdi” değeri vermeyi unutmayın, yoksa 5 dakikalık pencere 2025 tarihli zaman damgasını reddeder.

Header Değer
Ciqra-Event Olay türü, ör. order.paid.
Ciqra-Event-Id Olayın kararlı id’si — tekilleştirme için bunu kullanın.
Ciqra-Delivery Bu teslimat deneme serisinin id’si.
Ciqra-Webhook-Id Abonelik id’si.
Ciqra-Event-Age-Seconds Olayın gerçekleşmesinden bu yana geçen saniye; yeniden denemelerden sonra büyür.
User-Agent CIQRA-Webhooks/1.0

Bu header’lar imzalı değildir. Yönlendirme için kullanın; veri için yalnızca imzalı gövdeye güvenin.