史密斯写得好。我确实同意文档可以更直接。过去几周我的脑子很乱。
对于您的 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
EDIT
WebRequest 和 HttpWebResponse 的 ThreeDSNotificationURL 代码:
/////////////////////////////////////////////////////////
//// 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 所示处理响应。
EDIT
我发现您最好针对 3DSv1 发表帖子,并且不要使用 URL 参数,因为有些银行不接受这一点。与 3DSv2 的方式几乎相同
这在测试服务器上从未出现过,只有在上线时才会出现。
看起来测试服务器并没有提供我们上线后遇到的各种可能性。