Praxis Wiki logo

Overview Authentication


Algorithm

The signature is generated as a SHA-384 hash of the JSON string used in the request body.

Signature Generation

The following steps are required to generate the signature for outgoing requests:

  1. The values of the specified parameters are concatenated into a string (1),
    following the exact sequence described in the Signature section of each API method.
  2. Append the merchant secret to this string (1) to create a new temporary variable (2).
  3. The temporary variable from step 2 is hashed using the SHA-384 algorithm into a hash variable (3).
  4. The hash variable (3) is sent as Gt-Authentication: YOUR_HASH_STRING_HERE HTTP header.
  5. Additionally the following HTTP header is sent as well: Content-Type: application/json; charset=utf-8.
  6. JSON string is sent as the request body (or response body if replying to an incoming request).

Signature Validation

When receiving a request (or a response to your own outgoing request), it will be also preceded by the Gt-Authentication: ... and Content-Type: application/json; charset=utf-8 HTTP headers. You must validate the signature as follows:

  1. JSON string from incoming request body or from response body to your outgoing request is read and parsed into the data object.
  2. Values for the specified parameters are concatenated into a string (1) - in the exact order defined in the relevant API method's Signature section.
  3. String variable (1) is concatenated with the merchant secret into a new temporary variable (2).
  4. Resulting temporary variable (2) is hashed using the SHA-384 algorithm into a hash variable (3).
  5. Temporary hash variable (3) is compared to Gt-Authentication HTTP header of an incoming request or a response to your outgoing request using a string comparison function.
  6. If the value of the temporary hash variable (3) matches the Gt-Authentication HTTP header, the signature is considered valid. If they do not match, the signature is invalid and should be treated as an authentication failure. Your application should handle this case accordingly.

Example

<?php

class HowToBuildSignature
{
    //Action to be taken within the cashier
    const INTENT_PAYMENT = 'payment';
    // Your Merchant Account ID
    const MERCHANT_ID = 'Test-Integration-Merchant';
    // Your Merchant Secret
    const MERCHANT_SECRET = 'MerchantSecretKey';
    // Your Application Key
    const APPLICATION_KEY = 'Sandbox';
    // Your API Version
    const API_VERSION = '1.3';
​
    public static function _GET_SAMPLE_DATA_TO_SEND_REQUEST_(): array
    {
        $request = [
            'cid'                 => '1',
            'application_key'     => self::APPLICATION_KEY,
            'merchant_id'         => self::MERCHANT_ID,
            'intent'              => self::INTENT_PAYMENT,
            'order_id'            => self::getOrderID(),
            'your_variable_key_1' => 'some_string_value',
            'your_variable_key_2' => 12345,
            'your_variable_key_3' => null,
            'your_variable_key_4' => true,
            'timestamp'           => self::getCurrentTimestamp(),
            'version'             => self::API_VERSION
        ];
​
        return $request;
    }
​
    //Cashier API 1.3
    private static function getRequestSignatureList()
    {
        return [
            'merchant_id',
            'application_key',
            'timestamp',
            'intent',
            'cid',
            'order_id'
        ];
    }
​
    private static function getConcatenatedString(array $data): string
    {
        $concatenated_string = "";
        foreach (HowToBuildSignature::getRequestSignatureList() as $key) {
            if (array_key_exists($key, $data) && !is_null($data[$key])) {
                $concatenated_string .= $data[$key];
            }
        }
​
        return $concatenated_string;
    }
​
    private static function getGtAuthenticationHeader(array $request): string
    {
        // Sort request array by keys ASC
        $concatenated_string = self::getConcatenatedString($request);
​
        // Concatenate Merchant Secret Key with response params
        $concatenated_string .= self::MERCHANT_SECRET;
​
        // Generate HASH of concatenated string
        $signature = self::generateSignature($concatenated_string);
        return $signature;
    }
​
    private static function generateSignature(string $input): string
    {
        $hashtext = hash('sha384', $input);
​
        return $hashtext;
    }
​
    private static function exportArrayToJSON(array $input): string
    {
        $json_string = json_encode($input);
​
        return $json_string;
    }
​
    private static function getOrderID(): string
    {
        return 'order_' . rand(100, 100000);
    }
​
    private static function getCurrentTimestamp(): int
    {
        return time();
    }
​
    public static function _TEST_()
    {
        echo "=== TESTING REQUEST TO BE SENT ====";
        echo "\n";
        $request_to_send             = self::_GET_SAMPLE_DATA_TO_SEND_REQUEST_();
        $gt_authentication_header    = self::getGtAuthenticationHeader($request_to_send);
        $request_to_send_json_string = self::exportArrayToJSON($request_to_send);
        echo "== Gt-Authentication header in the request:";
        echo "\n";
        echo $gt_authentication_header;
        echo "\n";
        echo "== data to send:";
        echo "\n";
        echo $request_to_send_json_string;
        echo "\n";
        echo "\n";
    }
}
​
HowToBuildSignature::_TEST_();