Webhooks
With webhooks your system can subscribe to updates from Walley. By registrating one or many URLs at Walley, we can call it when we need to update you with new information.
Use Webhooksβ
Currently the webhook functionality is in preview mode and may change before general availability
Step 1. Expose an HTTPS endpointβ
To receive webhooks you are required to have an HTTPS endpoint.
Endpoint requirements
- Must listen to HTTP POST method
- Must be able to receive JSON body
- Must support HTTPS with TSL 1.2 or 1.3
Endpoint recommendations
- Basic authentication with username or password
- Support for HTTP2
- Validating the Walley-Signature header with HMAC key
Step 2. Accept webhooksβ
When you receive a webhook request you are required to respond with a http status code in the 2xx series.
Step 3. Configure webhooks in Walley Merchant Hubβ
To view webhook management in Merchant Hub, click here: Merchant Hub - Webhooks
Step 4. Test and enable for Productionβ
Not available right now.
Structureβ
You will receive a request body formated in JSON which will contain a type property with the name of the event, the timestamp when the event occured and a payload that can be diffrent for each event.
{
"type": string,
"timestamp": date,
"payload": object
}
Eventsβ
Events are grouped into these categories:
Headersβ
These headers will be included in the webhook requests
Key | Description |
---|---|
User-Agent | Standard http header the value would be something like, Walleybot 0.1 (+https://dev.walleypay.com) |
Walley-CorrelationId | The id of the request that triggered the webhook request, if you have issues with any request please provide this value in the support ticket. |
Walley-Timestamp | UNIX timestamp when this event occured, this is used for HMAC validation see below. |
Walley-Signature | Computed signature from Walley, this is used for HMAC validation see below. |
Walley-Live | True or False , this is used to know if the request to the webhook is made from Walleys production or a test triggered from the MerchantHub. True indicates production data. |
Verifying the request with HMACβ
When you set up a webhook, you'll get a HMAC key for it. You can use this key to check that requests you retrieve originates from Walley by using the follow method:
- Retrive the request header
Walley-Timestamp
- Concatenate the version number, the timestamp, and the body of the request to form a basestring. Use a semicolon as the delimiter between the three elements. The version number right now is always
v0
. Exampelv0:{Timestamp};{Body}
- Hash the string described above with the HMAC SHA256 implementation of you systems platform, using the HMAC secret for the webhook.
- Compare the computed signature with the request header
Walley-Signature
Examplesβ
- C#
- Node.js
- PHP
static string ComputeHash(string secret, string timestamp, string payload)
{
byte[] bytes = Encoding.UTF8.GetBytes(secret);
HMACSHA256 hmac = new HMACSHA256(bytes);
bytes = Encoding.UTF8.GetBytes($"v0;{timestamp};{payload}");
return Convert.ToHexString(hmac.ComputeHash(bytes)).ToLower();
}
static bool IsHashValid(string secret, string timestamp, string payload, string verify)
{
string hash = ComputeHash(secret, timestamp, payload);
ReadOnlySpan<byte> hashBytes = Convert.FromHexString(hash);
ReadOnlySpan<byte> verifyBytes = Convert.FromHexString(verify);
return CryptographicOperations.FixedTimeEquals(hashBytes, verifyBytes);
}
const computeHash = (secret, timestamp, payload) => {
const hmac = crypto.createHmac('sha256', secret);
hmac.write(`v0;${timestamp};${payload}`);
hmac.end();
return hmac.read().toString('hex');
};
const isHashValid = (secret, timestamp, payload, verify) => {
return crypto.timingSafeEqual(Buffer.from(verify, 'hex'), Buffer.from(computeHash(secret, timestamp, payload), 'hex'));
};
function computeHash($secret, $timestamp, $payload) {
$bytes = utf8_encode($secret);
$hmac = hash_hmac('sha256', "v0;$timestamp;$payload", $bytes, true);
return bin2hex($hmac);
}
function isHashValid($secret, $timestamp, $payload, $verify) {
$hash = computeHash($secret, $timestamp, $payload);
$hashBytes = hex2bin($hash);
$verifyBytes = hex2bin($verify);
return hash_equals($hashBytes, $verifyBytes);
}