我几乎完成了 3d Secure 2 工作流程 ( https://developer.globalpay.com/ecommerce/3d-secure-version2/browser-authentication#api ) 的实施,但我正在努力确定如何应对挑战流动。
除了挑战流程卡之外,所有卡片都可以使用,我的 iFrame 出现在我的最后,单击“继续”会触发对我的挑战 URL 的请求 - 我正在执行 API 文档中显示的代码(上面链接) 但我返回的 JSON 只是显示在 iFrame 中,而不是触发我的 javascript。请在下面找到我的 JS 和挑战流程的端点:
async function performPaymentFlow(type, cardDetails, personalDetails, orderID) {
// Perform the check card on the information sent in
var versionCheckData, authenticationData;
try {
// call the api to see whether the card is valid
versionCheckData = await checkVersion('/api/Payments/CheckCard', { cardNumber: cardDetails.cardNumber });
if (versionCheckData.IsError) {
// show user error
}
}
catch (e) {
// show user error
}
// perform authentication
// WITHIN THIS CALL THIS IS WHERE THE CHALLENGE IS SHOWN TO THE USER
try {
authenticationData = await initiateAuthentication('/api/Payments/Authenticate', {
serverTransactionId: versionCheckData.serverTransactionId,
methodUrlComplete: true,
card: {
expiryMonth: cardDetails.expiryMonth,
expiryYear: cardDetails.expiryYear,
securityCode: cardDetails.cv2,
cardHolderName: cardDetails.cardName,
cardNumber: cardDetails.cardNumber
},
challengeWindow: {
displayMode: 'lightbox',
},
screenOptions: {
colorDepth: screen.colorDepth,
language: navigator.language,
timezone: new Date().getTimezoneOffset()
},
personalDetails: personalDetails,
type: type,
orderID: orderID
});
if (authenticationData.IsError) {
// show user error
}
else {
// frictionless authentication success and authorization success
if (authenticationData.result == "AUTHORIZATION_SUCCESS") {
// complete
}
// challenge success
else if (authenticationData.challenge.response.data.transStatus == "Y") {
var serverTransactionId = authenticationData.challenge.response.data.threeDSServerTransID;
var model = {
serverTransactionId: serverTransactionId,
card: cardDetails,
type: type
};
$.ajax({
type: "POST",
url: "/api/Booking/Authorize",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: JSON.stringify({ "model": model })
}).done(function (authorizationResponse) {
if (authorizationResponse.IsError) {
// Show user errlr
}
else {
// complete
}
});
}
// challenge failure
else {
// show user error
}
}
}
catch (e) {
// show user error
}
};
这是我的挑战 URL 的服务器端实现
public void Challenge()
{
// Get the data from the form
var cres = HttpContext.Current.Request.Form["cres"];
try
{
#region Instantiate the service
ServicesContainer.ConfigureService(new GpEcomConfig
{
MerchantId = Constants.realexuser,
AccountId = "internet",
SharedSecret = Constants.realexsecret,
MethodNotificationUrl = Constants.DomainName + "/api/Payments/MethodSetup",
ChallengeNotificationUrl = Constants.DomainName + "/api/Payments/Challenge",
MerchantContactUrl = Constants.DomainName + "/visit/find-us-and-faqs",
Secure3dVersion = Secure3dVersion.Two
});
#endregion
#region data population and parsing
byte[] data = Convert.FromBase64String(cres.Replace('-', '+').Replace('_', '/').PadRight(4 * ((cres.Length + 3) / 4), '='));
string challengeUrlResponseString = Encoding.UTF8.GetString(data);
dynamic challengeUrlResponse = JsonConvert.DeserializeObject(challengeUrlResponseString);
var threeDSServerTransID = challengeUrlResponse.threeDSServerTransID; // af65c369-59b9-4f8d-b2f6-7d7d5f5c69d5
var acsTransId = challengeUrlResponse.acsTransID; // 13c701a3-5a88-4c45-89e9-ef65e50a8bf9
var messageType = challengeUrlResponse.messageType; // Cres
var messageVersion = challengeUrlResponse.messageVersion; // 2.1.0
var transStatus = challengeUrlResponse.transStatus; // Y
#endregion
// Package up the data and send it back to the user
challengeUrlResponseString = JsonConvert.SerializeObject(new
{
threeDSServerTransID = threeDSServerTransID,
transStatus = transStatus
});
SendResponse(challengeUrlResponseString);
return;
}
// Uh oh - another error from the API
catch (Exception exce)
{
// Return error to user
}
}
从此返回的 JSON 显示在 iframe 中,而不是返回到我的 JS,因此我可以继续流程,任何帮助将不胜感激。