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
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:
Headers | Content |
---|---|
Content-Type | application/json |
X-Webhook-Signature | HMAC-SHA256 Sign=5D90499D59FB0D9FAD44A15112936CFCABA73A6EE666AAA63B60A0FC03F40EA5, Nonce=b7891a74-ca9a-4770-bedd-8fd8341b122b,TS=1684633816 |
Body | Content |
---|---|
{"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.
Updated over 1 year ago