1

So I can do the following POST submit and get redirected to the payment gateway site

@Html.BeginForm(null, null, FormMethod.Post, new { @action = "https://l33tpaymentgateway.com" })
{
    <input id="RefNo" name="RefNo" type="hidden" value="ABCDE" />
    <input id="Amount" name="Amount" type="hidden" value="300" />
    <input id="UserEmail" name="UserEmail" type="hidden" value="warheat1990@warheat1990.com" />
    <input id="Signature" name="Signature" type="hidden" value="1234567890" />
    <input id="ResponseURL" name="ResponseURL" type="hidden" value="http://warheat1990.com" />

    <input type="submit" value="submit"/>
}

Doing the above on user page is a bad idea (the data can be tampered with), I tried to do this on the server side instead. But I have no idea how to redirect the user.

public ActionResult SubmitPayment()
{
        using (var client = new HttpClient())
        {
            client.BaseAddress = new Uri("https://l33tpaymentgateway.com");
            var content = new FormUrlEncodedContent(new[] 
            {
                new KeyValuePair<string, string>("RefNo", "ABCDE"),
                new KeyValuePair<string, string>("Amount", "300"),
                new KeyValuePair<string, string>("UserEmail", "warheat1990@warheat1990.com"),
                new KeyValuePair<string, string>("Signature", "1234567890"),
                new KeyValuePair<string, string>("ResponseURL", "http://warheat1990.com")
            });
            var result = await client.PostAsync("", content).Result;
            if(result.IsSuccessStatusCode)
            {
                //redirect user, but I have no idea how               
            }
        }
}

Any help will be appreciated.

EDIT : THE DOCUMENTATION

Step 1. Merchant sends HTTPs Post Request containing payment details to l33tpaymentgateway
OPSG payment page. Payment Details contain the following fields:
• MerchantCode
• PaymentId
• RefNo
• Amount
• Currency
• ProdDesc
• UserName
• UserEmail
• UserContact
• Remark
• Signature (refer to 3.1)
• ResponseURL
• BackendURL
Step 2. User views and confirms payment details entered in Step 1. For credit card
payment, the user will need to key-in credit card information.
Step 3. User continues to fill in Username and Password at bank website (for non
credit card payment)
Step 4. User selects the account to debit the payment. (for non credit card payment)
Step 5. User confirms the payment. If yes, go to next step. (for non credit card
payment)
Step 6. User views and prints the payment detail. (for non credit card payment)
Step 7. Response is returned to the l33tpaymentgateway OPSG website indicating a successful or
failed transaction.
Step 8. l33tpaymentgateway OPSG response back the payment status to merchant with a
signature
Step 9. For successful payment transaction, the merchant needs to compare the
signature from l33tpaymentgateway OPSG. Refer to (3.2)

HTTP POST example from the documentation which is a big NO in my opinion from security standpoint.

<HTML>
    <BODY>
        <FORM method="post" name="ePayment" action="https://l33tpaymentgateway.com">
            <INPUT type="hidden" name="MerchantCode" value="ID00001">
            <INPUT type="hidden" name="PaymentId" value="1">
            <INPUT type="hidden" name="RefNo" value="A00000001">
            <INPUT type="hidden" name="Amount" value="300">
            <INPUT type="hidden" name="Currency" value="USD">
            <INPUT type="hidden" name="ProdDesc" value="Photo Print">
            <INPUT type="hidden" name="UserName" value="John Tan">
            <INPUT type="hidden" name="UserEmail" value="john@hotmail.com">
            <INPUT type="hidden" name="UserContact" value="0126500100">
            <INPUT type="hidden" name="Remark" value="">
            <INPUT type="hidden" name="Lang" value="UTF-8">
            <INPUT type="hidden" name="Signature" value="Q/iIMzpjZCrhJ2Yt2dor1PaFEFI=">
            <INPUT type="hidden" name="ResponseURL" value="http://www.test.com/payment/response.asp">
            <INPUT type="hidden" name="BackendURL" value="http://www.test.com/payment/backend_response.asp">
            <INPUT type="submit" value="Proceed with Payment" name="Submit">
        </FORM>
    </BODY>
</HTML>

Signature generate :

private string ComputeHash(string Key)
{
    SHA1CryptoServiceProvider objSHA1 = new SHA1CryptoServiceProvider();

    objSHA1.ComputeHash(System.Text.Encoding.UTF8.GetBytes(Key.ToCharArray));

    byte[] buffer = objSHA1.Hash;
    string HashValue = System.Convert.ToBase64String(buffer);

    return HashValue;
}

where Key is a combination of MerchantKey (similar to private key) + Merchant Code + RefNo + Amount

tickwave
  • 3,335
  • 6
  • 41
  • 82
  • I don't quite understand what you're trying to do. Where are you trying to redirect to? You can just use the return new Redriect(redirectUrl); – Rafi Oct 21 '15 at 10:49
  • This really isn't answerable in its current form. It all depends on how the "l33t payment gateway" was designed. If it returns a page that the user needs to interact with, you must store any cookies serverside in the user's session, return the returned HTML data to the user and handle the next post as well. **You don't want to do that though**, as a user should not have to provide their payment details to _your_ site. If the site responds with a redirect, where the URL contains some kind of token for this payment, it's trivial. – CodeCaster Oct 21 '15 at 10:50
  • server.redirect(URL) – Amit Soni Oct 21 '15 at 10:50
  • Possible duplicate of [.net mvc redirect to external url](http://stackoverflow.com/questions/1549324/net-mvc-redirect-to-external-url) – Ric Oct 21 '15 at 10:50
  • You don't really need to redirect. Just use an HttpClient to make your call to their site and post the data. – Stephen Brickner Oct 21 '15 at 10:51
  • @Stephen no, see my comment. That action most likely returns a page where the user must enter their payment details. You don't want to send your credit card info to this user's site. – CodeCaster Oct 21 '15 at 10:52
  • @Rafi: I'm trying to redirect to any link `l33tpaymentgateway` provide after a success POST like CodeCaster said. – tickwave Oct 21 '15 at 10:52
  • Generally speaking, the redirect models offered by most payment providers will not fit with what you are trying to do (i.e. they will expect a post from the client). Most will, however, support a 'signature' that allows a check to be performed to ensure critical fields have not been tampered with. – SpruceMoose Oct 21 '15 at 10:54
  • @Cal279 no, that is not correct. Payment providers _do_ expect a serverside post, for the exact reason OP mentions: you don't want to trust the client with the amount to be paid. – CodeCaster Oct 21 '15 at 10:55
  • @CodeCaster - are you confusing service based and redirect models? – SpruceMoose Oct 21 '15 at 10:55
  • @Cal279 I'm not confusing anything. You're making an absolute statement where it isn't clear at all which kind of payment provider OP uses. – CodeCaster Oct 21 '15 at 11:02
  • @CodeCaster - A general statement, but true, it might be supported. Documentation would be the best place to start. – SpruceMoose Oct 21 '15 at 11:07
  • @CodeCaster: hey man, can you repost your answer? The documentation I got from the payment gateway company is something like `Merchant sends HTTPs Post Request containing payment details to l33tpaymentgateway OPSG payment page. Payment Details contain the following fields: RefNo, Amount, blah blah blah` and the example from the documentation is the HTML example I posted in the thread which is a big no no in security standpoint. – tickwave Oct 21 '15 at 11:16
  • I just add the documentation in my post, please read the updated post. – tickwave Oct 21 '15 at 11:20
  • That is really crappy documentation. Inspect the actual response when you perform the post. Do you get a redirect response, or an HTML page? There is mention of a signature field, so @Cal279 may be right in that you _are_ supposed to just present a page with the shown fields to the user, and the signature field will prevent tampering. The form's `action` attribute will make the post go to the payment provider. – CodeCaster Oct 21 '15 at 11:22
  • @warheat1990 - 1) I'm assuming this is not all the documentation.... 2) So, assuming (1), have you read about the signature field? i.e. the one you post to them, not the one they send to you? – SpruceMoose Oct 21 '15 at 11:22
  • @Cal279: Yes, and there's no such thing as validate the result to make sure the result is not tampered with if you're wondering about that. – tickwave Oct 21 '15 at 11:23
  • @warheat1990 - Then what is it for/how is it generated? The validation would be on their (payment gateway's) side. – SpruceMoose Oct 21 '15 at 11:24
  • @Cal279: On a 2nd thoughts, you're right, the signature is generated by combining Merchant private key and Amount of payment (please read my updated post), that leads to my new question which is is SHA1 safe/good enough? – tickwave Oct 21 '15 at 11:30
  • That being said, i still think it's not a good idea because it forced me to expose the signature in html field. – tickwave Oct 21 '15 at 11:44
  • You can assume, that if it's a payment provider of any decent size, that they know what they're doing. Since your private key is secret, a user-visible hash of "$key+$amount" cannot be trivially altered by a malicious user. – CodeCaster Oct 21 '15 at 12:25

1 Answers1

-1

Updated your code below:

public ActionResult SubmitPayment()
    {
            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri("https://l33tpaymentgateway.com");
                var content = new FormUrlEncodedContent(new[] 
                {
                    new KeyValuePair<string, string>("RefNo", "ABCDE"),
                    new KeyValuePair<string, string>("Amount", "300"),
                    new KeyValuePair<string, string>("UserEmail", "warheat1990@warheat1990.com"),
                    new KeyValuePair<string, string>("Signature", "1234567890"),
                    new KeyValuePair<string, string>("ResponseURL", "http://warheat1990.com")
                });
                var result = await client.PostAsync("", content).Result;
                if(result.IsSuccessStatusCode)
                {
                    return Redirect(result.url);            
                }
            }
    }

I'm not sure what the result object is. But put into the parameter of the Redirect method the url to redirect to.

Rafi
  • 2,433
  • 1
  • 25
  • 33