史密斯写得好。我同意文档可以更直接。在过去的几周里做了我的头。对于您的 1),您需要发布文档中提到的所有必填字段。至 8) 您从 SagePay 获得更多数据。如下所示:
VPSProtocol=4.00
Status=OK
StatusDetail=0000 : The Authorisation was Successful.
VPSTxId={1B19CB3F-E553-0E69-CFD5-6D75B53753C1}
SecurityKey=UAW4ZETUK7
TxAuthNo=2261559
AVSCV2=SECURITY CODE MATCH ONLY
AddressResult=NOTMATCHED
PostCodeResult=NOTMATCHED
CV2Result=MATCHED
3DSecureStatus=OK
CAVV=Q042ZUZRWndDbjAyWHRjYUFkZ2c=
DeclineCode=00
ExpiryDate=1035
BankAuthCode=999778
至 9) 您可以通过检查从 SagePay 获得的 StatusDetails 来区分 3DSecure v1 和 3DSecure v2。
3DSv1 returns StatusDetail=2007
3DSv2 returns StatusDetail=2021
我在结帐页面调用的类文件中进行付款处理。该类将响应返回到结帐页面,其中包含我需要的详细信息。对于 v1 和 v2,它们是不同的。
For v1 I return:
return "v1" + Status + "&3DSecureStatus=" + s3DSecureStatus + "&MD=" + sMD + "&ACSURL=" + sACSURL + "&PAReq=" + sPAReq + "&VendorTxCode=" + o.OrderID;
For v2 I return:
return "v2" + Status + "&3DSecureStatus=" + s3DSecureStatus + "&VPSTxId=" + sVPSTxId + "&ACSURL=" + sACSURL + "&CReq=" + sCReq + "&VendorTxCode=" + o.OrderID;
这使我可以在结帐代码中采取相应的行动。
我将 v1 重定向到带有 iFrame 的页面。iFrame 加载之前在响应中收到的 ACSURL。这直接显示了“挑战”窗口。
这主要是因为 SagePay 接受带有 3DSv1 查询字符串的 URL 并期望 3DSv2 的表单发布。
v2 使用 iFrame 重定向到另一个页面。iFrame 首先在我的网站上加载一个页面:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="ChallengeiFrame.aspx.cs" Inherits="ac_ChallengeiFrame" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title></title>
</head>
<body>
<div id="content">
<div id="contentHeader">
Your Bank requires Authentication
</div>
<p>
Please click the button below to continue.
</p>
<form action="<%= sACSUrl %>" method="post">
<input type="hidden" name="creq" value="<%= sCReq %>" />
<input type="hidden" name="threeDSSessionData" value="<%= sVPSTxId %>" />
<input type="submit" value="Click to continue" />
</form>
</div>
</body>
</html>
单击按钮发布到 ACSURL 并显示质询窗口。客户填写密码并提交。银行响应您为 v1 分配的页面,它是 TermUrl,而对于 v2,它是 ThreeDSNotificationURL。
在这些页面上,您发布您需要发布的内容并处理来自 SagePay 的响应。如果一切顺利,付款已收到,您可以将客户重定向到感谢页面并完成订单。
基本上,我使用 2 组代码文件来处理 3DSv1 和 3DSv2。喜欢将其分开,一旦 3DSv1 停产,我只需删除这些文件并删除我的付款处理页面和结帐页面中的代码块。那么应该直截了当。
希望这可以帮助。
这里是 3DSecure v2 文档的链接:
DIRECT_Integration_and_Protocol_4_Guidelines.pdf
编辑
WebRequest和HttpWebResponse的三个DSNotificationURL代码:
/////////////////////////////////////////////////////////
//// This is to get the posted results from the bank
/////////////////////////////////////////////////////////
NameValueCollection coll;
coll = Request.Form;
/////////////////////////////////////////////////////////
string sSagePayUrl = "";
if (EcommerceSettings.bLiveTransactions()) //That's just some logic so I can control live or test at one place in a settings class file.
{
sSagePayUrl = "https://live.sagepay.com/gateway/service/direct3dcallback.vsp?";
}
else
{
sSagePayUrl = "https://test.sagepay.com/gateway/service/direct3dcallback.vsp?";
}
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
WebRequest request = WebRequest.Create(sSagePayUrl + "cres=" + coll["cres"] + "&VPSTxId=" + coll["threeDSSessionData"]);
// Get the response.
HttpWebResponse getResponse = (HttpWebResponse)request.GetResponse();
// Display the status.
// Get the stream containing content returned by the server.
Stream dataStream = getResponse.GetResponseStream();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader(dataStream);
// Read the content.
string responseFromServer = reader.ReadToEnd();
// Cleanup the streams and the response.
reader.Close();
dataStream.Close();
getResponse.Close();
//Check the response and act accordingly
您需要为 3DSv1 构建不同的请求:这里是我在 TermUrl 页面中的方式:
vendorTxCode = Request.QueryString["VendorTx"];
NameValueCollection coll;
coll = Request.Form;
sMd = coll["MD"];
sPaRes = coll["PaRes"];
////////////////////////////////////////////////////
//// Build post to SagePay
////////////////////////////////////////////////////
StringBuilder sb = new StringBuilder();
if (EcommerceSettings.bLiveTransactions())
{
sb.Append("https://live.sagepay.com/gateway/service/direct3dcallback.vsp?");
}
else
{
sb.Append("https://test.sagepay.com/gateway/service/direct3dcallback.vsp?");
}
sb.Append("VendorTxCode=");
sb.Append(sOrderID);
sb.Append("&MD=");
sb.Append(sMD);
sb.Append("&PaRes=");
sPaRes = sPaRes.Replace(" ", "+");//HttpUtility.UrlEncode(sPaRes);
sb.Append(sPaRes);
string sRequestQuery = sb.ToString();
/////////////////////////////////////////////////////
//// Post To SagePay 3DCallback page
/////////////////////////////////////////////////////
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
WebRequest request = WebRequest.Create(sRequestQuery);
如 v2 所示处理响应。
编辑
我发现你最好为 3DSv1 发帖,不要使用 URL 参数,因为有些银行不接受这个。与 3DSv2 几乎相同的方式
这从来没有出现在测试服务器上,只有在直播时才会发生。
看起来测试服务器并没有提供我们上线后遇到的各种可能性。