This feature is supported from Notifications v5 and later.
For information about platform integrations built after August 1, 2022, refer to our new integration guide instead.
By default, Adyen notifications use basic authentication. You can optionally enable Hash-based Message Authentication Code (HMAC) signatures, which adds an extra layer of security to your standard notifications.
An HMAC signature is calculated using a request's key-value pairs and a secret key, which is known only to you and the Adyen payments platform. By verifying this signature, you'll confirm that the notification was not modified during transmission.
Enable HMAC signatures
You can use any 32bit hexadecimal HMAC key you like. If you subscribe to payment notifications you can reuse the same key. For more information, see Signing notifications with HMAC.
If you generate a new HMAC key, your previous notifications will still be signed with your previous HMAC key.
Subscribe to notifications
Subscribe to notifications with a HMAC Signature Key to receive HMAC signed notifications to the URL you specify in the /createNotificationConfiguration
call. We activate the ACCOUNT_HOLDER_VERIFICATION notification and send it to the endpoint on your server (https://www.merchant-domain.com/notification-handler) using the specified connection credentials (testUserName and testPassword).
Verify HMAC signature
To verify the signature, retrieve the values of the HmacSignature
and Protocol
parameters from the HTTP header of the incoming notification. HmacSignature
contains the signature itself and Protocol
is the protocol used to create the signature (only SHA256 is supported).
To compute the HMAC signature, apply the algorithm/protocol to the whole HTTP body using the key. If the computed HMAC signature is equal to the one in the header, the verification is successful.
Perform this check before deserializing the request. If you perform deserialization before verifying, a valid signature may fail due to a different order of the JSON elements
HMAC signature examples
To calculate the HMAC signature:
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
public class MarketplaceNotificationHmacExampleTest {
@Test
public void testMarketplaceNotificationHmac() {
// Example HEX Key (submitted at the moment of subscription)
String hmacSignatureKey = "79A3EAF309C43708726A8C284C0D72618696A12E840DFA1DF3A158AFA3B577DA";
// Signature. Retrieved from HTTP header under the name HmacSignature.
String hmacSignature = "A2bHr0WPlKg1fJLVEDReVAdUDWt3znmsuYvp2KdihXY=";
// Protocol. Retrieved from HTTP header under the name Protocol.
String protocol = "HmacSHA256";
// Payload. the payload of the notification consists on the whole body of the notification
String payload = "{\"eventDate\":\"2018-07-09T12:07:27+02:00\",\"eventType\":\"ACCOUNT_HOLDER_CREATED\",\"executingUserKey\":\"ws\",\"live\":false,\"pspReference\":\"9915311308462016\","
+ "\"content\":{\"invalidFields\":[],\"pspReference\":\"9915311308462016\",\"accountCode\":\"9915311308462024\",\"accountHolderCode\":\"6750d8cf-80ab-4a34-b2c5-f8a1f37a79da\","
+ "\"accountHolderDetails\":{\"bankAccountDetails\":[],\"email\":\"testEmail@gmail.com\",\"individualDetails\":{\"name\":{\"firstName\":\"TestFirstName\",\"gender\":\"MALE\","
+ "\"lastName\":\"TestData\"}},\"merchantCategoryCode\":\"7999\"},\"accountHolderStatus\":{\"status\":\"Active\",\"processingState\":{\"disabled\":false,"
+ "\"processedFrom\":{\"currency\":\"EUR\",\"value\":0},\"processedTo\":{\"currency\":\"EUR\",\"value\":0},\"tierNumber\":0},\"payoutState\":{\"allowPayout\":false,"
+ "\"disabled\":false,\"tierNumber\":0},\"events\":[]},\"legalEntity\":\"Individual\",\"verification\":{}}}";
try {
// decode HEX Key into bytes
byte[] keyBytes = new BigInteger(hmacSignatureKey, 16).toByteArray();
// get payload in bytes
byte[] payloadBytes = payload.getBytes(StandardCharsets.UTF_8);
// instantiate the MAC object using HMAC / SHA256
Mac hmacSha256 = Mac.getInstance(protocol);
// create a key object using the secret key and MAC object
SecretKey secretKey = new SecretKeySpec(keyBytes, hmacSha256.getAlgorithm());
// initialise the MAC object
hmacSha256.init(secretKey);
// finalise the MAC operation
byte[] signedPayload = hmacSha256.doFinal(payloadBytes);
// encode the signed payload in Base64
byte[] encodedSignedPayload = Base64.getEncoder().encode(signedPayload);
System.out.println("original HMAC signature: " + hmacSignature);
System.out.println("computed HMAC signature: " + new String(encodedSignedPayload, StandardCharsets.US_ASCII));
// assert the calculated Base64 encoded HMAC is equal to the received Base64 encoded HMAC
Assertions.assertArrayEquals(encodedSignedPayload, hmacSignature.getBytes(StandardCharsets.UTF_8));
} catch (NoSuchAlgorithmException e) {
// HmacSHA256 should be supported
} catch (InvalidKeyException e) {
// The key is invalid
}
}
}
If the calculated HmacSignature
matches the value you received in the notification, the notification wasn't modified during transmission.
The following is an example of a header containing an HMAC signature:
[Content-Type: application/json; charset=utf-8, Authorization: Basic dGVzdFVzZXJOYW1lOnRlc3RQYXNzd29yZA==, HmacSignature: awA4ZTCAYLp/ctyt9yFPlidqZcLjWs5EZikhIQCz98k=, Protocol: HmacSHA256, Content-Length: 819, Host: localhost:57851, Connection: Keep-Alive, User-Agent: Adyen HttpClient 1.0, Accept-Encoding: gzip,deflate]