1
Create an HTTP endpoint to receive webhook requests.
This endpoint must accept
POST requests such as the one below:- URL:
https://website.com/webhook_payment(HTTPS is mandatory) - METHOD:
POST - HEADERS:
- BODY:
Click to show.
Click to show.
This is an example of a webhook sent for a
payment_intent.created event. The data field holds the object concerned by the event, owner is your merchant ID and id identifies the event.2
Register this endpoint with the HUB2 API and subscribe to events.
The HUB2 API provides a dedicated endpoint for this action. Call it with the following body:
Code samples:The webhook is created in the environment (
Store the secret securely: you need it to verify the integrity of every webhook you receive.For more details, see the webhooks API reference: Create a webhook.
Click to show.
Click to show.
live or sandbox) given in the Environment header. The HUB2 API responds with HTTP 201 and a body such as:Click to show.
Click to show.
This response contains the secret associated with the webhook:
"secret": "whsec_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX". It is returned only once, at creation.3
Verify the webhook signature.
To make sure a webhook comes from the HUB2 API, check the signature of its body (payload).Sign the raw body as received, before any parsing. Parsing the JSON and serializing it again can change the string (spacing, key order, character escaping) and produce a different signature.
a. Get the secret of the webhook.
This secret was returned in step 2 ("secret": "whsec_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" in the example).b. Sign the payload.
Take the body of thePOST request sent by HUB2 (see step 1) as a string, exactly as received, and compute its HMAC-SHA256 with the secret as key, encoded in lowercase hexadecimal.Examples by programming language:c. Check the signature.
Finally, compare the computed signature with the one sent by HUB2 in the request headers:Hub2-Signature: header name (HTTP header names are case-insensitive).s1: signature computed with the currentsecret.s0: signature computed with the previous secret, if there is one. Otherwise,s0is empty.
s1, or s0 during a secret rotation. Use a constant-time comparison function where your language provides one.