Post Redirect to URL with post data

KJSR picture KJSR · Aug 5, 2015 · Viewed 25.1k times · Source

I am working on a post redirect for a payment provider and trying to pass form data to their secure URL.

I am doing this in kentico 8 by using their custom payment gateway method as shown here https://docs.kentico.com/display/K8/Creating+a+custom+payment+gateway

So in the custom payment class I prepared the data to be passed to the payment provider in a 'Form' format with hidden fields using this tutorial http://www.codeproject.com/Articles/37539/Redirect-and-POST-in-ASP-NET

However I am not able to figure out on how to redirect to the secure URL with the form data?

Here is my code so far.

I have tried Response.Redirect however it is a GET function instead of POST.

using System;
using System.Collections;
using System.Collections.Specialized;
using System.Configuration;
using CMS;
using CMS.Base;
using CMS.EcommerceProvider;
using CMS.Helpers;
using System.Security.Cryptography;
using System.Web;
using System.Web.Security;
using System.Text;
using System.IO;
using System.Net;
using System.Web.UI;


[assembly: RegisterCustomClass("CustomGateway", typeof(CustomGateway))]

public class CustomGateway : CMSPaymentGatewayProvider
{


/// <summary>
/// Process payment.
/// </summary>
public override void ProcessPayment()
{        
    // Get payment gateway url

    string url = "https://epage.payandshop.com/epage.cgi";
    if (url != "")
    {
        NameValueCollection postData = getRealexData();
        RedirectAndPOST(url, postData);
    }
    else
    {
        // Show error message - payment gateway url not found
        ErrorMessage = "Unable to finish payment: Payment gateway url not found.";
        // Update payment result
        PaymentResult.PaymentDescription = ErrorMessage;
        PaymentResult.PaymentIsCompleted = false;
        // Update order payment result in database
        UpdateOrderPaymentResult();
    }
}

public static void RedirectAndPOST(string destinationUrl, NameValueCollection data)
{
    //Prepare the Posting form
    string strForm = PreparePOSTForm(destinationUrl, data);

    HttpContext.Current.Response.Write(strForm);
    HttpContext.Current.Response.End();
}

private static String PreparePOSTForm(string url, NameValueCollection data)
{
    //Set a name for the form
    string formID = "PostForm";
    //Build the form using the specified data to be posted.
    StringBuilder strForm = new StringBuilder();
    strForm.Append("<form id=\"" + formID + "\" name=\"" + 
                    formID + "\" action=\"" + url + 
                    "\" method=\"POST\">");

    foreach (string key in data)
    {
        strForm.Append("<input type=\"hidden\" name=\"" + key + 
                        "\" value=\"" + data[key] + "\">");
    }

    strForm.Append("</form>");
    //Build the JavaScript which will do the Posting operation.
    StringBuilder strScript = new StringBuilder();
    strScript.Append("<script language=\"javascript\">");
    strScript.Append("var v" + formID + " = document." + 
                        formID + ";");
    strScript.Append("v" + formID + ".submit();");
    strScript.Append("</script>");
    //Return the form and the script concatenated.
    //(The order is important, Form then JavaScript)
    return strForm.ToString() + strScript.ToString();
}

public NameValueCollection getRealexData()
{
    //format the date expected by Realex
    string timestamp = RealexDateFormatter.DateFormatForRealex();

    //take the MerchantID and Shared Secret from the web.config
    string merchantid = ConfigurationManager.AppSettings["RealexMerchantID"];
    string secret = ConfigurationManager.AppSettings["RealexSecret"];

    // Order Info
    int orderid = ShoppingCartInfoObj.OrderId;
    string stringorderid = Convert.ToString(orderid);
    string curr = ShoppingCartInfoObj.Currency.CurrencyCode;
    double amount = ShoppingCartInfoObj.TotalPrice;
    amount = Convert.ToInt32(amount);
    string prepareMD5 = timestamp + "." + merchantid + "." + orderid + "." + amount + "." + curr;

    //generate the md5 Hash
    MD5 md5 = new MD5CryptoServiceProvider();

    string temp1 = GetMD5Hash(prepareMD5);
    temp1 = temp1.ToLower();
    string temp2 = temp1 + "." + secret;
    string md5hash = GetMD5Hash(temp2);
    md5hash = md5hash.ToLower();

    NameValueCollection data = new NameValueCollection();

    data.Add("MERCHANT_ID", merchantid);
    data.Add("ORDER_ID", stringorderid);
    data.Add("CURRENCY", curr);
    data.Add("AMOUNT", amount.ToString());
    data.Add("TIMESTAMP", timestamp);
    data.Add("MD5HASH", md5hash);
    data.Add("AUTO_SETTLE_FLAG", "1");

    return data;
}

public static String GetMD5Hash(String TextToHash)
{
    //Check wether data was passed
    if ((TextToHash == null) || (TextToHash.Length == 0))
    {
        return String.Empty;
    }

    //Calculate MD5 hash
    MD5 md5 = new MD5CryptoServiceProvider();

    // Create a new Stringbuilder to collect the bytes 
    // and create a string.
    byte[] data = md5.ComputeHash(Encoding.UTF8.GetBytes(TextToHash));

    StringBuilder sBuilder = new StringBuilder();

    // Loop through each byte of the hashed data  
    // and format each one as a hexadecimal string. 
    for (int i = 0; i < data.Length; i++)
    {
        sBuilder.Append(data[i].ToString("x2"));
    }
    return sBuilder.ToString();
}

}

Answer

Jerreck picture Jerreck · Aug 5, 2015

Take a look at this answer from a similar question. I would recommend using Method 3 in that answer. By creating an asynchronous call, you could wait for a response back and either redirect on a successful response with Response.Redirect(), or notify the user of any errors.