Webhooks — Python SDK
Flask example
from flask import Flask, request, jsonify
import simiz
app = Flask(__name__)
client = simiz.Client(api_key="sk_test_xxxxxxxxxxxx")
@app.route('/webhooks/simiz', methods=['POST'])
def handle_webhook():
payload = request.get_data()
signature = request.headers.get('X-Simiz-Signature')
try:
event = client.webhooks.construct_event(
payload=payload,
signature=signature,
secret="whsec_xxxxxxxxxxxx"
)
if event.type == "payment.succeeded":
print(f"Payment received: {event.data.id}")
elif event.type == "payment.failed":
print(f"Payment failed: {event.data.id}")
elif event.type == "refund.succeeded":
print(f"Refund completed: {event.data.id}")
return jsonify(received=True), 200
except simiz.errors.SignatureVerificationError as e:
return f"Invalid signature: {e}", 401
Django example
from django.http import JsonResponse, HttpResponse
from django.views.decorators.csrf import csrf_exempt
import simiz
client = simiz.Client(api_key="sk_test_xxxxxxxxxxxx")
@csrf_exempt
def webhook_handler(request):
if request.method != 'POST':
return HttpResponse(status=405)
payload = request.body
signature = request.META.get('HTTP_X_SIMIZ_SIGNATURE')
try:
event = client.webhooks.construct_event(
payload=payload,
signature=signature,
secret="whsec_xxxxxxxxxxxx"
)
# Process event...
return JsonResponse({"received": True})
except simiz.errors.SignatureVerificationError:
return HttpResponse("Invalid signature", status=401)
Manual verification
Signature format:
X-Simiz-Signature: t=<timestamp>,v1=<hmac_sha256_hex>The timestamp protects against replay attacks. Signatures older than 5 minutes are rejected.import hmac
import hashlib
def verify_signature(payload: bytes, signature_header: str, secret: str, tolerance_seconds: int = 300) -> bool:
"""Verify Simiz webhook signature with replay protection."""
# Parse signature header: t=<timestamp>,v1=<hash>
parts = signature_header.split(',')
timestamp = None
hash_value = None
for part in parts:
if part.startswith('t='):
timestamp = int(part[2:])
elif part.startswith('v1='):
hash_value = part[3:]
if timestamp is None or hash_value is None:
return False
# Check timestamp is within tolerance (default: 5 minutes)
import time
now = int(time.time())
if abs(now - timestamp) > tolerance_seconds:
return False
# Calculate expected signature
signature_payload = f"{timestamp}.{payload.decode()}"
expected_signature = hmac.new(
secret.encode(),
signature_payload.encode(),
hashlib.sha256
).hexdigest()
# Timing-safe comparison
return hmac.compare_digest(
hash_value.encode(),
expected_signature.encode()
)

