Receiving payment notifications with webhooks
Listen for payment notifications across the payment's lifecycle to automatically trigger reactions.
Webhooks are used to listen to payment notifications across a payment's lifecycle.
How receiving payment notifications with webhooks works
1. Supported scenarios
Scenario | Notes |
---|---|
Pay with Setel code scan (Not supported) | Webhook is not supported. |
Pay with Setel online | Webhook can be set upon creation of the checkout session. |
Considerations for webhooks
Due to network issues, there might be cases where the webhook requests might not be received by integrators. A retry query using the retrieve a checkout session API is recommended for this situation.
Multiple webhook requests for a single order might be sent. Please ensure there is an implementation to verify which request is the latest.
2. Subscribing to a webhook
You will need to define the webhook
URL when creating a checkout session. This URL will be used to receive updates on the payment sessions.
2.1 Webhook request payload
"headers": {
"Content-Type": "application/json",
"signature": "random string"
}
{
'id': 'test-id',
'createdAt': '2021-06-09T10:09:37.927Z',
'updatedAt': '2021-06-09T10:09:37.927Z',
'apiKey': 'test-x-api-key',
'paymentIntentId': 'test-payment-intent-id',
'paymentIntentStatus': 'succeeded',
'amount': '10',
'referenceId': 'test-reference-id',
}
3. Signature
A signature is used to verify the identity of the request/data sent. This is needed to prevent information from being stolen or received from the wrong entity.
3.1 How to generate a signature
- Step 1: Get the
secretHash
fromx-api-secret
. - Step 2: Calculate
data
by concatenating fields in above order. - Step 3: Get
signature
by hmac('sha256',secretHash
)(data
).
3.2 Sample code in NodeJS
const { createHmac, createHash } = require('crypto');
const secret = 'test-x-api-secret';
const secretHash = createHash('sha256').update(secret).digest('hex');
console.log(secretHash);
// secretHash: 874d70d91c89cfa556797c1754ea186e060a189a0cc398b000f94630c1b1674e
const body = {
'id': 'test-id',
'createdAt': '2021-06-09T10:09:37.927Z',
'updatedAt': '2021-06-09T10:09:37.927Z',
'apiKey': 'test-x-api-key',
'paymentIntentId': 'test-payment-intent-id',
'paymentIntentStatus': 'succeeded',
'amount': '10',
'referenceId': 'test-reference-id',
};
const fields = [
'id',
'createdAt',
'updatedAt',
'apiKey',
'paymentIntentId',
'paymentIntentStatus',
'amount',
'referenceId',
];
let data = '';
fields.forEach(field => data += body[field] || '');
console.log(data);
// data: test-id2021-06-09T10:09:37.927Z2021-06-09T10:09:37.927Ztest-x-api-keytest-payment-intent-idsucceeded10test-reference-id
const hmac = createHmac('sha256', secretHash).update(data).digest('hex');
console.log(hmac);
// hmac: 77b928780f10a0d2339d93be7319eda4dda4472d5a9fdf7bcc53768a2a61faf0
3.3 Sample input and output
3.3.1 Input
Name | Value |
---|---|
x-api-secret | test-x-api-secret |
body | { 'id': 'test-id', 'createdAt': '2021-06-09T10:09:37.927Z', 'updatedAt': '2021-06-09T10:09:37.927Z', 'apiKey': 'test-x-api-key', 'paymentIntentId': 'test-payment-intent-id', 'paymentIntentStatus': 'succeeded', 'amount': '10', 'referenceId': 'test-reference-id', } |
3.3.2 Output
77b928780f10a0d2339d93be7319eda4dda4472d5a9fdf7bcc53768a2a61faf0
Updated over 1 year ago