İç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.

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.

  1. Header’ı , ile, her parçayı da ilk = ile bölün; t ve v1’i 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. v1 ile sabit zamanlı (constant time) karşılaştırın.
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.
export function verifyCiqra(rawBody, header, secret, toleranceSec = 300, nowSec = Date.now() / 1000) {
const parts = {};
for (const part of String(header).split(",")) {
const eq = part.indexOf("=");
if (eq > 0) parts[part.slice(0, eq).trim()] = part.slice(eq + 1).trim();
}
const t = Number(parts.t);
if (!Number.isInteger(t) || Math.abs(nowSec - t) > toleranceSec) return false;
const expected = createHmac("sha256", secret).update(`${t}.${rawBody}`, "utf8").digest("hex");
const given = parts.v1 ?? "";
return given.length === expected.length && timingSafeEqual(Buffer.from(given), Buffer.from(expected));
}

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.