Ana içeriğe geç

İmza Doğrulama

Paylox'tan gelen webhook ve callback isteklerinin gerçekten Paylox'tan geldiğini doğrulamak için HMAC-SHA256 imza mekanizması kullanılır.

Nasıl Çalışır?

  1. Paylox, webhook gönderirken payload'ı secret key ile imzalar
  2. İmza, X-Paylox-Signature header'ında gönderilir
  3. Siz de aynı secret key ile imzayı hesaplayıp karşılaştırırsınız

İmza Hesaplama

signature = HMAC-SHA256(webhook_secret, request_body)

Node.js

const crypto = require("crypto");

function verifySignature(payload, signature, secret) {
const expected = crypto
.createHmac("sha256", secret)
.update(payload, "utf8")
.digest("hex");

return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}

app.post("/webhooks/paylox", (req, res) => {
const signature = req.headers["x-paylox-signature"];
const isValid = verifySignature(
JSON.stringify(req.body),
signature,
process.env.PAYLOX_WEBHOOK_SECRET
);

if (!isValid) {
return res.status(401).json({ error: "Invalid signature" });
}

res.status(200).json({ received: true });
});

Python

import hmac
import hashlib

def verify_signature(payload, signature, secret):
expected = hmac.new(
secret.encode("utf-8"),
payload.encode("utf-8"),
hashlib.sha256
).hexdigest()

return hmac.compare_digest(signature, expected)
import json
from django.http import JsonResponse

def paylox_webhook(request):
signature = request.headers.get("X-Paylox-Signature", "")
is_valid = verify_signature(
request.body.decode("utf-8"),
signature,
os.environ["PAYLOX_WEBHOOK_SECRET"]
)

if not is_valid:
return JsonResponse({"error": "Invalid signature"}, status=401)

return JsonResponse({"received": True})

PHP

<?php

function verifySignature(string $payload, string $signature, string $secret): bool
{
$expected = hash_hmac('sha256', $payload, $secret);
return hash_equals($expected, $signature);
}

$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_PAYLOX_SIGNATURE'] ?? '';
$secret = getenv('PAYLOX_WEBHOOK_SECRET');

if (!verifySignature($payload, $signature, $secret)) {
http_response_code(401);
echo json_encode(['error' => 'Invalid signature']);
exit;
}

http_response_code(200);
echo json_encode(['received' => true]);

Önemli Kurallar

KuralAçıklama
Timing-safe karşılaştırma== yerine timingSafeEqual / compare_digest / hash_equals kullanın
Raw bodyİmzayı parse edilmiş body değil, ham body üzerinden hesaplayın
Secret güvenliğiWebhook secret'ı environment variable olarak saklayın