Verifying webhook events come from Fintava is necessary to avoid creating transactions due to a fraudulent event. To verify events, validate the x-fintava-signature header sent with the event
Important Security Notes:
- Always verify the
x-fintava-signatureheader before processing webhooks- Use your webhook secret from the Fintava dashboard
- Never hardcode secrets - use environment variables
- Use raw request body for signature verification (not parsed JSON)
Node.js
const express = require('express');
const crypto = require('crypto');
const app = express();
app.use(express.json({ verify: (req, res, buf) => {
req.rawBody = buf;
}}));
app.post("/webhook_url", function(req, res) {
const webhookSecret = process.env.WEBHOOK_SECRET;
// Validate signature
const hash = crypto
.createHmac('sha512', webhookSecret)
.update(req.rawBody) // Use raw body for exact match
.digest('hex');
if (hash === req.headers['x-fintava-signature']) {
const event = req.body;
console.log('Webhook received:', event);
// Process the event
switch (event.type) {
case 'wallet_to_wallet_transfer_v2':
handleWalletToWallet(event.data);
break;
case 'account_funded':
handleAccountFunded(event.data);
break;
}
return res.status(200).json({ received: true });
} else {
console.error('Invalid signature');
return res.status(401).json({ error: 'Invalid signature' });
}
});
Python
from flask import Flask, request, jsonify
import hashlib
import hmac
import os
app = Flask(__name__)
@app.route('/webhook_url', methods=['POST'])
def webhook():
webhook_secret = os.environ.get('WEBHOOK_SECRET').encode()
signature = request.headers.get('x-fintava-signature')
# Generate expected signature
expected_signature = hmac.new(
webhook_secret,
request.get_data(),
hashlib.sha512
).hexdigest()
# Compare signatures securely
if hmac.compare_digest(expected_signature, signature):
event = request.json
print(f"Webhook received: {event}")
# Process event here
return jsonify({'status': 'success'}), 200
else:
return jsonify({'error': 'Invalid signature'}), 401
PHP
<?php
$webhook_secret = getenv('WEBHOOK_SECRET');
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_FINTAVA_SIGNATURE'];
// Calculate expected signature
$expected_signature = hash_hmac('sha512', $payload, $webhook_secret);
// Compare signatures (timing-safe)
if (hash_equals($expected_signature, $signature)) {
$event = json_decode($payload, true);
// Process the event
error_log("Webhook received: " . print_r($event, true));
http_response_code(200);
echo json_encode(['status' => 'success']);
} else {
http_response_code(401);
echo json_encode(['error' => 'Invalid signature']);
}
?>