Generate a Message Signature / Hash

Introduction

All requests to our payment integrations (whether via the API or hosted solutions) require the use of a hash, also referred to as a message signature. This makes use of not only your api key, but your api secret (also available in the portal) to add an extra layer of security to requests and prevent man-in-the-middle attacks.

The high-level idea is that for every request, you must:

  • Combine your api key and some request data into a single string
  • Hash the string using the HMAC SHA256 method and your secret key
  • Add the hash to your request

The rest of this page goes into step-by-step detail on how to do this for each integration method.

Payments API

Message Signature Header

When calling the Payments API, Checkouts and Payment Links endpoints, this is the method that must be used; generating the hash and attaching it as the Message-Signature header along with the Timestamp and Client-Request-Id headers.

For full detail on how to do this, our best resource is the following recipe:

Hosted Payment Page

hashExtended form parameter

When using the Hosted Payment Page, the fields used to generate and pass the has are slightly different to the header above.

The hash needs to be calculated using all of the request parameters in ascending order of the parameter names (parameter hashExtended). When you are using the embedded form, there is also an option where you do not need to know the card details (PAN, CVV and Expiry Date) for the hash calculation. This will be managed with a specific setting performed on your store.

The request parameters that are not specified in our solution can still be submitted in your request to the Gateway, but they must be excluded from the hash calculation. They will be ignored during processing and returned back in the response. Please contact your local support team if you want to enable this feature.

Creating the hash

Transaction request values used for the hash calculation:

FieldExample
chargetotal13.00
currency978
paymentMethodM
responseFailURLhttps://mywebshop/response_failure.jsp
responseSuccessURLhttps://mywebshop/response_success.jsp
sharedsecretsharedsecret
storename10123456789
timezoneEurope/Berlin
transactionNotificationURLhttps://mywebshop/transactionNotification
txndatetime2022:04:17-17:32:41
txntypesale

📘

Payment Method Options

Please refer to the Forms fields page in this documentation for the complete list of values

Step 1: The hashExtended needs to be calculated using all request parameters in ascending order of the parameter names

Join the parameters’ values to one string with pipe separator (use only parameters’ values and not the parameters’ names).

let chargetotal = "13.00";
let currency =	"978";
let paymentMethod =	"M";
let responseFailURL = "https://mywebshop/response_failure.jsp";
let responseSuccessURL = "https://mywebshop/response_success.jsp";
let sharedsecret = "sharedsecret";
let storename =	"10123456789";
let timezone = "Europe/Berlin";
let transactionNotificationURL = "https://mywebshop/transactionNotification";
let txndatetime = "2020:04:17-17:32:41";
let txntype = "sale";
let stringToExtendedHash = `${chargetotal}|${currency}|${paymentMethod}|${responseFailURL}|${responseSuccessURL}|${storename}|${timezone}|${transactionNotificationURL}|${txndatetime}|${txntype}`;

Note the corresponding hash string does not include sharedsecret, which has to be used as the secret key for the HMAC instead.

Step 2: Pass the created string to the HMACSHA256 algorithm and using shared secret ('sharedsecret') as a key for calculating the hash value.

var hashExtended = CryptoJS.HmacSHA256(stringToExtendedHash, sharedsecret);

Step 3: Use the value returned by the HMACSHA256 algorithm and submit it to our Gateway in the given form.

<input type="hidden" name="hashExtended" value="8CVD62a88mwr/Nfc+t+CWB+XG0g5cqmSrN8JhFlQJVM="/>

Only HMAC algorithm (i.e.: HMACSHA256, HMACSHA384 or HMACSHA512) is supported for generating the extended request hash.

Examples

let chargetotal = "13.00";
let currency =	"978";
let paymentMethod =	"M";
let responseFailURL = "https://mywebshop/response_failure.jsp";
let responseSuccessURL = "https://mywebshop/response_success.jsp";
let sharedsecret = "sharedsecret";
let storename =	"10123456789";
let timezone = "Europe/Berlin";
let transactionNotificationURL = "https://mywebshop/transactionNotification";
let txndatetime = "2020:04:17-17:32:41";
let txntype = "sale";
let stringToExtendedHash = `${chargetotal}|${currency}|${paymentMethod}|${responseFailURL}|${responseSuccessURL}|${storename}|${timezone}|${transactionNotificationURL}|${txndatetime}|${txntype}`;
var hashExtended = CryptoJS.HmacSHA256(stringToExtendedHash, sharedsecret);

<input type="hidden" name="hashExtended" value="8CVD62a88mwr/Nfc+t+CWB+XG0g5cqmSrN8JhFlQJVM="/>
<?php
    // Timezeone needs to be set
    date_default_timezone_set('Europe/Berlin');
    $dateTime = date("Y:m:d-H:i:s");

    function getDateTime() {
        global $dateTime;
        return $dateTime;
    }

    /*
        Function that calculates the hash of the following parameters:
        - Store Id
        - Date/Time(see $dateTime above)
        - chargetotal
        - currency (numeric ISO value)
        - shared secret
    */
    function createExtendedHash($chargetotal, $currency) {
        // Please change the store Id to your individual Store ID
        $storeId = "10123456789";
        // NOTE: Please DO NOT hardcode the secret in that script. For example read it from a database.
        $sharedSecret = "sharedsecret";
        $separator = "|";
        
        $stringToHash = $storeId . $separator .  getDateTime() . $separator . $chargetotal . $separator . $currency;

        $hashSHA256 = CryptoJS.HmacSHA384(hashWithAllStrings, sharedSecret);
        $hash = CryptoJS.enc.Base64.stringify($hashSHA256);

        return $hash;
    }
?>
<!-- google CryptoJS for HMAC -->
<script LANGUAGE=JScript RUNAT=Server src="script/cryptoJS/crypto-js.min.js"></script>
<script LANGUAGE=JScript RUNAT=Server src="script/cryptoJS/enc-base64.min.js"></script>
<script LANGUAGE=JScript RUNAT=Server>
      var today = new Date();
      var txndatetime = today.formatDate("Y:m:d-H:i:s");

      /*
          Function that calculates the hash of the following parameters:
  - chargetotal
  - currency
  - paymentMethod
  - responseFailURL
  - responseSuccessURL
  - sharedsecret
  - storename
  - timezone
  - transactionNotificationURL
  - txndatetime
  - txntype    
      */

      function createExtendedHash(chargetotal, currency) {
          // Please change the storename to your individual Store Name
          var storename = "10123456789";
          // NOTE: Please DO NOT hardcode the secret in that script. For example read it from a database.
          var stringToExtendedHash = chargetotal|currency|paymentMethod|responseFailURL|responseSuccessURL|storename|timezone|transactionNotificationURL|txndatetime|txntype;

          var hashHMACSHA256 = CryptoJS.HmacSHA256(stringToExtendedHash, sharedSecret);
      var extendedhash = CryptoJS.enc.Base64.stringify(hashHMACSHA256);

          Response.Write(extendedhash);
      }

      function getDateTime() {
          Response.Write(txndatetime);
      }
</script>

NEXO Acquirer API

A similar concept is applied to our NEXO Acquirer API.

Please refer to Nexo encryption and macing section for more information.


Want a quick overview?