{"title":"HMAC signature calculation","category":"default","creationDate":1776961627,"content":"<div class=\"sc-notice warning\"><div>\n<p><strong>Hosted Payment Pages are no longer available<\/strong><\/p>\n<p>To accept payments through an Adyen-hosted page, use our <a href=\"\/pt\/online-payments\/build-your-integration\/sessions-flow?platform=Web&amp;integration=Hosted%2BCheckout\">Hosted Checkout<\/a>.<\/p>\n<p>This page is for the classic Hosted Payment Pages (HPP) integration, which has reached end-of-life.  We are no longer processing transactions though HPP.<\/p>\n<\/div><\/div>\n<p>To ensure authenticity and data integrity of incoming requests Adyen requires these requests to be signed.\u00a0This signature is based on a\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/Hash-based_message_authentication_code\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">Hash-based Message Authentication Code (HMAC)<\/a>\u00a0calculated using a request's key-value pairs and a secret key, which is known only to you and Adyen.\u00a0<\/p>\n<p>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\u00a0tampered.<\/p>\n<p>Similarly,\u00a0you can validate responses from Adyen by calculating the corresponding signature and comparing it with the signature in the response.<\/p>\n<div class=\"sc-notice info\"><div>\n<p>Signatures can also be used to\u00a0add an extra layer of security for\u00a0<a href=\"\/pt\/development-resources\/webhooks\">webhooks<\/a>. However, the calculation for this functionality is different. For details, refer to the\u00a0<a href=\"\/pt\/development-resources\/webhooks\/secure-webhooks\/verify-hmac-signatures\">Signing webhooks with HMAC<\/a>\u00a0guide.<\/p>\n<\/div><\/div>\n<h2 id=\"getting-hmac-keys\">Getting HMAC keys<\/h2>\n<p>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:<\/p>\n<ol>\n<li>\n<p>Log in to your\u00a0<a href=\"https:\/\/ca-test.adyen.com\/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">Customer Area<\/a>\u00a0using your company account.<\/p>\n<\/li>\n<li>\n<p>From the main menu, select\u00a0<strong>Account<\/strong>\u00a0&gt;\u00a0<strong>Skins<\/strong>.<\/p>\n<\/li>\n<li>\n<p>Select an existing skin from the\u00a0<strong>List<\/strong>\u00a0tab or create a new skin by switching to the\u00a0<strong>New<\/strong>\u00a0tab.<\/p>\n<\/li>\n<li>\n<p>Click\u00a0<strong>Generate new HMAC key<\/strong>\u00a0both for the\u00a0<strong>Test platform<\/strong>\u00a0and\u00a0<strong>Live platform<\/strong>. Then copy new keys and store them in a secure place in your system to access these values later.<br \/>\n<img alt=\"Generate HMAC keys\" src=\"\/user\/pages\/docs\/02.online-payments\/60.classic-integrations\/04.hosted-payment-pages\/04.hmac-signature-calculation\/GenerateHMACKeys.png\" \/><\/p>\n<\/li>\n<li>\n<p>Provide a description for this skin.<\/p>\n<\/li>\n<li>\n<p>To save the skin click\u00a0<strong>Create New Skin on Test<\/strong>\u00a0at the page bottom.<\/p>\n<\/li>\n<\/ol>\n<h2 id=\"implementing-signature-calculation\">Implementing signature calculation<\/h2>\n<p>In this tutorial, we use the following HMAC key and key-value pairs as an example.<\/p>\n<p>Sample HMAC key:<\/p>\n<pre><code>44782DEF547AAA06C910C43932B1EB0C71FC68D9D0C057550C48EC2ACF6BA056<\/code><\/pre>\n<p>Sample key-value pairs:<\/p>\n<table>\n<thead>\n<tr>\n<th>Key<\/th>\n<th>Value<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>shopperLocale<\/td>\n<td>en_GB<\/td>\n<\/tr>\n<tr>\n<td>merchantReference<\/td>\n<td>paymentTest:143522\\64\\39255<\/td>\n<\/tr>\n<tr>\n<td>merchantAccount<\/td>\n<td>YOUR_MERCHANT_ACCOUNT<\/td>\n<\/tr>\n<tr>\n<td>sessionValidity<\/td>\n<td>2018-07-25T10:31:06Z<\/td>\n<\/tr>\n<tr>\n<td>shipBeforeDate<\/td>\n<td>2018-07-30<\/td>\n<\/tr>\n<tr>\n<td>paymentAmount<\/td>\n<td>1995<\/td>\n<\/tr>\n<tr>\n<td>currencyCode<\/td>\n<td>EUR<\/td>\n<\/tr>\n<tr>\n<td>skinCode<\/td>\n<td>X7hsNDWp<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div class=\"sc-notice warning\"><div>\n<p>Do not use this example key for your real integration with Adyen.<\/p>\n<\/div><\/div>\n<div data-component-wrapper=\"code-sample\">\n    <code-sample :title=\"''\" :id=\"'865667596'\" :code-data=\"[{&quot;language&quot;:&quot;java&quot;,&quot;tabTitle&quot;:&quot;Java&quot;,&quot;content&quot;:&quot;String HMAC_KEY = \\&quot;44782DEF547AAA06C910C43932B1EB0C71FC68D9D0C057550C48EC2ACF6BA056\\&quot;;\\nMap&lt;String, String&gt; pairs = new HashMap&lt;&gt;();\\npairs.put(\\&quot;shopperLocale\\&quot;, \\&quot;en_GB\\&quot;);\\npairs.put(\\&quot;merchantReference\\&quot;, \\&quot;paymentTest:143522\\\\\\\\64\\\\\\\\39255\\&quot;);\\npairs.put(\\&quot;merchantAccount\\&quot;, \\&quot;YOUR_MERCHANT_ACCOUNT\\&quot;);\\npairs.put(\\&quot;sessionValidity\\&quot;, \\&quot;2018-07-25T10:31:06Z\\&quot;);\\npairs.put(\\&quot;shipBeforeDate\\&quot;, \\&quot;2018-07-30\\&quot;);\\npairs.put(\\&quot;paymentAmount\\&quot;, \\&quot;1995\\&quot;);\\npairs.put(\\&quot;currencyCode\\&quot;, \\&quot;EUR\\&quot;);\\npairs.put(\\&quot;skinCode\\&quot;, \\&quot;X7hsNDWp\\&quot;);&quot;},{&quot;language&quot;:&quot;php&quot;,&quot;tabTitle&quot;:&quot;PHP&quot;,&quot;content&quot;:&quot;$HMAC_KEY = \\&quot;44782DEF547AAA06C910C43932B1EB0C71FC68D9D0C057550C48EC2ACF6BA056\\&quot;;\\n$pairs[\\&quot;shopperLocale\\&quot;] = \\&quot;en_GB\\&quot;;\\n$pairs[\\&quot;merchantReference\\&quot;] = \\&quot;paymentTest:143522\\\\\\\\64\\\\\\\\39255\\&quot;;\\n$pairs[\\&quot;merchantAccount\\&quot;] = \\&quot;YOUR_MERCHANT_ACCOUNT\\&quot;;\\n$pairs[\\&quot;sessionValidity\\&quot;] = \\&quot;2018-07-25T10:31:06Z\\&quot;;\\n$pairs[\\&quot;shipBeforeDate\\&quot;] = \\&quot;2018-07-30\\&quot;;\\n$pairs[\\&quot;paymentAmount\\&quot;] = \\&quot;1995\\&quot;;\\n$pairs[\\&quot;currencyCode\\&quot;] = \\&quot;EUR\\&quot;;\\n$pairs[\\&quot;skinCode\\&quot;] = \\&quot;X7hsNDWp\\&quot;;&quot;},{&quot;language&quot;:&quot;py&quot;,&quot;tabTitle&quot;:&quot;Python&quot;,&quot;content&quot;:&quot;HMAC_KEY = \\&quot;44782DEF547AAA06C910C43932B1EB0C71FC68D9D0C057550C48EC2ACF6BA056\\&quot;\\npairs = {\\n    'shopperLocale': 'en_GB',\\n    'merchantReference': 'paymentTest:143522\\\\\\\\64\\\\\\\\39255',\\n    'merchantAccount': 'YOUR_MERCHANT_ACCOUNT',\\n    'sessionValidity': '2018-07-25T10:31:06Z',\\n    'shipBeforeDate': '2018-07-30',\\n    'paymentAmount': '1995',\\n    'currencyCode': 'EUR',\\n    'skinCode': 'X7hsNDWp'\\n}&quot;}]\" :enable-copy-link-to-code-block=\"true\" :code-sample-card-size=\"'fullsize'\"><\/code-sample>\n<\/div>\n<p>1.\u00a0Sort the key-value pairs by key.<\/p>\n<div data-component-wrapper=\"code-sample\">\n    <code-sample :title=\"''\" :id=\"'1806431167'\" :code-data='[{\"language\":\"java\",\"tabTitle\":\"Java\",\"content\":\"SortedMap&lt;String, String&gt; sortedPairs = new TreeMap&lt;&gt;(pairs);\"},{\"language\":\"php\",\"tabTitle\":\"PHP\",\"content\":\"ksort($pairs, SORT_STRING);\"},{\"language\":\"py\",\"tabTitle\":\"Python\",\"content\":\"sorted_pairs = OrderedDict(sorted(pairs.items(), key=lambda t: t[0]))\"}]' :enable-copy-link-to-code-block=\"true\" :code-sample-card-size=\"'fullsize'\"><\/code-sample>\n<\/div>\n<ol start=\"2\">\n<li>Replace null values with an empty string (\"\") and escape the following characters in the value of each pair:<\/li>\n<\/ol>\n<ul>\n<li>\"\\\" (backslash) as \"\\\\\"<\/li>\n<li>\":\" (colon) as \"\\:\"<\/li>\n<\/ul>\n<div data-component-wrapper=\"code-sample\">\n    <code-sample :title=\"''\" :id=\"'285133380'\" :code-data=\"[{&quot;language&quot;:&quot;java&quot;,&quot;tabTitle&quot;:&quot;Java&quot;,&quot;content&quot;:&quot;SortedMap&lt;String, String&gt; escapedPairs =\\n        sortedPairs.entrySet().stream()\\n                .collect(Collectors.toMap(\\n                        e -&gt; e.getKey(),\\n                        e -&gt; (e.getValue() == null) ? \\&quot;\\&quot; : e.getValue().replace(\\&quot;\\\\\\\\\\&quot;, \\&quot;\\\\\\\\\\\\\\\\\\&quot;).replace(\\&quot;:\\&quot;, \\&quot;\\\\\\\\:\\&quot;),\\n                        (k, v) -&gt; k,\\n                        TreeMap::new\\n                ));&quot;},{&quot;language&quot;:&quot;php&quot;,&quot;tabTitle&quot;:&quot;PHP&quot;,&quot;content&quot;:&quot;foreach ($pairs as $key =&gt; $value) {\\n\\t$escapedPairs[$key] = str_replace(':','\\\\\\\\:', str_replace('\\\\\\\\', '\\\\\\\\\\\\\\\\', $value));\\n}&quot;},{&quot;language&quot;:&quot;py&quot;,&quot;tabTitle&quot;:&quot;Python&quot;,&quot;content&quot;:&quot;def escape(val):\\n    if isinstance(val,int):\\n        return val\\n    if val is None:\\n        return \\&quot;\\&quot;\\n    return val.replace('\\\\\\\\', '\\\\\\\\\\\\\\\\').replace(':', '\\\\\\\\:')\\n\\nescaped_pairs = OrderedDict(map(lambda t: (t[0], escape(t[1])), sorted_pairs.items()))&quot;}]\" :enable-copy-link-to-code-block=\"true\" :code-sample-card-size=\"'fullsize'\"><\/code-sample>\n<\/div>\n<p>The table below reflects the sorting and escaping steps.<\/p>\n<table>\n<thead>\n<tr>\n<th>Key<\/th>\n<th>Value<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>currencyCode<\/td>\n<td>EUR<\/td>\n<\/tr>\n<tr>\n<td>merchantAccount<\/td>\n<td>YOUR_MERCHANT_ACCOUNT<\/td>\n<\/tr>\n<tr>\n<td>merchantReference<\/td>\n<td>paymentTest\\:143522\\\\64\\\\39255<\/td>\n<\/tr>\n<tr>\n<td>paymentAmount<\/td>\n<td>1995<\/td>\n<\/tr>\n<tr>\n<td>sessionValidity<\/td>\n<td>2018-07-25T10\\:31\\:06Z<\/td>\n<\/tr>\n<tr>\n<td>shipBeforeDate<\/td>\n<td>2018-07-30<\/td>\n<\/tr>\n<tr>\n<td>shopperLocale<\/td>\n<td>en_GB<\/td>\n<\/tr>\n<tr>\n<td>skinCode<\/td>\n<td>X7hsNDWp<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<ol start=\"3\">\n<li>Concatenate the key names, first, followed by the values. Use a colon (\":\") to delimit the key names and values to obtain the signing string.<\/li>\n<\/ol>\n<div data-component-wrapper=\"code-sample\">\n    <code-sample :title=\"''\" :id=\"'726181440'\" :code-data='[{\"language\":\"java\",\"tabTitle\":\"Java\",\"content\":\"String signingString = Stream.concat(escapedPairs.keySet().stream(), escapedPairs.values().stream())\\n        .collect(Collectors.joining(\\\":\\\"));\"},{\"language\":\"php\",\"tabTitle\":\"PHP\",\"content\":\"$signingString = implode(\\\":\\\", array_merge(array_keys($escapedPairs), array_values($escapedPairs)));\"},{\"language\":\"py\",\"tabTitle\":\"Python\",\"content\":\"signing_string = \\\":\\\".join(escaped_pairs.keys() + escaped_pairs.values())\"}]' :enable-copy-link-to-code-block=\"true\" :code-sample-card-size=\"'fullsize'\"><\/code-sample>\n<\/div>\n<p>The signing string below shows the concatenated and delimited key-value pairs.<\/p>\n<pre><code>currencyCode:merchantAccount:merchantReference:paymentAmount:sessionValidity:shipBeforeDate:shopperLocale:skinCode:EUR:YOUR_MERCHANT_ACCOUNT:paymentTest\\:143522\\\\64\\\\39255:1995:2018-07-25T10\\:31\\:06Z:2018-07-30:en_GB:X7hsNDWp<\/code><\/pre>\n<ol start=\"4\">\n<li>Convert the HMAC key to the binary representation. Note that the HMAC key is considered as hexadecimal value.<\/li>\n<\/ol>\n<div data-component-wrapper=\"code-sample\">\n    <code-sample :title=\"''\" :id=\"'341138954'\" :code-data='[{\"language\":\"java\",\"tabTitle\":\"Java\",\"content\":\"\\\/\\\/ import from com.google.common.io.BaseEncoding;\\nbyte[] binaryHmacKey = BaseEncoding.base16().decode(HMAC_KEY);\"},{\"language\":\"php\",\"tabTitle\":\"PHP\",\"content\":\"$binaryHmacKey = pack(\\\"H*\\\" , $HMAC_KEY);\"},{\"language\":\"py\",\"tabTitle\":\"Python\",\"content\":\"binary_hmac_key = binascii.a2b_hex(HMAC_KEY)\"}]' :enable-copy-link-to-code-block=\"true\" :code-sample-card-size=\"'fullsize'\"><\/code-sample>\n<\/div>\n<p>5.\u00a0Calculate the HMAC with the signing string, in binary representation given the UTF-8 charset, using the cryptographic hash function\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/SHA-2\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">SHA-256<\/a>.<\/p>\n<div data-component-wrapper=\"code-sample\">\n    <code-sample :title=\"''\" :id=\"'1029472813'\" :code-data=\"[{&quot;language&quot;:&quot;java&quot;,&quot;tabTitle&quot;:&quot;Java&quot;,&quot;content&quot;:&quot;\\\/\\\/ Create an HMAC SHA-256 key from the raw key bytes\\nSecretKeySpec signingKey = new SecretKeySpec(binaryHmacKey, \\&quot;HmacSHA256\\&quot;);\\n\\n\\\/\\\/ Get an HMAC SHA-256 Mac instance and initialize with the signing key\\nMac mac = Mac.getInstance(\\&quot;HmacSHA256\\&quot;);\\nmac.init(signingKey);\\n\\n\\\/\\\/ calculate the hmac on the binary representation of the signing string\\nbyte[] binaryHmac = mac.doFinal(signingString.getBytes(Charset.forName(\\&quot;UTF8\\&quot;)));&quot;},{&quot;language&quot;:&quot;php&quot;,&quot;tabTitle&quot;:&quot;PHP&quot;,&quot;content&quot;:&quot;$binaryHmac = hash_hmac('sha256', $signingString, $binaryHmacKey, true);&quot;},{&quot;language&quot;:&quot;py&quot;,&quot;tabTitle&quot;:&quot;Python&quot;,&quot;content&quot;:&quot;binary_hmac = hmac.new(binary_hmac_key, signing_string, hashlib.sha256)&quot;}]\" :enable-copy-link-to-code-block=\"true\" :code-sample-card-size=\"'fullsize'\"><\/code-sample>\n<\/div>\n<ol start=\"6\">\n<li>Encode the result using the\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/Base64\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">Base64<\/a>\u00a0encoding scheme to obtain the signature.<\/li>\n<\/ol>\n<div data-component-wrapper=\"code-sample\">\n    <code-sample :title=\"''\" :id=\"'282265585'\" :code-data='[{\"language\":\"java\",\"tabTitle\":\"Java\",\"content\":\"String signature = Base64.getEncoder().encodeToString(binaryHmac);\"},{\"language\":\"php\",\"tabTitle\":\"PHP\",\"content\":\"$signature = base64_encode($binaryHmac);\"},{\"language\":\"py\",\"tabTitle\":\"Python\",\"content\":\"signature = base64.b64encode(binary_hmac.digest())\"}]' :enable-copy-link-to-code-block=\"true\" :code-sample-card-size=\"'fullsize'\"><\/code-sample>\n<\/div>\n<p>The signature calculated, for example, key-value pairs and HMAC key is:<\/p>\n<pre><code>8SFtIc6zQlswxAZqDKXL+BpRmlDvIWyjOwU8wdl0zK4=<\/code><\/pre>\n<h2 id=\"testing-a-signature\">Testing a signature<\/h2>\n<p>You can check your signature calculation by constructing a request URL from the\u00a0key-value pairs and a check HMAC endpoint:<br \/>\n<a href=\"https:\/\/ca-test.adyen.com\/ca\/ca\/skin\/checkhmac.shtml\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">https:\/\/ca-test.adyen.com\/ca\/ca\/skin\/checkhmac.shtml<\/a><\/p>\n<p>To make the request, you have to be signed\u00a0into your merchant account, as the endpoint is a part of the <a href=\"https:\/\/ca-test.adyen.com\/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">Customer Area<\/a>.<\/p>\n<div class=\"sc-notice info\"><div>\n<p>You need the <strong>Merchant Technical Integrator<\/strong> role to be able to see the page in your Customer Area.<\/p>\n<\/div><\/div>\n<p>Note that for the test to work you also need to supply your merchant account and a <a href=\"\/pt\/online-payments\/classic-integrations\/hosted-payment-pages\/skin\">skin code<\/a> associated with it.<\/p>\n<p>Supply the signature in the\u00a0<code>merchantSig<\/code>\u00a0field, and the parameters have to be\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/Percent-encoding\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">URL-encoded<\/a>.<\/p>\n<div data-component-wrapper=\"code-sample\">\n    <code-sample :title=\"''\" :id=\"'1117519786'\" :code-data=\"[{&quot;language&quot;:&quot;java&quot;,&quot;tabTitle&quot;:&quot;Java&quot;,&quot;content&quot;:&quot;String signature = calculateSignature(pairs);\\npairs.put(\\&quot;merchantSig\\&quot;, signature);\\n\\nString queryString = pairs.keySet().stream()\\n        .map(key -&gt; {\\n            try {\\n                return key + \\&quot;=\\&quot; +  URLEncoder.encode(pairs.get(key), \\&quot;UTF-8\\&quot;);\\n            } catch (UnsupportedEncodingException e) {\\n                e.printStackTrace();\\n            }\\n            return \\&quot;Error: could not URL-encode value\\&quot;;\\n        }).collect(Collectors.joining(\\&quot;&amp;\\&quot;));\\n\\nString testUrl = \\&quot;https:\\\/\\\/ca-test.adyen.com\\\/ca\\\/ca\\\/skin\\\/checkhmac.shtml\\&quot; + \\&quot;?\\&quot; + queryString;&quot;},{&quot;language&quot;:&quot;php&quot;,&quot;tabTitle&quot;:&quot;PHP&quot;,&quot;content&quot;:&quot;$signature = $this-&gt;calculateSignature($pairs);\\n$pairs[\\&quot;merchantSig\\&quot;] = $signature;\\n$queryString = http_build_query($pairs);\\n    \\t\\n$testUrl = \\&quot;https:\\\/\\\/ca-test.adyen.com\\\/ca\\\/ca\\\/skin\\\/checkhmac.shtml\\&quot; . \\&quot;?\\&quot; . $queryString;&quot;},{&quot;language&quot;:&quot;py&quot;,&quot;tabTitle&quot;:&quot;Python&quot;,&quot;content&quot;:&quot;signature = calculate_signature(pairs)\\npairs['merchantSig'] = signature\\n\\ntest_url = \\&quot;https:\\\/\\\/ca-test.adyen.com\\\/ca\\\/ca\\\/skin\\\/checkhmac.shtml\\&quot; + '?' + urlencode(pairs)&quot;}]\" :enable-copy-link-to-code-block=\"true\" :code-sample-card-size=\"'fullsize'\"><\/code-sample>\n<\/div>\n<p>Optionally, to compare your signing string with the string that Adyen calculates from the supplied key-value pairs, you\u00a0can submit the\u00a0<code>signingString<\/code>\u00a0field value in addition to the standard payment fields.<\/p>","url":"https:\/\/docs.adyen.com\/pt\/online-payments\/classic-integrations\/hosted-payment-pages\/hmac-signature-calculation","articleFields":{"parameters":{"anchor_new":"<a href=\"\/development-resources\/webhooks\/secure-webhooks\/verify-hmac-signatures\"> webhooks<\/a>","parent_page":"classic Hosted Payment Pages (HPP)","new_desc":"looking for HMAC signature verification"},"sitemap":{"priority":0.3},"id":"24216160","type":"page","_expandable":{"operations":""},"status":"current","last_edit_on":"12-05-2020 09:40"},"algolia":{"url":"https:\/\/docs.adyen.com\/pt\/online-payments\/classic-integrations\/hosted-payment-pages\/hmac-signature-calculation","title":"HMAC signature calculation","content":"\nHosted Payment Pages are no longer available\nTo accept payments through an Adyen-hosted page, use our Hosted Checkout.\nThis page is for the classic Hosted Payment Pages (HPP) integration, which has reached end-of-life.  We are no longer processing transactions though HPP.\n\nTo ensure authenticity and data integrity of incoming requests Adyen requires these requests to be signed.\u00a0This signature is based on a\u00a0Hash-based Message Authentication Code (HMAC)\u00a0calculated using a request's key-value pairs and a secret key, which is known only to you and Adyen.\u00a0\nBefore 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\u00a0tampered.\nSimilarly,\u00a0you can validate responses from Adyen by calculating the corresponding signature and comparing it with the signature in the response.\n\nSignatures can also be used to\u00a0add an extra layer of security for\u00a0webhooks. However, the calculation for this functionality is different. For details, refer to the\u00a0Signing webhooks with HMAC\u00a0guide.\n\nGetting HMAC keys\nYou 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:\n\n\nLog in to your\u00a0Customer Area\u00a0using your company account.\n\n\nFrom the main menu, select\u00a0Account\u00a0&gt;\u00a0Skins.\n\n\nSelect an existing skin from the\u00a0List\u00a0tab or create a new skin by switching to the\u00a0New\u00a0tab.\n\n\nClick\u00a0Generate new HMAC key\u00a0both for the\u00a0Test platform\u00a0and\u00a0Live platform. Then copy new keys and store them in a secure place in your system to access these values later.\n\n\n\nProvide a description for this skin.\n\n\nTo save the skin click\u00a0Create New Skin on Test\u00a0at the page bottom.\n\n\nImplementing signature calculation\nIn this tutorial, we use the following HMAC key and key-value pairs as an example.\nSample HMAC key:\n44782DEF547AAA06C910C43932B1EB0C71FC68D9D0C057550C48EC2ACF6BA056\nSample key-value pairs:\n\n\n\nKey\nValue\n\n\n\n\nshopperLocale\nen_GB\n\n\nmerchantReference\npaymentTest:143522\\64\\39255\n\n\nmerchantAccount\nYOUR_MERCHANT_ACCOUNT\n\n\nsessionValidity\n2018-07-25T10:31:06Z\n\n\nshipBeforeDate\n2018-07-30\n\n\npaymentAmount\n1995\n\n\ncurrencyCode\nEUR\n\n\nskinCode\nX7hsNDWp\n\n\n\n\nDo not use this example key for your real integration with Adyen.\n\n\n    \n\n1.\u00a0Sort the key-value pairs by key.\n\n    \n\n\nReplace null values with an empty string (\"\") and escape the following characters in the value of each pair:\n\n\n\"\\\" (backslash) as \"\\\\\"\n\":\" (colon) as \"\\:\"\n\n\n    \n\nThe table below reflects the sorting and escaping steps.\n\n\n\nKey\nValue\n\n\n\n\ncurrencyCode\nEUR\n\n\nmerchantAccount\nYOUR_MERCHANT_ACCOUNT\n\n\nmerchantReference\npaymentTest\\:143522\\\\64\\\\39255\n\n\npaymentAmount\n1995\n\n\nsessionValidity\n2018-07-25T10\\:31\\:06Z\n\n\nshipBeforeDate\n2018-07-30\n\n\nshopperLocale\nen_GB\n\n\nskinCode\nX7hsNDWp\n\n\n\n\nConcatenate the key names, first, followed by the values. Use a colon (\":\") to delimit the key names and values to obtain the signing string.\n\n\n    \n\nThe signing string below shows the concatenated and delimited key-value pairs.\ncurrencyCode:merchantAccount:merchantReference:paymentAmount:sessionValidity:shipBeforeDate:shopperLocale:skinCode:EUR:YOUR_MERCHANT_ACCOUNT:paymentTest\\:143522\\\\64\\\\39255:1995:2018-07-25T10\\:31\\:06Z:2018-07-30:en_GB:X7hsNDWp\n\nConvert the HMAC key to the binary representation. Note that the HMAC key is considered as hexadecimal value.\n\n\n    \n\n5.\u00a0Calculate the HMAC with the signing string, in binary representation given the UTF-8 charset, using the cryptographic hash function\u00a0SHA-256.\n\n    \n\n\nEncode the result using the\u00a0Base64\u00a0encoding scheme to obtain the signature.\n\n\n    \n\nThe signature calculated, for example, key-value pairs and HMAC key is:\n8SFtIc6zQlswxAZqDKXL+BpRmlDvIWyjOwU8wdl0zK4=\nTesting a signature\nYou can check your signature calculation by constructing a request URL from the\u00a0key-value pairs and a check HMAC endpoint:\nhttps:\/\/ca-test.adyen.com\/ca\/ca\/skin\/checkhmac.shtml\nTo make the request, you have to be signed\u00a0into your merchant account, as the endpoint is a part of the Customer Area.\n\nYou need the Merchant Technical Integrator role to be able to see the page in your Customer Area.\n\nNote that for the test to work you also need to supply your merchant account and a skin code associated with it.\nSupply the signature in the\u00a0merchantSig\u00a0field, and the parameters have to be\u00a0URL-encoded.\n\n    \n\nOptionally, to compare your signing string with the string that Adyen calculates from the supplied key-value pairs, you\u00a0can submit the\u00a0signingString\u00a0field value in addition to the standard payment fields.","type":"page","locale":"pt","boost":16,"hierarchy":{"lvl0":"Home","lvl1":"Online payments","lvl2":"Classic integrations for Ecommerce","lvl3":"Hosted Payment Pages","lvl4":"HMAC signature calculation"},"hierarchy_url":{"lvl0":"https:\/\/docs.adyen.com\/pt","lvl1":"https:\/\/docs.adyen.com\/pt\/online-payments","lvl2":"https:\/\/docs.adyen.com\/pt\/online-payments\/classic-integrations","lvl3":"https:\/\/docs.adyen.com\/pt\/online-payments\/classic-integrations\/hosted-payment-pages","lvl4":"\/pt\/online-payments\/classic-integrations\/hosted-payment-pages\/hmac-signature-calculation"},"levels":5,"category":"Online Payments","category_color":"green","tags":["signature","calculation"]},"articleFiles":{"GenerateHMACKeys.png":"<img alt=\"\" src=\"https:\/\/docs.adyen.com\/user\/pages\/docs\/02.online-payments\/60.classic-integrations\/04.hosted-payment-pages\/04.hmac-signature-calculation\/GenerateHMACKeys.png\" \/>"}}
