views:

64

answers:

1

Guys apologize me if the question is less organized and less clear. I am in hurry :(

My web app has payment form that need to be submitted to another ASP.NET page (lets call it http://vendor.com/getpay.aspx) residing on another server.

That page will do some mumbo-jumbo works and then redirects it to the acutal payment gateway site.

when i post my payment form to getpay.aspx via simple HTML form, it works and redirects fine.

if i change the form and its hidden inputs to server side controls, it doesn't work. their page is throwing viewstate exception.

  1. I need the form hidden inputs to be server controls so that i can bind some values generated by my code behind.(i think i can do this like the classic asp way using <%= %>, but it is like going back in standard!)
  2. I tried HttpWebRequest in the code behind, it posts the form but the browser doesn't redirect to Payment Gateway page.
  3. I am posting the payment info over non https, how can i prevent the user tampering with the posted data?.
  4. I want to validate the payment form in the backend then post it, i couldn't trust the user input data.
  5. Also the result was returned to my redirect page with query strings appended. It is also happening over the non https. how much i can trust this redirect data?

Thx much

+3  A: 

Generate your form by clearing the Response and rewriting the html HTTP form out into the cleared response. When I get home I will trawl through my old code and provide an example.

EDIT: OK here is my code, I had to recreate because I am still at work but it goes a little like this:

Create an intermediate page to capture your variables from the ASPX page and then use this to send as a 'simple' form:

        protected void Page_Load(object sender, EventArgs e)
        {

            // Capture the post to this page
            IDictionary<string, string> variables = new Dictionary<string, string>();

            variables.Add("test", Request.Form["test"]); // collect all variables after checking they exist

            RewriteContent(variable);
        }

        public void RewriteContent(IDictionary<string, string> variables)
        {
            string formContent = @"
    <html>
        <head>
            <title>My Form</title>
        </head>
        <body>
            <form action='' method=''>";

            foreach (KeyValuePair<string, string> keyVal in variables)
            {
                formContent += @"<input type='" + keyVal.Key + "' value='" + keyVal.Value + "' />";
            }

        formContent += @"
            </form>
        </body>
    </html>"; // Add either an auto post in a javascript or an explicit submit button

            Response.Clear();
            Response.Write(formContent);
            Response.Flush();
            Response.End();
        }

EDIT 2: Sorry I just realised I have not answered the other questions.

Q3/Q4/Q5. If you are not using https you cannot really stop tampering or be sure the response is correct but you can restrict the chance it is bogus. This can be achieved by hashing the values with a secret that is shared at your end and the destination, and then when you get the response you should hash the values and compare to the hash that is sent back to you before you accept that it is valid.

Most payment mechanisms are verified in this manner usually with an MD5 or SHA1 hash you can find more info on the following links:

http://msdn.microsoft.com/en-us/library/system.security.cryptography.sha1.aspx http://www.developerfusion.com/code/4601/create-hashes-md5-sha1-sha256-sha384-sha512/ http://snippets.dzone.com/posts/show/5816

EDIT 3: Doing some encryption now and thought I would share some code with you (because I am nice like that). Might give you an idea of what to do and you can probably code better than me so just tidy up my mess a bit :)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using log4net;

namespace MyCompany.Cipher
{
    private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

    public string GenerateSha1HashForString(string valueToHash, EncodeStyle encodeStyle)
    {
        string hashedString = string.Empty;

        try
        {
            hashedString = SHA1HashEncode(Encoding.UTF8.GetBytes(valueToHash), encodeStyle);
        }
        catch (Exception ex)
        {
            if (log.IsErrorEnabled) { log.Error(string.Format("{0}\r\n{1}", ex.Message, ex.StackTrace)); }
            throw new Exception("Error trying to hash a string; information can be found in the error log", ex);
        }

        return hashedString;
    }

    private string ByteArrayToString(byte[] bytes, EncodeStyle encodeStyle)
    {
        StringBuilder output = new StringBuilder(bytes.Length);

        if (EncodeStyle.Base64 == encodeStyle)
        {
            return Convert.ToBase64String(bytes);
        }

        for (int i = 0; i < bytes.Length; i++)
        {
            switch (encodeStyle)
            {
                case EncodeStyle.Dig:
                    //encode to decimal with 3 digits so 7 will be 007 (as range of 8 bit is 127 to -128)
                    output.Append(bytes[i].ToString("D3"));
                    break;
                case EncodeStyle.Hex:
                    output.Append(bytes[i].ToString("X2"));
                    break;
            }
        }

        return output.ToString();
    }

    private string SHA1HashEncode(byte[] valueToHash, EncodeStyle encode)
    {
        SHA1 a = new SHA1CryptoServiceProvider();
        byte[] arr = new byte[60];
        string hash = string.Empty;

        arr = a.ComputeHash(valueToHash);
        hash = ByteArrayToString(arr, encode);

        return hash;
    }
}

Put it in a class some where that your project can see and it can generate an SHA1 hash based on a string value by calling the public method.

Monkieboy
Thx for the response... i will be waiting for the code sample..
vijay
I don't know if this works or not, but this is a very detailed answer. Well done sir!
Reddog
Thank you Reddog.
Monkieboy
sorry for the late reply. @Monkieboy Thank You, I did as in the sample code..but haven't done anything about the security part.. schedule is pretty tight they just want the damn thing working. I am discussing with them setting up the SSL, if the time not permits, will finish the code and declare disowning it. God bless the client!!!
vijay
Haha goodluck, remember you will get no thanks even when you go the extra mile, clients rarely understand :)
Monkieboy