如何在ASP.Net MVC中实现Moneris Checkout?
ASP.Net MVC 集成 Moneris Checkout 实现方案
1. 前期准备
- 从Moneris商户后台获取商户ID、API密钥,明确当前使用测试环境还是生产环境(二者API地址不同)
- 梳理业务规则:确认支持的支付方式、订单金额限制、支付后的状态流转逻辑
2. 后端核心实现(C#)
2.1 封装Moneris工具类
创建工具类处理API请求与签名生成,避免重复代码:
public class MonerisHelper { private readonly string _merchantId; private readonly string _apiKey; private readonly string _baseUrl; public MonerisHelper(string merchantId, string apiKey, bool isProduction) { _merchantId = merchantId; _apiKey = apiKey; _baseUrl = isProduction ? "https://www3.moneris.com/HPPDP/index.php" : "https://esqa.moneris.com/HPPDP/index.php"; } // 生成Moneris要求的HMAC-SHA256签名 private string GenerateSignature(Dictionary<string, string> parameters) { var sortedParams = parameters.OrderBy(kv => kv.Key).Select(kv => $"{kv.Key}={kv.Value}"); var rawString = string.Join("&", sortedParams) + _apiKey; using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(_apiKey)); var hashBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(rawString)); return BitConverter.ToString(hashBytes).Replace("-", "").ToLower(); } // 初始化支付会话,获取支付凭证ID public async Task<string> InitiateCheckout(decimal amount, string orderId, string callbackUrl, string returnUrl) { var parameters = new Dictionary<string, string> { ["merchant_id"] = _merchantId, ["api_token"] = _apiKey, ["amount"] = amount.ToString("F2"), ["order_id"] = orderId, ["callback_url"] = callbackUrl, ["return_url"] = returnUrl, ["action"] = "preload" }; parameters["hash"] = GenerateSignature(parameters); using var client = new HttpClient(); var content = new FormUrlEncodedContent(parameters); var response = await client.PostAsync(_baseUrl, content); var responseContent = await response.Content.ReadAsStringAsync(); // 解析XML响应获取支付凭证 var doc = XDocument.Parse(responseContent); return doc.Descendants("ticket").FirstOrDefault()?.Value; } }
2.2 控制器Action处理支付发起
在订单控制器中添加Action,为前端生成支付会话:
public class OrderController : Controller { private readonly MonerisHelper _monerisHelper; public OrderController() { // 建议从配置文件读取商户信息,禁止硬编码 _monerisHelper = new MonerisHelper("YOUR_MERCHANT_ID", "YOUR_API_KEY", isProduction: false); } public async Task<ActionResult> StartPayment(int orderId) { // 从数据库获取订单详情 var order = GetOrderFromDatabase(orderId); var callbackUrl = Url.Action("PaymentCallback", "Order", null, Request.Scheme); var returnUrl = Url.Action("PaymentResult", "Order", new { orderId }, Request.Scheme); var paymentTicket = await _monerisHelper.InitiateCheckout(order.TotalAmount, order.OrderNumber, callbackUrl, returnUrl); ViewBag.PaymentTicket = paymentTicket; ViewBag.OrderId = orderId; return View(); } }
3. 前端集成(Razor视图)
在支付页面嵌入Moneris JS SDK,渲染支付按钮:
@{ ViewBag.Title = "订单支付"; } <h3>请完成支付</h3> <!-- 支付组件容器 --> <div id="moneris-payment-box"></div> <script src="https://www3.moneris.com/HPPDP/js/monerisCheckout.js"></script> <script> monerisCheckout({ ticket: '@ViewBag.PaymentTicket', container: 'moneris-payment-box', buttonText: '确认支付', buttonStyle: { backgroundColor: '#28a745', color: '#fff', borderRadius: '4px', padding: '10px 20px' }, onSuccess: function() { window.location.href = '@Url.Action("PaymentResult", "Order", new { orderId = ViewBag.OrderId })'; }, onError: function(err) { console.error('支付异常:', err); alert('支付失败,请稍后重试'); } }); </script>
4. 异步回调处理
创建Action接收Moneris支付结果,必须验证签名防止伪造请求:
[HttpPost] public async Task<ActionResult> PaymentCallback() { var formParams = Request.Form.AllKeys.ToDictionary(k => k, k => Request.Form[k]); var receivedHash = formParams["hash"]; formParams.Remove("hash"); // 验证签名 var helper = new MonerisHelper("YOUR_MERCHANT_ID", "YOUR_API_KEY", isProduction: false); var generatedHash = helper.GenerateSignature(formParams); if (receivedHash != generatedHash) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } // 解析支付状态 var orderId = formParams["order_id"]; var isSuccess = formParams["response_code"] == "00"; // 00表示支付成功 // 更新订单状态到数据库 UpdateOrderPaymentStatus(orderId, isSuccess); // 返回成功响应给Moneris return Content("OK"); }
5. 关键注意事项
- 订单唯一性:每个订单号必须唯一,避免重复支付
- 签名验证:发起支付和处理回调时必须做签名验证,拒绝伪造请求
- 环境切换:生产环境务必切换到正式API地址和生产密钥,测试用Moneris提供的测试卡号(如4242424242424242)
- 异常处理:添加HTTP超时、响应解析失败等异常捕获,保证系统稳定性
内容的提问来源于stack exchange,提问作者Shahid Iqbal
相关产品推荐
相关产品推荐

