Webhooks
Why to use webhooks
You can receive events to be notified about the updates in your integration in real time. Payment Gateway uses webhooks for this purpose. Webhook is a code that sends an event object to an endpoint when an API v.2 object is changed.
To enable webhook events, you need to register webhook endpoints, generate a secret to sign events, and select the events to listen to. You can configure these settings via the Personal area.
Currently, you can receive the events related to the following objects:
- Session
- Payment
- PaymentMethod
- Refund
See the whole list of supported event types.
Event overview
Each event is a POST request with JSON body, with symmetric signature with HMAC.
A single API request might result in creation of multiple events. For example, if you complete a two-step payment (make a capture), you receive payment.funded
and payment.succeeded
events.
Event header structure
Each request has the following headers:
-
X-Version
- API version in YYYY-MM-DD format (example: 2023-11-15); -
X-Signature
– signature for webhook; -
API-Request-Id
– request identifier (format: req_UUID).
Example:
-H "Content-Type: application/json" \
-H "X-Signature: your_webhook_signature" \
-H "X-Version: 2023-11-15" \
Event body structure
Event body contains the following attributes:
Attribute | Description |
---|---|
created |
Date of the event creation |
data |
Attribute for sending the snapshot of the API v.2 object |
data.object |
Attribute containing the snapshot of the API v.2 object (Payment, Session, PaymentMethod, or Refund) |
type |
Type of the sent event |
Example of the event body:
{
"created": "2022-02-17T16:30:55+00:00",
"data": {
"object": {
"id": "ps_2njmpfC9BUCfsmALYNEQv5eoR8SdVsEHuXZC7D3uLiRxqfb8g2wJzWo8UvE9QL",
"amount": 90000,
"created": "2022-02-17T16:10:54+00:00",
"currency": "EUR",
"expiresAt": "2022-02-17T16:10:54+00:00",
"failureUrl": "https://mybestmerchantreturnurl.com/failure",
"locale": "en",
"paymentData": {
"captureMethod": "automatic"
},
"paymentStatus": "unpaid",
"paymentUrl": "https://dev.bpcbt.com/payment/merchants/ecom/payment.html?mdOrder=0fbfe391-c2d1-7528-a0a9-5a4500a99ded&language=en",
"status": "expired",
"successUrl": "https://mybestmerchantreturnurl.com/success"
}
},
"type": "session.expired"
}
Event types
The following event types are supported.
API v.2 object | Event type | When is it sent |
---|---|---|
Session | session.completed | Payment via Session is completed. |
Session | session.expired | Session is expired (no payment attempts were made for the Session). |
Payment | payment.amountCapturableUpdated | Money for two-step Payment are successfully held. |
Payment | payment.canceled | Payment is canceled. |
Payment | payment.created | Payment is created. |
Payment | payment.funded | Money for two-step Payment are successfully captured. |
Payment | payment.failed | Payment attempt was unsuccessful. |
Payment | payment.succeeded | Payment was successfull. |
PaymentMethod | paymentMethod.created | Payment Method was successfully stored. |
Refund | refund.updated | Money were refunded. |
API version
The API version will be specified in X-Version
header of the event.
Why event objects get generated
The following scenarios can trigger generating event objects:
- When you do some changes via Personal Area (for example, make a refund)
- When you use API
- When a customer does something via the Payment page
How to set up your webhook integration
To start receiving webhook events, create and register a webhook endpoint by following the steps below. You can register and create one endpoint or multiple endpoints.
1. Identify the events to monitor
Use the Events types table to identify the events you want to receive.
2. Create a webhook endpoint function
Set up an HTTPS endpoint function that can accept webhook requests with a POST method. Set up your endpoint function so that it:
- Handles POST requests with a JSON payload consisting of an event object.
- Quickly returns a successful status code (2xx) prior to any complex logic that could cause a timeout. For example, you must return a 200 response before updating a customer’s invoice as paid in your accounting system.
3. Register you webhook endpoint via Personal Area
You can configure your webhook integration via your Personal area. See the details in the Merchant Portal User Guide.
When a webhook fails
If a response other than 200 OK
is returned to the Payment Gateway, sending event is considered unsuccessful. In this case, the Payment Gateway repeats sending the event at intervals of 30 seconds until one of the following conditions is met:
- the Payment Gateway receives 200 OK,
- there are 3 successive webhook failures.
When one of the above conditions is met, attempts to send an event stop.
Best practices for using webhooks
Only listen to event types your integration requires
Configure your webhook endpoints to receive only the types of events required by your integration. Listening for extra events (or all events) creates excess load on your server, so we don’t recommend it. You can change the events that a webhook endpoint receives via the Personal area.
Receive events with an HTTPS server
If you use an HTTPS URL for your webhook endpoint, Payment Gateway validates that the connection to your server is secure before sending your webhook data. For this to work, your server must be correctly configured to support HTTPS with a valid server certificate.
Verify events are sent from Payment Gateway
The X-Signature
header included in each signed event contains a timestamp and one or more signatures that you must verify. The timestamp is prefixed by t=
, and each signature is prefixed by v1=
.
Payment Gateway generates signatures using HMAC with SHA-256.
Example of the X-Signature
header:
X-Signature: t=1492774577,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
To verify the signature, follow these steps:
Step 1: Extract the timestamp and signatures from the header
Split the header using the ,
character as the separator to get a list of elements. Then split each element using the =
character as the separator to get a prefix and value pair. The value for the prefix t
corresponds to the timestamp, and v1
corresponds to the signature (or signatures).
Step 2: Prepare the signed_payload
string
The signed_payload
string is created by concatenating:
- The timestamp (as a string)
- The character
.
- The actual JSON payload (that is, the event body)
Step 3: Determine the expected signature
Compute an HMAC with the SHA256 hash function. Use the endpoint’s signing secret as the key and use the signed_payload
string as the message. The result value will be the expected signature.
Step 4: Compare the signatures
Compare the signature (or signatures) in the header to the expected signature. For an equality match, compute the difference between the current timestamp and the received timestamp, then decide if the difference is within your tolerance. To protect against timing attacks, use a constant-time-string comparison to compare the expected signature to each of the received signatures.
Use support of two signing secrets
Many companies require changing signing secret from time to time for security purpose. To make this change safely, we recommend you to use the following approach:
- When you are going to change your signing secret, first generate a new signing secret manually or using the tool of your choise (the secret should be a random string with at least 20 symbols - numbers and latin characters).
- Support two secrets: 1) the old one, 2) the new one that you have generated.
- Change the old secret to the new secret via the Personal Area (enter it in the Signing secret field and click Save).
- Make sure that the received events are correctly verified by the new secret. If something goes wrong, change the secret back to the old one.
- If everything works correctly, delete the old secret from your systems.