public function generateCrypt(array $data)
    {
        // No data values should be null.

        array_walk($data, function (&$value) {
            if (! isset($value)) {
                $value = '';
            }
        });

        // Build the data in a query string.

        // The encrypted data MUST be ISO8859-1 regardless of what encoding
        // is used to submit the form, because that is how the gateway treats
        // the data internally.
        // This package assumes input data will be UTF-8 by default, and will
        // comvert it accordingly. This can be disabled if the data is already
        // ISO8859-1.
        // For the Server and Direct gateway methods, the POST encoding type
        // will tell the gateway how to interpret the character encoding, and
        // the gateway will do any encoding conversions necessary.

        // We cannot use http_build_query() because the gateway does
        // not decode the string as any standard encoded query string.
        // We just join the names and values with "=" and "&" and the
        // gateway somehow decodes ambiguous strings.

        $disableUtf8Decode = (bool)$this->getDisableUtf8Decode();

        $query = [];
        foreach ($data as $name => $value) {
            $query[] = $name . '=' . ($disableUtf8Decode ? $value : utf8_decode($value));
        }
        $query = implode('&', $query);

        // Encrypted using AES(block size 128-bit) in CBC mode with PKCS#5 padding.

        // AES encryption, CBC blocking with PKCS5 padding then HEX encoding.

        $key = $this->getEncryptionKey();

        // Normally IV (paramert 5, initialization vector) would be a kind of salt.
        // That is more relevant when encrypting user details where multiple users
        // could have identical passwords. But this is a one-off transport of a message
        // that will always be unique, so no variable IV is needed.

        $crypt = openssl_encrypt($query, 'aes-128-cbc', $key, OPENSSL_RAW_DATA, $key);

        return '@' . strtoupper(bin2hex($crypt));
    }