Are you looking for test card numbers?

Would you like to contact support?

Atenção, esta página não se encontra disponível em Português
Classic-integration icon

HMAC signature calculation

This page is for our classic Hosted Payment Pages (HPP) integration. For information about new integrations, refer to notification webhooks instead.

To ensure authenticity and data integrity of incoming requests Adyen requires these requests to be signed. This signature is based on a Hash-based Message Authentication Code (HMAC) calculated using a request's key-value pairs and a secret key, which is known only to you and Adyen. 

Before sending a request to Adyen, you calculate a signature and add it as a request parameter. When a request comes in, Adyen calculates the same signature based on the received key-value pairs and the secret key stored by Adyen. By verifying that both signatures are equal, Adyen ensures that the request is not tampered.

Similarly, you can validate responses from Adyen by calculating the corresponding signature and comparing it with the signature in the response.

Signatures can also be used to add an extra layer of security for notifications. However, the calculation for this functionality is different. For details, refer to the Signing notifications with HMAC guide.

Getting HMAC keys

You need to generate your secret HMAC keys to use them for signature calculation. To obtain these keys for the test and live platform, follow the steps below:

  1. Log in to your Customer Area using your company-level account.

  2. From the main menu, select Account > Skins.

  3. Select an existing skin from the List tab or create a new skin by switching to the New tab.

  4. Click Generate new HMAC key both for the Test platform and Live platform. Then copy new keys and store them in a secure place in your system to access these values later.

  5. Provide a description for this skin.

  6. To save the skin click Create New Skin on Test at the page bottom.

Implementing signature calculation

In this tutorial, we use the following HMAC key and key-value pairs as an example.

Sample HMAC key:


Sample key-value pairs:

Key Value
shopperLocale en_GB
merchantReference paymentTest:143522\64\39255
sessionValidity 2018-07-25T10:31:06Z
shipBeforeDate 2018-07-30
paymentAmount 1995
currencyCode EUR
skinCode X7hsNDWp

Don't use this example key for your real integration with Adyen.

String HMAC_KEY = "44782DEF547AAA06C910C43932B1EB0C71FC68D9D0C057550C48EC2ACF6BA056";
Map<String, String> pairs = new HashMap<>();
pairs.put("shopperLocale", "en_GB");
pairs.put("merchantReference", "paymentTest:143522\\64\\39255");
pairs.put("merchantAccount", "TestMerchant");
pairs.put("sessionValidity", "2018-07-25T10:31:06Z");
pairs.put("shipBeforeDate", "2018-07-30");
pairs.put("paymentAmount", "1995");
pairs.put("currencyCode", "EUR");
pairs.put("skinCode", "X7hsNDWp");
$HMAC_KEY = "44782DEF547AAA06C910C43932B1EB0C71FC68D9D0C057550C48EC2ACF6BA056";
$pairs["shopperLocale"] = "en_GB";
$pairs["merchantReference"] = "paymentTest:143522\\64\\39255";
$pairs["merchantAccount"] = "TestMerchant";
$pairs["sessionValidity"] = "2018-07-25T10:31:06Z";
$pairs["shipBeforeDate"] = "2018-07-30";
$pairs["paymentAmount"] = "1995";
$pairs["currencyCode"] = "EUR";
$pairs["skinCode"] = "X7hsNDWp";
HMAC_KEY = "44782DEF547AAA06C910C43932B1EB0C71FC68D9D0C057550C48EC2ACF6BA056"
pairs = {
    'shopperLocale': 'en_GB',
    'merchantReference': 'paymentTest:143522\\64\\39255',
    'merchantAccount': 'TestMerchant',
    'sessionValidity': '2018-07-25T10:31:06Z',
    'shipBeforeDate': '2018-07-30',
    'paymentAmount': '1995',
    'currencyCode': 'EUR',
    'skinCode': 'X7hsNDWp'

1. Sort the key-value pairs by key.

SortedMap<String, String> sortedPairs = new TreeMap<>(pairs);
ksort($pairs, SORT_STRING);
sorted_pairs = OrderedDict(sorted(pairs.items(), key=lambda t: t[0]))
  1. Replace null values with an empty string ("") and escape the following characters in the value of each pair:
  • "\" (backslash) as "\\"
  • ":" (colon) as "\:"
SortedMap<String, String> escapedPairs =
                        e -> e.getKey(),
                        e -> (e.getValue() == null) ? "" : e.getValue().replace("\\", "\\\\").replace(":", "\\:"),
                        (k, v) -> k,
foreach ($pairs as $key => $value) {
    $escapedPairs[$key] = str_replace(':','\\:', str_replace('\\', '\\\\', $value));
def escape(val):
    if isinstance(val,int):
        return val
    if val is None:
        return ""
    return val.replace('\\', '\\\\').replace(':', '\\:')

escaped_pairs = OrderedDict(map(lambda t: (t[0], escape(t[1])), sorted_pairs.items()))

The table below reflects the sorting and escaping steps.

Key Value
currencyCode EUR
merchantReference paymentTest\:143522\\64\\39255
paymentAmount 1995
sessionValidity 2018-07-25T10\:31\:06Z
shipBeforeDate 2018-07-30
shopperLocale en_GB
skinCode X7hsNDWp
  1. Concatenate the key names, first, followed by the values. Use a colon (":") to delimit the key names and values to obtain the signing string.
String signingString = Stream.concat(escapedPairs.keySet().stream(), escapedPairs.values().stream())
$signingString = implode(":", array_merge(array_keys($escapedPairs), array_values($escapedPairs)));
signing_string = ":".join(escaped_pairs.keys() + escaped_pairs.values())

The signing string below shows the concatenated and delimited key-value pairs.

  1. Convert the HMAC key to the binary representation. Note that the HMAC key is considered as hexadecimal value.
// import from;
byte[] binaryHmacKey = BaseEncoding.base16().decode(HMAC_KEY);
$binaryHmacKey = pack("H*" , $HMAC_KEY);
binary_hmac_key = binascii.a2b_hex(HMAC_KEY)

5. Calculate the HMAC with the signing string, in binary representation given the UTF-8 charset, using the cryptographic hash function SHA-256.

// Create an HMAC SHA-256 key from the raw key bytes
SecretKeySpec signingKey = new SecretKeySpec(binaryHmacKey, "HmacSHA256");

// Get an HMAC SHA-256 Mac instance and initialize with the signing key
Mac mac = Mac.getInstance("HmacSHA256");

// calculate the hmac on the binary representation of the signing string
byte[] binaryHmac = mac.doFinal(signingString.getBytes(Charset.forName("UTF8")));
$binaryHmac = hash_hmac('sha256', $signingString, $binaryHmacKey, true);
binary_hmac =, signing_string, hashlib.sha256)
  1. Encode the result using the Base64 encoding scheme to obtain the signature.
String signature = Base64.getEncoder().encodeToString(binaryHmac);
$signature = base64_encode($binaryHmac);
signature = base64.b64encode(binary_hmac.digest())

The signature calculated, for example, key-value pairs and HMAC key is:


Testing a signature

You can check your signature calculation by constructing a request URL from the key-value pairs and a check HMAC endpoint:

To make the request, you have to be signed into your merchant account, as the endpoint is a part of the Customer Area.

You need the Merchant Technical Integrator role to be able to see the page in your Customer Area.

Note that for the test to work you also need to supply your merchant account and a skin code associated with it.

Supply the signature in the merchantSig field, and the parameters have to be URL-encoded.

String signature = calculateSignature(pairs);
pairs.put("merchantSig", signature);

String queryString = pairs.keySet().stream()
        .map(key -> {
            try {
                return key + "=" +  URLEncoder.encode(pairs.get(key), "UTF-8");
            } catch (UnsupportedEncodingException e) {
            return "Error: could not URL-encode value";

String testUrl = "" + "?" + queryString;
$signature = $this->calculateSignature($pairs);
$pairs["merchantSig"] = $signature;
$queryString = http_build_query($pairs);

$testUrl = "" . "?" . $queryString;
signature = calculate_signature(pairs)
pairs['merchantSig'] = signature

test_url = "" + '?' + urlencode(pairs)

Optionally, to compare your signing string with the string that Adyen calculates from the supplied key-value pairs, you can submit the signingString field value in addition to the standard payment fields.