Webhook Handler Examples
Complete webhook handler implementations for popular languages and frameworks.
<?php
header('Content-Type: application/json');
$rawPayload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_RAZCRYPTO_SIGNATURE'] ?? '';
$secret = getenv('RAZ_WEBHOOK_SECRET');
$expected = hash_hmac('sha256', $rawPayload, $secret);
if (!hash_equals($expected, $signature)) {
http_response_code(401);
exit(json_encode(['error' => 'Invalid signature']));
}
$data = json_decode($rawPayload, true);
$event = $data['event'] ?? '';
if ($event === 'payment.completed') {
$paymentId = $data['payment_id'];
$amount = $data['amount'];
$txHash = $data['tx_hash'];
$orderId = $data['custom_data']['order_id'] ?? $paymentId;
// Update your database
$pdo->prepare("UPDATE orders SET status='paid', tx_hash=? WHERE order_id=?")
->execute([$txHash, $orderId]);
}
http_response_code(200);
echo json_encode(['status' => 'success']);
?>
<?php
// app/Http/Controllers/WebhookController.php
public function handle(Request $request)
{
$rawPayload = $request->getContent();
$signature = $request->header('x-razcrypto-signature', '');
$secret = config('services.razcrypto.webhook_secret');
$expected = hash_hmac('sha256', $rawPayload, $secret);
if (!hash_equals($expected, $signature)) {
return response()->json(['error' => 'Invalid signature'], 401);
}
$data = $request->json()->all();
$event = $data['event'] ?? '';
if ($event === 'payment.completed') {
$orderId = $data['custom_data']['order_id'] ?? null;
if ($orderId) {
Order::where('id', $orderId)->update([
'status' => 'paid',
'payment_id' => $data['payment_id'],
'tx_hash' => $data['tx_hash'],
'paid_at' => now(),
]);
}
}
return response()->json(['status' => 'success']);
}
?>
const express = require('express');
const crypto = require('crypto');
const app = express();
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const payload = req.body.toString('utf8');
const signature = req.headers['x-razcrypto-signature'] || '';
const secret = process.env.RAZ_WEBHOOK_SECRET;
const expected = crypto.createHmac('sha256', secret).update(payload).digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature))) {
return res.status(401).json({ error: 'Invalid signature' });
}
const data = JSON.parse(payload);
const event = data.event;
if (event === 'payment.completed') {
const orderId = data.custom_data?.order_id;
// db.query('UPDATE orders SET status=paid WHERE id=?', [orderId])
console.log('Paid:', orderId, 'tx:', data.tx_hash);
}
res.status(200).json({ status: 'ok' });
});
import hmac, hashlib, json, os
from flask import Flask, request, jsonify
app = Flask(__name__)
SECRET = os.getenv('RAZ_WEBHOOK_SECRET', '')
@app.route('/webhook', methods=['POST'])
def webhook():
payload = request.get_data(as_text=True)
signature = request.headers.get('X-Razcrypto-Signature', '')
expected = hmac.new(SECRET.encode(), payload.encode(), hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, signature):
return jsonify({'error': 'Invalid signature'}), 401
data = json.loads(payload)
event = data.get('event')
if event == 'payment.completed':
order_id = data.get('custom_data', {}).get('order_id')
tx_hash = data.get('tx_hash')
print(f'Order {order_id} paid — tx: {tx_hash}')
# Update your database here
return jsonify({'status': 'success'})