使用 Sitefinity 电子商务实施 3D 安全

Implementing 3D Secure with Sitefinity Ecommerce

我想为通过网站进行的信用卡付款添加 3D 安全身份验证。我正在使用电子商务插件 Sitefinity 8 和 SagePay 作为支付处理器。

我已经创建了一个自定义支付提供商并且可以成功地将用户重定向到 3D 安全页面。我能够使用 SagePay 集成工具包(即从电子商务插件外部)执行对 SagePay 的第二次身份验证调用。但是,由于内部电子商务类功能的方式,我正在努力寻找一种方法来完成付款。

困难在于,如果需要 3D 安全身份验证,订单处理者会将付款视为拒绝,但似乎没有一种方法可以在不使用内置功能的情况下正确处理订单。根据我对电子商务库的检查,由于 internal 修饰符和具体实现,似乎无法扩展或修改这些 类。

认证完成后如何处理订单?有没有人通过电子商务成功实施 3D 安全?或者知道是否可行?

这是我目前的自定义支付提供商。

public class CustomSagePayProvider : SagePayProvider
{
    // Rest of code...

    protected override IPaymentResponse ParseReponse(string uniqueTransactionCode, string responseXml)
    {
        var paymentResponse = base.ParseReponse(uniqueTransactionCode, responseXml);

        if (Requires3DSecure(paymentResponse))
        {
            var responseFields = GetResponseAsDictionary(responseXml);
            Set3DSecureFields(responseFields, paymentResponse);
        }

        return paymentResponse;
    }

    private bool Requires3DSecure(IPaymentResponse paymentResponse)
    {
        return paymentResponse.GatewayCSCResponse == "OK";
    }

    private void Set3DSecureFields(Dictionary<string, string> responseFields, IPaymentResponse paymentResponse)
    {
        var postValues = new NameValueCollection();
        postValues.Add("MD", responseFields.ContainsKey("MD") ? responseFields["MD"] : string.Empty);
        postValues.Add("PAReq", responseFields.ContainsKey("PAReq") ? responseFields["PAReq"] : string.Empty);

        paymentResponse.GatewayRedirectUrlPostValues = postValues;
        paymentResponse.GatewayRedirectUrl = responseFields.ContainsKey("ACSURL") ? responseFields["ACSURL"] : string.Empty;
    }
}

这是使用 .NET SagePay 集成套件的 3D 安全支付流程

using SagePay.IntegrationKit;
using SagePay.IntegrationKit.Messages;

// Rest of code

var sagePay = new SagePayIntegration();
IThreeDAuthRequest request = new DataObject();
request.Md = Request.Form["MD"];
request.PaRes = Request.Form["PaRes"];
sagePay.RequestQueryString = sagePay.BuildQueryString(request, ProtocolMessage.THREE_D_AUTH_REQUEST, ProtocolVersion.V_223);
sagePay.ResponseQueryString = sagePay.ProcessWebRequestToSagePay("https://test.sagepay.com/gateway/service/direct3dcallback.vsp", sagePay.RequestQueryString);
var result = sagePay.GetDirectPaymentResult(sagePay.ResponseQueryString);

if (result.Status == ResponseStatus.OK)
{
    // Process order
}

我能够通过将第二次身份验证调用视为异地支付并将 IOffsitePaymentProcessorProvider 接口添加到我的支付提供商 class

来添加 3D 安全身份验证
public class CustomSagePayProvider : SagePayProvider, IOffsitePaymentProcessorProvider
{
    // Triggered after payments that have been 3D Secure authenticated
    public IPaymentResponse HandleOffsiteNotification(int orderNumber, HttpRequest request, PaymentMethod paymentMethod)
    {
        var paymentResponse = new PaymentResponse() { IsOffsitePayment = true };

        var sagePay = new SagePayIntegration();
        var result = sagePay.GetDirectPaymentResult(request.Params.ToString());

        if (result.ThreeDSecureStatus == ThreeDSecureStatus.OK)
        {
            paymentResponse.IsSuccess = true;
            paymentResponse.GatewayTransactionID = result.TxAuthNo.ToString();
        }

        return paymentResponse;
    }

    public IPaymentResponse HandleOffsiteReturn(int orderNumber, HttpRequest request, PaymentMethod paymentMethod)
    {
        throw new NotImplementedException();
    }

我在第一次请求身份验证时将通知 url 作为 termUrl 值 post 中的查询字符串参数传递给 SagePay (url 必须是 /Ecommerce/offsite-payment-notification/ 才能使用内置越位支付通知处理程序)。

var notificationUrl = request.Url.GetLeftPart(UriPartial.Authority) + "/Ecommerce/offsite-payment-notification/";

在用户认证完成后SagePay的回调中,我使用SagePay集成包对认证结果进行了处理

var sagePay = new SagePayIntegration();  
IThreeDAuthRequest request = new DataObject();
request.Md = md;
request.PaRes = paRes;
sagePay.RequestQueryString = sagePay.BuildQueryString(request, ProtocolMessage.THREE_D_AUTH_REQUEST, ProtocolVersion.V_223);
sagePay.ResponseQueryString = sagePay.ProcessWebRequestToSagePay("https://test.sagepay.com/gateway/service/direct3dcallback.vsp", sagePay.RequestQueryString);

return sagePay.GetDirectPaymentResult(sagePay.ResponseQueryString);

最后,我通过 posting 到 url www.mysite.com/Ecommerce/offsite-payment-notification/ 触发了 HandleOffsiteNotification 事件。这会将订单标记为已完成、更新库存水平并清理用户的购物篮。为简单起见,在此示例中,我使用 SagePay 集成工具包对象来构建查询字符串和 post 到 url.

var sagePay = new SagePayIntegration();   
var ordersManager = OrdersManager.GetManager();

var query = sagePay.ConvertSagePayMessageToNameValueCollection(ProtocolMessage.DIRECT_PAYMENT_RESULT, typeof(IDirectPaymentResult), result, ProtocolVersion.V_223);

// Required Sitefinity fields to trigger HandleOffsiteNotification in IOffsitePaymentProcessorProvider
query.Add("invoice", orderNumber.ToString());
query.Add("provider", ordersManager.Provider.Name);

var queryString = sagePay.BuildQueryString(query);

// Post 3d secure details to this site simulate an offsite payment processor response
sagePay.ProcessWebRequestToSagePay(notificationUrl, queryString);