Bir Qvard webhook'ını nasıl doğrularsınız

X-Qvard-Signature başlığı hakkında kısa bir kılavuz: nedir ve bunu birkaç satır kod ile nasıl kontrol edersiniz.

İmza nedir

Bir ödemenin durumu değiştiğinde, Qvard mağaza ayarlarınızdaki adrese bir bildirim (webhook) gönderir. O adrese herhangi biri bir istek gönderebilir, bu nedenle gerçek bir bildirimi sahte bir bildirimden ayırt etmenin bir yoluna ihtiyaç vardır.

İmza bu kanıttır: Qvard'ın ileti ve gizli anahtarınızdan hesapladığı kısa bir kod. Yalnız Qvard ve siz anahtarı bilirsiniz, bu nedenle yalnızca Qvard doğru kodu üretebilir.

Ne alırsınız

Her webhook ekstra bir başlık ve küçük bir JSON gövdesi taşır:

X-Qvard-Signature: t=1760950000,v1=3f2a…c91e {"id":"order_1024","status":"paid"}

t mesajın gönderildiği saattir (Unix, saniye). v1 koddur. Gizli anahtarınızı döndürdükten sonra 24 saat boyunca başlık iki v1 değeri taşır: biri yeni anahtar için, biri eski anahtar için.

id ve status alanları aynen kalır. İmzalanan aynı gövdeye dört tutar alanı eklenir:

  • amount ve currency: isteğde gönderdiğiniz tutar ve para birimi.
  • amountUsd: muhasebede kullanılan USD tutarı.
  • rate: ödeme oluşturulduğu andaki 1 USD karşılığı para birimi miktarı.
  • Eski entegrasyonlar çalışmaya devam eder: id ve status alanlarını okurlar, yeni alanları yok sayarlar. İmza öncekiyle aynı gövde üzerinden doğrulanır.

Nasıl kontrol edersiniz

  1. 1
    İstek gövdesini tam olarak geldiği gibi alın: ham metin, herhangi bir JSON ayrıştırmasından önce.
  2. 2
    X-Qvard-Signature başlığından t ve her v1'i okuyun.
  3. 3
    Metni t + "." + gövde ile gizli anahtarınızı (qvard_sk_…) kullanarak HMAC-SHA256 olarak hesaplayın ve küçük harf onaltılık olarak yazın.
  4. 4
    Sonucunuz herhangi bir v1 ile eşleşirse (sabit zamanda karşılaştırın), ileti gerçektir.
  5. 5
    İnsanların 5 dakikadan uzun bir mesajı tekrar göndermesini sağlamayacak şekilde t'nin 5 dakikadan daha eski olmadığını kontrol edin.
  6. 6
    Ancak o zaman verileri kullanın ve o sipariş için ödenen tutarı kendi veritabanınızda doğrulayın.

Hazır kod

const crypto = require('crypto');

function verifyQvardSignature(rawBody, header, secret, toleranceSec = 300) {
  const parts = header.split(',').map((p) => p.trim());
  const t = Number((parts.find((p) => p.startsWith('t=')) || '').slice(2));
  const sigs = parts.filter((p) => p.startsWith('v1=')).map((p) => p.slice(3));
  if (!t || sigs.length === 0) return false;
  if (Math.abs(Date.now() / 1000 - t) > toleranceSec) return false;
  const expected = crypto.createHmac('sha256', secret).update(`${t}.${rawBody}`).digest();
  return sigs.some((s) => {
    const got = Buffer.from(s, 'hex');
    return got.length === expected.length && crypto.timingSafeEqual(got, expected);
  });
}

// Use the RAW body: express.raw, not express.json
app.post('/qvard-webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const raw = req.body.toString('utf8');
  if (!verifyQvardSignature(raw, req.get('X-Qvard-Signature') || '', process.env.QVARD_SECRET_KEY)) {
    return res.sendStatus(400);
  }
  const { id, status } = JSON.parse(raw);
  // Confirm the paid amount for order `id` in your own database before fulfilling it.
  res.sendStatus(200);
});

Gizli anahtarınızı döndürdükten sonra 24 saat boyunca başlık iki v1 değeri taşır: herhangi biri eşleşirse webhook'u kabul edin.

Yaygın hatalar

  • JSON'u ayrıştırıp yeniden seri hale getirmek metni değiştirir. Her zaman ham gövdeyi kullanın.
  • Gizli anahtar yerine genel anahtarı (qvard_pk_…) kullanma.
  • Senkronize olmayan bir sunucu saati 5 dakikalık kontrolü başarısız kılar. Senkronize tutun.
  • Sabit zaman karşılaştırması yerine == ile karşılaştırma.

Gizli anahtarınızı nerede bulursunuz

Panelde: mağazanız, Ayarlar, API anahtarları. Yalnızca sunucunuzda saklayın. Sızarsa, orada döndürün: eski anahtar ödememeler için 24 saat daha çalışır (para çekmeleri için değil).

Paneli aç

API referansı

Eski anahtarlar

Mağazanızda hala eski format anahtarı varsa (qvard_sk_ öneki olmadan), webhook'lar da o anahtarı içeren x-api-key başlığını taşır. Döndürdükten sonra, o başlık kaybolur. İmza kontrolüne geçin.

Ödeme penceresini denemek ister misiniz?

Demoyu aç