You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 10:05:17