I am building a web application using the ASP.NET C# Core 3.1 MVC and Razor pages. I am new to Razor pages.
I am integrating PayU payment interface in the application.
"Register.cshtml" form accepts UserFirstName, UserLastName, UserEmailAddress, UserPhoneNumber, ProducType and Amount from user and post the data along with PayU credentials (merchant key, salt) arranged in format - "key|txnid|amount|productinfo|firstname|email|udf1|udf2|udf3|udf4|udf5|udf6|udf7|udf8|udf9|udf10" to https://test.payu.in
Following error appears: -
Following is the code:
appsettings.json
"PayUMoneyKey": {
"MERCHANT_KEY": "gtKFFx",
"SALT": "4R38IvwiV57FwVpsgOvTXBdLE4tHUXFW",
"PAYU_BASE_URL": "https://test.payu.in",
"action": "",
"hashSequence": "key|txnid|amount|productinfo|firstname|email|udf1|udf2|udf3|udf4|udf5|udf6|udf7|udf8|udf9|udf10"
},
Register,chtml
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
if (ModelState.IsValid)
{
string strUserFirstName = UserFirstName;
string strUserLastName = UserLastName;
string strUserEmailAddress = UserEmailAddress;
string strUserPhoneNumber = UserPhoneNumber;
string strProducType = ProducType;
string strAmount = Amount;
returnUrl = returnUrl ?? Url.Content("~/");
objappdbcont = new AppDbContext();
try
{
string[] hashVarsSeq;
string hash_string = string.Empty;
Random rnd = new Random();
string strHash = Generatehash512(rnd.ToString() + DateTime.Now);
txnid1 = strHash.ToString().Substring(0, 20);
mkey1 = _configuration.GetSection("PayUMoneyKey").GetSection("MERCHANT_KEY").Value;
msalt1 = _configuration.GetSection("PayUMoneyKey").GetSection("SALT").Value;
hashVarsSeq = _configuration.GetSection("PayUMoneyKey").GetSection("hashSequence").Value.Split('|');
hash_string = "";
foreach (string hash_var in hashVarsSeq)
{
if (hash_var == "key")
{
hash_string = hash_string + mkey1;
hash_string = hash_string + '|';
}
else if (hash_var == "txnid")
{
hash_string = hash_string + txnid1;
hash_string = hash_string + '|';
}
else if (hash_var == "amount")
{
hash_string = hash_string + Convert.ToDecimal(strAmount).ToString("g29");
hash_string = hash_string + '|';
}
else if (hash_var == "email")
{
hash_string = hash_string + strUserEmailAddress;
hash_string = hash_string + '|';
}
else if (hash_var == "firstname")
{
hash_string = hash_string + strUserFirstName;
hash_string = hash_string + '|';
}
else if (hash_var == "productinfo")
{
hash_string = hash_string + strProducType;
hash_string = hash_string + '|';
}
else
{
hash_string = hash_string + '|';
}
}
hash_string += msalt1;// appending SALT
hash1 = Generatehash512(hash_string).ToLower(); //generating hash
action1 = _configuration.GetSection("PayUMoneyKey").GetSection("PAYU_BASE_URL").Value + "/_payment";// setting URL
string strUserFirstName = UserFirstName;
string strUserLastName = UserLastName;
string strUserEmailAddress = UserEmailAddress;
string strUserPhoneNumber = UserPhoneNumber;
string strProducType = ProducType;
string strAmount = Amount;
string strDummy = "test";
System.Collections.Hashtable data = new System.Collections.Hashtable(); // adding values in gash table for data post
data.Add("hash", hash1);
data.Add("txnid", txnid1);
data.Add("key", mkey1);
data.Add("salt", msalt1);
string AmountForm = Convert.ToDecimal(strAmount.Trim()).ToString("g29");// eliminating trailing zeros
data.Add("amount", AmountForm);
data.Add("firstname", strUserFirstName);
data.Add("email", strUserEmailAddress);
data.Add("phone", strUserPhoneNumber);
data.Add("productinfo", strProducType);
data.Add("surl", "http://localhost:51600/RegisterConfirm");
data.Add("furl", "http://localhost:51600/RegisterConfirm");
data.Add("lastname", strUserLastName);
data.Add("curl", "");
data.Add("address1", strDummy);
data.Add("address2", strDummy);
data.Add("city", strDummy);
data.Add("state", strDummy);
data.Add("country", strDummy);
data.Add("zipcode", strDummy);
data.Add("udf1", "");
data.Add("udf2", "");
data.Add("udf3", "");
data.Add("udf4", "");
data.Add("udf5", "");
data.Add("pg", "");
string strForm = PreparePOSTForm(action1, data);
return Content(strForm, System.Net.Mime.MediaTypeNames.Text.Html);
}
catch (Exception ex)
{}
}
return Page();
}
private string PreparePOSTForm(string url, System.Collections.Hashtable data) // post form
{
//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 (System.Collections.DictionaryEntry key in data)
{
strForm.Append("<input type=\"hidden\" name=\"" + key.Key +
"\" value=\"" + key.Value + "\">");
}
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 string Generatehash512(string text)
{
byte[] message = Encoding.UTF8.GetBytes(text);
UnicodeEncoding UE = new UnicodeEncoding();
byte[] hashValue;
SHA512Managed hashString = new SHA512Managed();
string hex = "";
hashValue = hashString.ComputeHash(message);
foreach (byte x in hashValue)
{
hex += String.Format("{0:x2}", x);
}
return hex;
}
RegisterConfirm
public class RegisterConfirmModel : PageModel
{
public RegisterConfirmModel(
IConfiguration configuration)
{
_configuration = configuration;
}
public ActionResult OnGet(Microsoft.AspNetCore.Http.IFormCollection collection)
{
try
{
ViewData["Name"] = collection["hash"];
return Page();
}
catch
{
return Page();
}
}
Question: How to redirect from PayU Payment to ( success and failure cshtml page) RegisterConfirm.cshtml and retrieve transaction details?
The error "This page isn't working right now" was shown because the request posted from PayU didn't had RequestVerificationToken.
Request Verification in ASP.NET Razor Pages is a mechanism designed to prevent possible Cross Site Request Forgery attacks, also referred to by the acronyms XSRF and CSRF.
The Razor pages MVC framework expects the "RequestVerificationToken" as part of the posted request. The framework uses this to prevent possible CSRF attacks. If the request does not have this information, the framework will return the HTTP Error 400 (bad request).
To solve this issue, either RequestVerificationToken should be in the posted form data or the Razor page should bypass the token check
1. Include the token in header -
headers:
{
"RequestVerificationToken": $('input:hidden[name="__RequestVerificationToken"]').val()
},
OR
2. Bypass the checks by adding the IgnoreAntiforgeryTokenAttribute to the relevant PageModel class (not a handler method):
[IgnoreAntiforgeryToken(Order = 1001)]
public class RegisterConfirmModel : PageModel
When the token check was bypassed the page RegisterConfirm.cshtml was loaded.