Webhook Integration

Learn how to set up webhooks to receive real-time notifications about payment events and transaction updates.

What are Webhooks?

Webhooks are HTTP callbacks that notify your application when specific events occur in your Gafiapay account. Instead of polling our API for updates, webhooks push data to your server in real-time.

Supported Events

Event Description Triggered When
payment.success Payment completed successfully A payment is confirmed and processed
payment.failed Payment failed A payment attempt fails
account.created Virtual account created A new virtual account is generated

Setting Up Webhooks

Step-by-Step Setup

1

Create Webhook Endpoint

Create a public HTTPS endpoint on your server to receive webhook notifications.

2

Configure in Dashboard

Go to Settings → Webhook Settings in the Gafiapay dashboard and add your webhook URL to update your webhook configuration.

Webhook Payload Structure

All webhook payloads follow a consistent structure:

{
  "data": {
    "transaction": {
      "id": "68a990e4917e8283a1351fc6",
      "orderNo": "MI1959193613179124912",
      "email": "user@domain.com",
      "amount": 1000,
      "currency": "NGN",
      "status": "completed",
      "charges": {
        "amount": 0.1,
        "type": "payment",
        "percentage": 1
      },
      "metadata": {
        "payerAccountName": "John Doe",
        "payerAccountNo": "9023456789",
        "payerBankName": "PALMPAY",
        "virtualAccountNo": "669634239",
        "createdTime": "2025-08-23T09:58:52.096Z",
        "updateTime": "2025-08-23T09:58:52.096Z",
        "grossAmount": 10,
        "netAmount": 9.9,
        "chargeAmount": 0.1,
        "chargePercentage": 1,
        "chargeType": "percentage"
      },
      "description": "incoming payment of NGN1000 from Johndoe (PALMPAY)"
    }
  }
}

Webhook Security

🔐 IP Whitelist

Webhooks are only accepted from whitelisted IP addresses for security.

✅ Signature Verification

Each webhook includes a signature header that must be verified using HMAC SHA256.

⏱️ Timestamp Validation

Webhooks include a timestamp header for additional security validation.

Implementation Examples

Code Examples

Select your preferred programming language to view the implementation

JavaScript Example

const express = require('express');
const crypto = require('crypto');

const app = express();
app.use(express.json());

const WEBHOOK_SECRET = process.env.GAFIAPAY_SECRET_KEY;
const ALLOWED_IPS = ['38.242.149.154'];

app.post('/webhook', (req, res) => {
  const signature = req.headers['x-signature'];
  const ip_address = req.headers['x-forwarded-for'] || req.ip;
  const timestamp = req.headers['x-timestamp'];
  const payload = req.body;
  
  // Validate IP address
  if (!ALLOWED_IPS.includes(ip_address)) {
    console.log('Invalid IP address:', ip_address);
    return res.status(403).send('Permission denied, invalid IP address');
  }
  
  // Verify signature
  const expectedSignature = crypto
    .createHmac('sha256', WEBHOOK_SECRET)
    .update(timestamp)
    .digest('hex');
  
  if (signature !== expectedSignature) {
    return res.status(403).send('Invalid signature');
  }
  
  // Process webhook
  const { data } = payload;
  const { transaction } = data;
  
  console.log('Payment received:', {
    id: transaction.id,
    orderNo: transaction.orderNo,
    email: transaction.email,
    amount: transaction.amount,
    currency: transaction.currency,
    status: transaction.status,
    charges: transaction.charges,
    metadata: transaction.metadata,
    description: transaction.description
  });
  
  // Update user balance and create transaction record
  // Your business logic here
  
  res.status(200).send('Transaction received successfully');
});

app.listen(3000, () => {
  console.log('Webhook server running on port 3000');
});

Required Headers

Your webhook endpoint must validate these headers:

Header Description Example
x-signature HMAC SHA256 signature for verification abc123...
x-timestamp Timestamp used in signature generation 1647768600
x-forwarded-for Client IP address for validation 38.242.149.154

Testing Webhooks

You can test your webhook endpoint using tools like ngrok:

# Using ngrok to expose local server
ngrok http 3000

# Your webhook URL will be something like:
# https://abc123.ngrok.io/webhook

Troubleshooting

Webhook Not Received

  • Verify your webhook URL is publicly accessible
  • Check that your server is running and responding
  • Ensure your webhook endpoint accepts POST requests
  • Check your server logs for any errors

Signature Verification Failed

  • Verify you're using the correct webhook secret
  • Ensure you're reading the raw request body
  • Check that your signature generation matches our algorithm

IP Validation Failed

  • Ensure your server can receive the correct IP address
  • Check if you're behind a proxy or load balancer
  • Verify the IP address matches our whitelist