🔏Virtual / Dynamic Account Webhook
Webhooks are a powerful feature of the Xixapay API that allow your application to receive real-time notifications about events that occur on the Xixapay platform. Instead of polling the API for updates (which can be resource-intensive), you can use webhooks to automatically receive data about important events like successful payments, payment failures, refunds, and more.
In this section, we will walk you through the process of setting up webhooks, handling incoming webhook notifications, and troubleshooting common issues.
Webhook Notification Format
The webhook will send a JSON payload to your endpoint, with the following structure:
// notificaton json format
{
"notification_status": "payment_successful",
"transaction_id": "xxx",
"amount_paid": 100,
"settlement_amount": 99.5,
"settlement_fee": 0.5,
"transaction_status": "success",
"sender": {
"name": "A D E LIMITED",
"account_number": "****4290",
"bank": "HYDROGEN"
},
"receiver": {
"name": "adex-Abd(xixapay)",
"account_number": "667985",
"bank": "PalmPay"
},
"customer": {
"name": "adex dev",
"email": "[email protected],
"phone": null,
"customer_id": "xxx"
},
"description": "Your payment has been successfully processed.",
"timestamp": "2024-11-22T13:00:04.256092Z"
}Field Descriptions
Field
Description
notification_status
The status of the notification. In this case, it indicates that the payment was successful.
transaction_id
A unique identifier for the transaction. This ID can be used to track the transaction in your system.
amount_paid
The total amount paid by the customer (e.g., 100 units of the selected currency).
settlement_amount
The amount that will be settled to the receiver, after any fees are deducted (e.g., 99.5 units).
settlement_fee
The fee charged by the payment processor or Xixapay for the transaction (e.g., 0.5 units).
transaction_status
The status of the transaction. In this case, "success" indicates the transaction was completed successfully.
sender.name
The name of the sender or the business initiating the payment (e.g., "AGH ONLINE ACADEMY TUTORS LIMITED").
sender.account_number
The masked account number of the sender (last 4 digits are shown).
sender.bank
The bank name associated with the sender (e.g., "HYDROGEN").
receiver.name
The name of the receiver, which could be your business or another entity (e.g., "ALBARKADATASUB-Abd(Paymentpoint)").
receiver.account_number
The account number associated with the receiver (e.g., "6679854996").
receiver.bank
The bank name associated with the receiver (e.g., "PalmPay").
customer.name
The name of the customer who made the payment (e.g., "Abdulismail").
customer.email
The email address of the customer (e.g., "[email protected]").
customer.phone
The phone number of the customer. In this case, it's null, indicating no phone number was provided.
customer.customer_id
The unique customer ID assigned by your system (e.g., "xxx").
description
A brief description of the transaction (e.g., "Your payment has been successfully processed.").
timestamp
The timestamp of when the event occurred, formatted in ISO 8601 format (e.g., "2024-11-22T13:00:04.256092Z").
Webhook Signature Verification
To ensure the authenticity and integrity of the webhook data, Xixapay includes a signature in the request header for every webhook notification sent. This signature is generated by Xixapay using your secret security key and the webhook payload.
1. Verifying the Webhook Signature
When you receive a webhook, you need to:
Retrieve the payload sent by Xixapay in the request body.
Retrieve the xixapay header, which contains the expected signature for the webhook.
Hash the payload with your secret security key using the same hashing algorithm Xixapay uses (usually HMAC-SHA256).
Compare the computed signature with the one sent in the xixapay header.
If the signatures match, you can be confident that the webhook is authentic and hasn't been tampered with
2. Signature Verification in Different Languages
Here’s how to implement the signature verification in PHP, Python, and Node.js.
<?php
// Retrieve the raw POST body and headers
$payload = file_get_contents('php://input');
$signatureHeader = $_SERVER['HTTP_XIXAPAY']; // xixapay signature header
// Your Xixapay secret security key
$secretKey = 'your-secret-key'; // Replace with your actual secret key
// Calculate the expected signature using HMAC-SHA256
$calculatedSignature = hash_hmac('sha256', $payload, $secretKey);
// Compare the calculated signature with the one from the xixapay header
if (hash_equals($calculatedSignature, $signatureHeader)) {
// Signature is valid, proceed with handling the webhook
echo "Webhook signature is valid!";
// Process the payload (decode JSON, handle business logic)
$data = json_decode($payload, true);
// Example: Process the data (e.g., update database)
} else {
// Signature is invalid, reject the request
header('HTTP/1.1 400 Bad Request');
echo "Invalid signature!";
}
?>
import hmac
import hashlib
import json
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.conf import settings
# Your Xixapay secret security key (set this in your settings)
SECRET_KEY = "" # Add your secret key in xixapay
@csrf_exempt
def webhook(request):
if request.method == 'POST':
# Get the payload (raw body)
payload = request.body
# Get the signature from the header (xixapay)
signature_header = request.headers.get('xixapay')
if not signature_header:
return JsonResponse({'error': 'No signature header'}, status=400)
# Calculate the HMAC signature using SHA-256
calculated_signature = hmac.new(
SECRET_KEY.encode(), payload, hashlib.sha256
).hexdigest()
# Compare the calculated signature with the one from the xixapay header
if hmac.compare_digest(calculated_signature, signature_header):
# Signature is valid, process the webhook data
data = json.loads(payload)
print("Webhook received:", data)
# Do your processing here (e.g., update database, send email, etc.)
return JsonResponse({'status': 'success'}, status=200)
else:
# Signature mismatch
return JsonResponse({'error': 'Invalid signature'}, status=400)
else:
return JsonResponse({'error': 'Invalid HTTP method'}, status=405)
// Some code
const express = require('express');
const crypto = require('crypto');
const bodyParser = require('body-parser');
const app = express();
const secretKey = 'your-secret-key'; // Replace with your actual secret key
// Middleware to parse incoming JSON payload
app.use(bodyParser.json());
app.post('/webhook', (req, res) => {
// Retrieve the raw POST body and signature header
const payload = JSON.stringify(req.body); // Ensure the body is a JSON string
const signatureHeader = req.headers['xixapay']; // xixapay signature header
// Calculate the HMAC signature using SHA-256
const calculatedSignature = crypto.createHmac('sha256', secretKey).update(payload).digest('hex');
// Compare the calculated signature with the one from the xixapay header
if (calculatedSignature === signatureHeader) {
// Signature is valid, process the webhook
console.log("Webhook signature is valid!");
// Example: Process the data (e.g., update database)
res.status(200).send('Webhook received');
} else {
// Signature is invalid, reject the request
res.status(400).send('Invalid signature');
}
});
// Start the server
app.listen(3000, () => {
console.log('Server listening on port 3000');
});
Last updated