Webhook security
We do recommend implementing a list of security tips to ensure the security of your server:
- Ignore all the message not coming from these ranges of IP:
- PROD : 35.159.7.141/32
- PREPROD : 18.197.251.96/32
- Ignore all the messages not having this signature header
slimpay-signature
- Ignore all the messages for which the signature header
slimpay-signature
does not contain both t and v1 subparameters - Compare the v1 value with your signature computation. See below.
- You can ignore all the message with a timestamp
t
too old. In addition to comparing the signatures, the timestamp can be used to discard messages older than a set threshold. Consider keeping the threshold at no less than 5 minutes.
The computation of v1
is simplified by using the following algorithm:
Compute an HMAC with the SHA256 hash function.
The signed_payload (dataToSign) string is created by concatenating:
- The timestamp (as a string)
- The character
:
- The actual JSON payload (that is, the request body)
To simplify the implementation we are providing you some code below:
JAVA
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
public class HmacSha256 {
public static String calculateHMAC_SHA256(String data, String key) {
try {
final SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "HmacSHA256");
final Mac mac = Mac.getInstance("HmacSHA256");
mac.init(secretKey);
final byte[] hmacData = mac.doFinal(data.getBytes());
// Convert the byte array to a hexadecimal string
final StringBuilder hexChars = new StringBuilder();
for (byte b : hmacData) {
hexChars.append(String.format("%02x", b));
}
return hexChars.toString();
} catch (Exception e) {
throw new RuntimeException("Error calculating HMAC: " + e.getMessage(), e);
}
}
public static void main(String[] args) {
String secretKey = "b[VQm?-]F0!{=sIXftL=xHiAVwVsr]R#(Y@XDw}d+jtI_ap*[fX$Bky6aMF?p5)G";
String dataToHash = "1697188825898:{\"id\":\"cc480206-97ae-4fc1-8824-3b9a886eb50f\",\"version\":1,\"createdAt\":1697188825263,\"eventType\":\"payment_slimcollectpay.update\",\"data\":{\"uuid\":\"88d54b14-d94e-432a-bfbd-f082b88c4c0d\",\"status\":\"PROCESSED\",\"code\":10006,\"statusMessage\":\"Your payment is available in your bank account\"}}";
String hmacSHA256 = calculateHMAC_SHA256(dataToHash, secretKey);
System.out.println("Expected : " + "22dd211c188bf67152eb05695795db57d2de0eff745f110dd2fc3982cdfa1f9a");
System.out.println("HMAC-SHA256: " + hmacSHA256);
}
}
PYTHON
import hmac
import hashlib
def calculate_hmac_sha256(data, key):
key = key.encode('utf-8')
data = data.encode('utf-8')
hmac_hash = hmac.new(key, data, hashlib.sha256)
return hmac_hash.hexdigest()
if __name__ == '__main__':
secret_key = "b[VQm?-]F0!{=sIXftL=xHiAVwVsr]R#(Y@XDw}d+jtI_ap*[fX$Bky6aMF?p5)G"
data_to_hash = "1697188825898:{"id":"cc480206-97ae-4fc1-8824-3b9a886eb50f","version":1,"createdAt":1697188825263,"eventType":"payment_slimcollectpay.update","data":{"uuid":"88d54b14-d94e-432a-bfbd-f082b88c4c0d","status":"PROCESSED","code":10006,"statusMessage":"Your payment is available in your bank account"}}"
hmac_sha256 = calculate_hmac_sha256(data_to_hash, secret_key)
print("Expected : " + "22dd211c188bf67152eb05695795db57d2de0eff745f110dd2fc3982cdfa1f9a");
print("HMAC-SHA256: " + hmac_sha256);
KOTLIN
val dataToSign = """
1697188825898:{"id":"cc480206-97ae-4fc1-8824-3b9a886eb50f","version":1,"createdAt":1697188825263,"eventType":"payment_slimcollectpay.update","data":{"uuid":"88d54b14-d94e-432a-bfbd-f082b88c4c0d","status":"PROCESSED","code":10006,"statusMessage":"Your payment is available in your bank account"}}
""".trimIndent()
val expectedResult = "22dd211c188bf67152eb05695795db57d2de0eff745f110dd2fc3982cdfa1f9a"
// b[VQm?-]F0!{=sIXftL=xHiAVwVsr]R#(Y@XDw}d+jtI_ap*[fX$Bky6aMF?p5)G
val secret = "b[VQm?-]F0!{=sIXftL=xHiAVwVsr]R#(Y@XDw}d+jtI_ap*[fX\$Bky6aMF?p5)G"
val secretKey = SecretKeySpec(secret.toByteArray(), "HmacSHA256")
val mac = Mac.getInstance("HmacSHA256")
mac.init(secretKey)
val hmacData = mac.doFinal(dataToSign.toByteArray())
// Convert the byte array to a hexadecimal string
val hexChars = StringBuilder()
for (byte in hmacData) {
hexChars.append(String.format("%02x", byte))
}
println(expectedResult)
println(hexChars.toString())