Signing Requests

Plugin icon

Signing Requests

All operations are secured with an HMAC-SHA256 one-way hash that is performed using a shared secret key between Zip and the merchant. This secret key will be provided to you.

Signatures are generated based on the request type.

  • POST JSON Requests sign the entire request body contents.
  • POST Form Requests sign all the keys + values contained in the form request in alphabetical order except for the signature.
  • GET Requests sign all the keys + values contained in the query string in alphabetical order except for the signature.

The header or query parameter name is always X-QP-Signature

Implementing this is language specific. Here are examples that can generate these hashes for you:

public class HmacSha256Signature
    {
        private static Encoding encoding = Encoding.UTF8;

        /// If your entire request body is passed in as bytes (e.g. POST JSON request), this will give you the correct hash
        public string Compute(string secretKey, byte[] bytes)
        {
            using (var hmacsha256 = new HMACSHA256(encoding.GetBytes(secretKey)))
            {
                var hash = hmacsha256.ComputeHash(bytes);

                return Convert.ToBase64String(hash);
            }
        }

        /// Given a dictionary that contains all the values from a GET or form POST request, this will return your correct hash
        public string Compute(string secretKey, IDictionary<string, string> values)
        {
            var builder = new StringBuilder();

            // Form Keys Sorted Alphabetically
            foreach (var item in values.OrderBy(i => i.Key))
            {
                if (!item.Key.Equals(Constants.SignatureKey, StringComparison.OrdinalIgnoreCase))
                {
                    builder.Append(item.Key);
                    builder.Append(item.Value);
                }
            }

            var message = builder.ToString();

            return this.Compute(secretKey, encoding.GetBytes(message));
        }

        public string Compute(string secretKey, string json)
        {
            var bytes = encoding.GetBytes(json);

            return this.Compute(secretKey, bytes);
        }

        /// This can take any object and turn it into a dictionary to be used for hash creation
        public IDictionary<string, string> GenerateKeyValues(object model)
        {
            var jsonObject = JObject.FromObject(model, JsonSerializer.Create(Constants.KeyGenSerializerSettings));
            var jTokens = jsonObject.Descendants().Where(p => p.Count() == 0);
            var keyValues = jTokens.Aggregate(
                new Dictionary<string, string>(),
                (
                    properties,
                    jToken) =>
                {
                    properties.Add(jToken.Path, jToken.ToString());
                    return properties;
                });

            return keyValues;
        }
    }
$signature = base64_encode(hash_hmac('sha256', $data, $secret, true));