using System.Collections.Generic;
using System.Security.Cryptography;
using System.ComponentModel.DataAnnotations;
public static void Main()
var nonce = Guid.NewGuid().ToString();
var merchantAccountId = "EGate_SecureCoAccountId_Purchase";
var hexKey = "c982b82023d29f27f112c2931739a31438fd9c44bd6b9877d851f9b47635797f";
var hppRequest = new HPPRequest{
BearerToken = "d08a2cc93a97ecc487645c1ac393a642", TransactionType = "purchase", SecureCoAccountId = merchantAccountId,
RequestedAmount = "10.00", Token = "", RequestType = "semafone",
RequestID = Guid.NewGuid().ToString(), TransactionTimestamp = "3/07/2018 1:37:22 AM"
string hppMessage = FormatRequest(hppRequest);
string httpSignature = GenerateHmacSignature(hexKey, hppMessage, null, nonce);
hppRequest.SignatureHmac = httpSignature;
hppRequest.SignatureNonce = nonce;
Console.WriteLine("HMAC Details \n ");
Console.WriteLine("Secret Key - " + hexKey + "\n ");
Console.WriteLine("Message Signature - " + hppRequest.SignatureHmac + "\n ");
Console.WriteLine("Nonce - " + hppRequest.SignatureNonce + "\n ");
Console.WriteLine("HPP Request - " + FormatRequest(hppRequest));
public static string FormatRequest(HPPRequest hppRequest)
dynamic request = new System.Dynamic.ExpandoObject();
request.RequestedAmount = hppRequest.RequestedAmount;
request.SecureCoAccountId = hppRequest.SecureCoAccountId;
request.RequestType = hppRequest.RequestType;
request.OrderNumber = hppRequest.OrderNumber;
request.FirstName = hppRequest.FirstName;
request.LastName = hppRequest.LastName;
request.RequestID = hppRequest.RequestID;
request.TransactionType = hppRequest.TransactionType;
request.SemafoneCrn = hppRequest.SemafoneCrn;
request.SemafoneSessionID = hppRequest.SemafoneSessionID;
request.SemafoneEndpoint = hppRequest.SemafoneEndpoint;
request.BearerToken = hppRequest.BearerToken;
request.Token = hppRequest.Token;
request.AgentID = hppRequest.AgentID;
request.SignatureHmac = hppRequest.SignatureHmac;
request.SignatureNonce = hppRequest.SignatureNonce;
if (hppRequest.RequestType.ToLower() == "ecommerce")
request.SuccessCallbackUrl = hppRequest.SuccessCallbackUrl;
request.ErrorCallbackUrl = hppRequest.ErrorCallbackUrl;
request.SuccessCallbackUrl = hppRequest.CancellationCallbackUrl;
if (!string.IsNullOrEmpty(hppRequest.SuccessCallbackUrl))
request.SuccessCallbackUrl = hppRequest.SuccessCallbackUrl;
if (!string.IsNullOrEmpty(hppRequest.ErrorCallbackUrl))
request.ErrorCallbackUrl = hppRequest.ErrorCallbackUrl;
if (!string.IsNullOrEmpty(hppRequest.CancellationCallbackUrl))
request.CancellationCallbackUrl = hppRequest.CancellationCallbackUrl;
StringBuilder signableRequest = new StringBuilder();
foreach (var property in (IDictionary<string, object>)request)
signableRequest.Append(property.Key + "=" + property.Value).Append("&");
return signableRequest.ToString().TrimEnd(new char[]{'&'});
public static string GenerateHmacSignature(string hexKey, string message, string epochUtcTime = null, string nonce = null)
if (String.IsNullOrEmpty(hexKey))
throw new Exception("HexKey is null or Empty.");
if (!IsValidHexString(hexKey))
throw new Exception("HexKey contains non-hexidecimal characters.");
byte[] byteKey = HexStringToByteArray(hexKey);
if (byteKey.Length != 32 && byteKey.Length != 64)
throw new Exception("Key length is not 256 or 512 bits");
var completeMessage = (String.IsNullOrEmpty(nonce) ? "nonce=&" : "nonce=" + HttpUtility.UrlEncode(nonce) + "&") + (String.IsNullOrEmpty(epochUtcTime) ? "epochUtcTime=&" : "epochUtcTime=" + HttpUtility.UrlEncode(epochUtcTime) + "&") + message;
using (HMACSHA256 hmac = new HMACSHA256(byteKey))
using (MemoryStream inStream = new MemoryStream(Encoding.UTF8.GetBytes(completeMessage)))
hashValue = hmac.ComputeHash(inStream);
return ByteArrayToHexString(hashValue);
private static bool IsValidHexString(IEnumerable<char> hexString)
return hexString.Select(currentCharacter => (currentCharacter >= '0' && currentCharacter <= '9') || (currentCharacter >= 'a' && currentCharacter <= 'f') || (currentCharacter >= 'A' && currentCharacter <= 'F')).All(isHexCharacter => isHexCharacter);
public static byte[] HexStringToByteArray(String hex)
int NumberChars = hex.Length;
byte[] bytes = new byte[NumberChars / 2];
for (int i = 0; i < NumberChars; i += 2)
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
public static string ByteArrayToHexString(byte[] ba)
StringBuilder hex = new StringBuilder(ba.Length * 2);
hex.AppendFormat("{0:x2}", b);
public static void PostData(HPPRequest hppRequest){
WebRequest request = WebRequest.Create ("http://sandbox-payments.secureco.co/home/");
string postData = FormatRequest(hppRequest);
byte[] byteArray = Encoding.UTF8.GetBytes (postData);
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = byteArray.Length;
Stream dataStream = request.GetRequestStream ();
dataStream.Write (byteArray, 0, byteArray.Length);
WebResponse response = request.GetResponse ();
Console.WriteLine (((HttpWebResponse)response).StatusDescription);
dataStream = response.GetResponseStream ();
StreamReader reader = new StreamReader (dataStream);
string responseFromServer = reader.ReadToEnd ();
Console.WriteLine (responseFromServer);
public string OrderNumber
public string RequestedAmount
[Required(ErrorMessage = "SecureCo AccountID is required")]
public string SecureCoAccountId
[Required(ErrorMessage = "RequestID is required")]
[Required(ErrorMessage = "Transaction Type is required")]
public string TransactionType
public string TransactionTimestamp
public string SuccessCallbackUrl
public string CancellationCallbackUrl
public string ErrorCallbackUrl
[Required(ErrorMessage = "Request Type is required")]
public string RequestType
public string SignatureHmac
public string SignatureNonce
public string BearerToken
public string PostbackUrl
public bool IsHmacGenerated
[Required(ErrorMessage = "Hmac Key is required")]
public string SemafoneCrn
public string SemafoneSessionID
public string SemafoneEndpoint