Webhook Event Verification

Asuring the message integrity

Webhook events can optionally have their content integrity and authenticity verified, using a signature present in the headers.

The verification process occurs when the integrator is capable of reproducing the generation technique and obtaining the same signature as the one received in the message.

This procedure ensures that the original message content has not been corrupted and that the encryption key used in the operation is the only one known by both teams.

Below are the details on how to implement this verification.


Step 1: Encryption Key

PagFast shares an encryption key with each of its integrators, which is used to sign the sent messages.

For convenience, this key can be generated by the integrator in the administrative panel, via the Webhooks Preferences Menu

The Integration > Webhook Preferences Menu.

Integration > Webhook Preferences Menu.

If the key does not exist or if you want to change the existing one, request the generation of a new key by clicking[Create new]button. Press[Save]button to confirm, or leave the screen to keep the previous key.

In this example, the generated key is presented below and will be used later in this tutorial:

  • bf8867f612a34346a57d4e1c5e98b1ecc53defe3cccc4b7b8ea72dfbcf74a349

The saved key will be crucial for validating the content of the messages your system receives from PagFast. If you create and save a new key, update it in your system .

If you find it dificult to generate the key, PagFast team can generate the key and provide it to you.


Step 2: Validating the Message Content

To explain the validation of a message, let's consider its structure, below:

HeadersContent
Content-Typeapplication/json
X-Webhook-SignatureHMAC-SHA256 Sign=5D90499D59FB0D9FAD44A15112936CFCABA73A6EE666AAA63B60A0FC03F40EA5,
Nonce=b7891a74-ca9a-4770-bedd-8fd8341b122b,TS=1684633816
BodyContent
{"id":"f6431a0f-970a-4be9-9c6d-f444f729adc3","transactionState":"Completed",
"transactionDate":"2023-05-19T19:51:21.320Z","transactionAmount":"0.010000",
"transactionType":"Credit","transactionPaymentType":"PIX","payer":{"name":"Johnny Boy","taxNumber":"09977799400"}}

A signed message has a payload in conventional JSON format. However, a field called X-Webhook-Signature is added to the message headers. This field provides both the signature itself (Sign) and the data required to replicate it, such as Nonce and TS (Timestamp).


To replicate the signature, the integrator must follow steps bellow.

Build a string that combines the X-Webhook-Signature fields: Nonce, TS, and the information from the body content, separated by a colon :.

Using the example message presented before, we have:

From the Header:

  • Nonce = b7891a74-ca9a-4770-bedd-8fd8341b122b
  • TS = 1684633816

From the Body:

  • {"id":"f6431a0f-970a-4be9-9c6d-f444f729adc3","transactionState":"Completed","transactionDate":"2023-05-19T19:51:21.320Z","transactionAmount":"0.010000","transactionType":"Credit","transactionPaymentType":"PIX","payer":{"name":"Johnny Boy","taxNumber":"09977799400"}}

Thus, the concatenated string has the following format:

  • b7891a74-ca9a-4770-bedd-8fd8341b122b:1684633816:{"id":"f6431a0f-970a-4be9-9c6d-f444f729adc3","transactionState":"Completed","transactionDate":"2023-05-19T19:51:21.320Z","transactionAmount":"0.010000","transactionType":"Credit","transactionPaymentType":"PIX","payer":{"name":"Johnny Boy","taxNumber":"09977799400"}}

Apply an HMAC generation algorithm with the SHA256 hash generation algorithm with two parameters: the string described above, as message; and the key generated in the administrative panel, as key.

For this purpose, you can use for instance the crypto library, as in the Javascript example bellow:

const crypto = require('crypto');

const message = `b7891a74-ca9a-4770-bedd-8fd8341b122b:1684633816:{"id":"f6431a0f-970a-4be9-9c6d-f444f729adc3","transactionState":"Completed","transactionDate":"2023-05-19T19:51:21.320Z","transactionAmount":"0.010000","transactionType":"Credit","transactionPaymentType":"PIX","payer":{"name":"Johnny Boy","taxNumber":"09977799400"}}`;
const key = "bf8867f612a34346a57d4e1c5e98b1ecc53defe3cccc4b7b8ea72dfbcf74a349";
const algorithm = 'sha256';

const hmac = crypto.createHmac(algorithm, key);
hmac.update(message);

const signature = hmac.digest('hex');
console.log(signature.toUpperCase());

If everything is correct, the generated signature should be as follows:

  • 5D90499D59FB0D9FAD44A15112936CFCABA73A6EE666AAA63B60A0FC03F40EA5

This signature should match the Sign field in X-Webhook-Signature, ensuring the integrity of the received message.


What’s Next