On every payment confirmation we get from the payment provider, we send the following to your webhook with us. First lets define the fields

FieldDescription
statusThis is the status of the payment. this can be success or failed or refunded in the case of payment refunds
clientIdThis is your clientId
amountThis is the amount of the transaction in kobo
chargeThis is the charge the customer paid
referenceThis is the unique reference generated by Payfonte for this transaction.
externalReferenceThis is the reference sent to us by you when initializing the transaction.
providerThis is the provider used for this transaction
channelThis is the channel for this transaction. This can be card, ussd, cryptocurrency and so on
userThis is a user object containing at least one of email, phone number or name
{
    "event": "payment.completed",
    "clientId": "payfonte",
    "data": {
        "clientId": "Payfonte",
        "reference": "Payfonte_development_1682882716958",
        "externalReference": "Payfonte_development_1682882716958",
        "platformReference": "644ec09c4c2604002fac9d17",
        "amount": 100,
        "provider": "paystack",
        "channel": "card",
        "status": "success",
        "charge": 0,
        "chargeFee": 0,
        "paymentCard": {
            "deletedAt": null,
            "first6Pan": "408408",
            "last4Pan": "4081",
            "userId": "644ec099ca0ac522ae18555e",
            "authorizationCode": "AUTH_407z0h7txb",
            "bank": "TEST BANK",
            "cardType": "visa ",
            "clientId": "Payfonte",
            "countryCode": "NG",
            "createdAt": "2023-04-30T19:37:10.605Z",
            "expiry": {
                "month": "12",
                "year": "2030"
            },
            "provider": "paystack",
            "updatedAt": "2023-04-30T19:37:10.605Z",
            "id": "644ec366821b0b8a5986bc55"
        },
        "user": {
            "name": "Payfonte",
            "email": "[email protected]"
        },
        "paidAt": 1682883430,
        "integrationLogId": "644ec35e1dd6180dd34a089e"
    }
}

Signature Verification

Given that your webhook URL is accessible to the public, it's crucial to confirm that the events are being sent from Payfonte and not from malicious entities. The header of every webhook sent to you will contain a x-webhook-signature which is a SHA512 encryption using your client-secretwhich can be found in Settings -> API Keys/Webhooks

const crypto = require('crypto');
const secret = process.env.CLIENT_SECRET;
// Using Express
app.post("/my/webhook/url", function(req, res) {
    //validate event
    const hash = crypto.createHmac('sha512', secret).update(JSON.stringify(req.body)).digest('hex');
    if (hash == req.headers['x-webook-signature']) {
    // get the request's body
    const event = req.body;
    // process this event 
    }
    res.send(200);

Webhook Order and Priority

The order of webhook priority is as follow:

  • If a webhook url is sent with the request to generate a checkout url, we will use that else
  • if a webhook url is set when creating a provider integration, we will use that
  • we will use the webhook set in the setting section of the dashboard.