ASP.NET Core 3.1 Razor Pages集成PayU后无法跳转至结果页问题
解决PayU支付后跳转RegisterConfirm.cshtml及获取交易详情的方案
一、先排查回调地址配置问题
PayU跳转失败核心原因基本是回调地址(success/failure URL)配置错误,必须满足以下要求:
- 提交给PayU的表单里,
success_url和failure_url必须是完整的绝对路径(PayU不支持相对路径),示例:<input type="hidden" name="success_url" value="https://你的域名/RegisterConfirm" /> <input type="hidden" name="failure_url" value="https://你的域名/RegisterConfirm" /> - 本地调试时,要用ngrok这类工具把本地端口映射为公网地址,否则PayU无法访问你的localhost页面。
- 确认RegisterConfirm页的路由正确:Razor Pages默认路由是
/页面文件名,如果有自定义路由,要和回调地址完全匹配。
二、配置RegisterConfirm页接收PayU回调参数
PayU会通过POST请求把交易详情发送到回调地址,你需要在RegisterConfirm的PageModel中处理POST请求并验证签名(防止伪造请求)。
1. RegisterConfirm.cshtml.cs 核心代码
public class RegisterConfirmModel : PageModel { public TransactionResult Transaction { get; set; } public async Task<IActionResult> OnPostAsync() { var formData = Request.Form; // 先验证签名,这一步必须做 if (!ValidatePayUSignature(formData)) { Transaction = new TransactionResult { Status = "无效请求" }; return Page(); } // 提取交易核心信息 Transaction = new TransactionResult { TransactionId = formData["txnid"], Status = formData["status"], Amount = formData["amount"], ProductType = formData["productinfo"], UserEmail = formData["email"], UserName = formData["firstname"] }; // 可选:把交易记录保存到数据库 // await _dbContext.PaymentTransactions.AddAsync(Transaction); // await _dbContext.SaveChangesAsync(); return Page(); } private bool ValidatePayUSignature(IFormCollection formData) { string merchantKey = "你的商户Key"; string merchantSalt = "你的商户Salt"; string receivedSignature = formData["hash"]; string status = formData["status"]; // 严格按照PayU文档的签名规则拼接字符串 string hashRawString = status.Equals("success", StringComparison.OrdinalIgnoreCase) ? $"{merchantSalt}|{status}||||||{formData["udf5"]}|{formData["udf4"]}|{formData["udf3"]}|{formData["udf2"]}|{formData["udf1"]}|{formData["email"]}|{formData["firstname"]}|{formData["productinfo"]}|{formData["amount"]}|{formData["txnid"]}|{merchantKey}" : $"{merchantKey}|{formData["txnid"]}|{formData["amount"]}|{status}||||||{formData["udf5"]}|{formData["udf4"]}|{formData["udf3"]}|{formData["udf2"]}|{formData["udf1"]}|{formData["email"]}|{formData["firstname"]}|{formData["productinfo"]}|{merchantSalt}"; // 生成SHA512哈希并对比 using var sha512 = System.Security.Cryptography.SHA512.Create(); byte[] hashBytes = sha512.ComputeHash(System.Text.Encoding.UTF8.GetBytes(hashRawString)); string generatedSignature = BitConverter.ToString(hashBytes).Replace("-", "").ToLower(); return generatedSignature.Equals(receivedSignature, StringComparison.OrdinalIgnoreCase); } } public class TransactionResult { public string TransactionId { get; set; } public string Status { get; set; } public string Amount { get; set; } public string ProductType { get; set; } public string UserEmail { get; set; } public string UserName { get; set; } }
2. RegisterConfirm.cshtml 页面展示
@page @model RegisterConfirmModel <h2>交易结果</h2> @if (Model.Transaction != null) { <div class="result-card"> <p><strong>交易ID:</strong> @Model.Transaction.TransactionId</p> <p><strong>交易状态:</strong> @(Model.Transaction.Status.Equals("success", StringComparison.OrdinalIgnoreCase) ? "<span style='color:green'>成功</span>" : "<span style='color:red'>失败</span>")</p> <p><strong>交易金额:</strong> @Model.Transaction.Amount</p> <p><strong>产品类型:</strong> @Model.Transaction.ProductType</p> <p><strong>用户信息:</strong> @Model.Transaction.UserName (@Model.Transaction.UserEmail)</p> </div> } else { <p>无法获取交易信息,请稍后重试</p> }
三、调试与排查要点
- 本地调试用ngrok生成公网地址,替换回调URL中的localhost部分,确保PayU能访问到你的页面。
- 登录PayU商户后台查看交易日志,里面会明确标注跳转失败的原因(比如地址不可达、返回404等)。
- 如果出现404:检查RegisterConfirm的文件命名是否规范(必须是
RegisterConfirm.cshtml和RegisterConfirm.cshtml.cs),路由是否正确。 - 如果签名验证失败:检查参数拼接顺序是否和PayU文档一致,udf参数如果未使用要填空字符串,注意大小写和特殊字符的编码。
内容的提问来源于stack exchange,提问作者devman
相关产品推荐
相关产品推荐

