Authorize.net 的接受托管 iframe 中没有 action=transactResponse
no action=transactResponse in Accept Hosted iframe for Authorize.net
我正在尝试在 Coldfusion 应用程序中实施 Authorize.net Accept Hosted 托管结帐解决方案。
(对于所有 ColdFusion 开发人员,此代码 运行 在 BlueDragon.NET 9 上是一个 CF9 实现。cfscript 堆栈跟踪支持很糟糕,这就是为什么此代码在标签中而不是在 cfscript 中。 )
使用我们的沙盒 authorize.net 帐户,显示 iframe 托管的结帐页面。我可以填写信用卡信息并提交。我收到了收据,来自 authorize.net 的 2 封收据电子邮件,并被发送到确认页面,但 AuthorizeNetIFrame.onReceiveCommunication 中的案例“transactResponse”从未被触发。我在 javascript 函数中放置了一个警报,以查看进入 iframe 的所有查询字符串。
除了用于验证和获取令牌的 coldfusion 代码(这似乎有效),我从 Authorize.net 文档中获得了其余代码。
知道为什么我没有看到 action=transactResponse 查询字符串与来自 authorize.net 信用卡交易的响应一起进入 iframe。
我也使用实时 authorize.net 帐户尝试过此操作,但我在 iframe 支付页面上得到了一个 'User authentication failed due to invalid authentication values.',尽管我可以成功验证并获得 iframe 的令牌。我错过了什么。任何帮助将不胜感激。
代码的敏感部分(即凭据)、电子邮件和地址已被编辑。
这是主要代码文件(包括 iframe):
<!DOCTYPE html>
<html>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
<head>
<title>HostedPayment Test Page</title>
<script src="https://code.jquery.com/jquery-3.6.0.js"
integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk="
crossorigin="anonymous"></script>
<script type="text/javascript">
$(function () {
$("#btnOpenAuthorizeNetIFrame").click(function () {
$("#add_payment").show();
$("#send_token").attr({ "action": "https://test.authorize.net/payment/payment", "target": "add_payment" }).submit();
$(window).scrollTop($('#add_payment').offset().top - 50);
});
});
</script>
</head>
<body>
<cfif NOT IsDefined("url.CFID") or NOT IsDefined("url.CFTOKEN")>
<p style="color: red;">Error: CFID and CFTOKEN required as URL parameters...</p>
<cfabort />
</cfif>
<cfinclude template="../#client.custom_path#/constants.cfm" />
<cfset variables.LOGIN_TOKEN_URL = "https://apitest.authorize.net/xml/v1/request.api" />
<cfset variables.API_LOGIN_ID = "ZZZZZZZZZZZ" />
<cfset variables.TRANSACTION_KEY = "ZZZZZZZZZZZZZZ" />
<h2>Authenticate</h2>
<cfoutput>
<cfsavecontent variable="variables.soapBody">
<authenticateTestRequest xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd">
<merchantAuthentication>
<name>#variables.API_LOGIN_ID#</name>
<transactionKey>#variables.TRANSACTION_KEY#</transactionKey>
</merchantAuthentication>
</authenticateTestRequest>
</cfsavecontent>
</cfoutput>
<cfhttp url="#variables.LOGIN_TOKEN_URL#"
method="post"
result="variables.result1">
<cfhttpparam
type="xml"
value="#Trim( variables.soapBody )#"
/>
</cfhttp>
<cfdump var="#variables.result1#" />
<cfset variables.response1 = XMLParse(Trim(Right(variables.result1.filecontent, Len(variables.result1.filecontent)-1))) />
<cfset variables.response = StructNew() />
<cfset variables.response.resultCode = xmlSearch(Trim(Right(variables.result1.filecontent, Len(variables.result1.filecontent)-1)),
"//*[ local-name() = 'resultCode' ]"
) />
<cfif IsDefined("variables.response.resultCode[1].XmlText")>
<cfset variables.response.resultCode = variables.response.resultCode[1].XmlText />
</cfif>
<cfset variables.response.code = xmlSearch(Trim(Right(variables.result1.filecontent, Len(variables.result1.filecontent)-1)),
"//*[ local-name() = 'code' ]"
) />
<cfif IsDefined("variables.response.code[1].XmlText")>
<cfset variables.response.code = variables.response.code[1].XmlText />
</cfif>
<cfset variables.response.text = xmlSearch(Trim(Right(variables.result1.filecontent, Len(variables.result1.filecontent)-1)),
"//*[ local-name() = 'text' ]"
) />
<cfif IsDefined("variables.response.text[1].XmlText")>
<cfset variables.response.text = variables.response.text[1].XmlText />
</cfif>
<cfif IsDefined("variables.response.text") AND FindNoCase("Successful", variables.response.text)>
<p style="color: green; font-weight: bold;">Success</p>
<cfelse>
<p style="color: red; font-weight: bold;">Failure</p>
</cfif>
<cfdump var="#variables.response#" />
<cfdump var="#variables.response1#" />
<h2>Get token</h2>
<cfoutput>
<cfsavecontent variable="variables.soapBody2">
<getHostedPaymentPageRequest xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd">
<merchantAuthentication>
<name>#variables.API_LOGIN_ID#</name>
<transactionKey>#variables.TRANSACTION_KEY#</transactionKey>
</merchantAuthentication>
<transactionRequest>
<transactionType>authCaptureTransaction</transactionType>
<amount>0.01</amount>
<customer>
<email>ZZZZZZZZ@ZZZZZZZZ.com</email>
</customer>
<billTo>
<firstName>ZZZZZZZZ</firstName>
<lastName>Tester1</lastName>
<company></company>
<address>123 Main Street</address>
<city>ZZZZZZZZ</city>
<state>ZZ</state>
<zip>22222</zip>
<country>US</country>
</billTo>
</transactionRequest>
<hostedPaymentSettings>
<setting>
<settingName>hostedPaymentReturnOptions</settingName>
<settingValue>{"showReceipt": true, "url": "https://ZZZZZZZZ.com/test/hosted_pages/cart_hosted_confirm.cfm", "urlText": "Continue", "cancelUrl": "https://ZZZZZZZZ.com/test/hosted_pages/cart_hosted_cancel.cfm", "cancelUrlText": "Cancel"}</settingValue>
</setting>
<setting>
<settingName>hostedPaymentButtonOptions</settingName>
<settingValue>{"text": "Pay"}</settingValue>
</setting>
<setting>
<settingName>hostedPaymentStyleOptions</settingName>
<settingValue>{"bgColor": "blue"}</settingValue>
</setting>
<setting>
<settingName>hostedPaymentPaymentOptions</settingName>
<settingValue>{"cardCodeRequired": true, "showCreditCard": true, "showBankAccount": false}</settingValue>
</setting>
<setting>
<settingName>hostedPaymentSecurityOptions</settingName>
<settingValue>{"captcha": false}</settingValue>
</setting>
<setting>
<settingName>hostedPaymentShippingAddressOptions</settingName>
<settingValue>{"show": false, "required": false}</settingValue>
</setting>
<setting>
<settingName>hostedPaymentBillingAddressOptions</settingName>
<settingValue>{"show": true, "required":true}</settingValue>
</setting>
<setting>
<settingName>hostedPaymentCustomerOptions</settingName>
<settingValue>{"showEmail": true, "requiredEmail": true, "addPaymentProfile": false}</settingValue>
</setting>
<setting>
<settingName>hostedPaymentOrderOptions</settingName>
<settingValue>{"show": true, "merchantName": "Test Company, LLC"}</settingValue>
</setting>
<setting>
<settingName>hostedPaymentIFrameCommunicatorUrl</settingName>
<settingValue>{"url": "https://ZZZZZZZZ.com/test/hosted_pages/IFrameCommunicator.html"}</settingValue>
</setting>
</hostedPaymentSettings>
</getHostedPaymentPageRequest>
</cfsavecontent>
</cfoutput>
<cfhttp url="#variables.LOGIN_TOKEN_URL#"
method="post"
result="variables.result2">
<cfhttpparam
type="xml"
value="#Trim( variables.soapBody2 )#"
/>
</cfhttp>
<cfdump var="#variables.result2#" />
<cfset variables.response2 = XMLParse(Trim(Right(variables.result2.filecontent, Len(variables.result2.filecontent)-1))) />
<cfset variables.responseToken = StructNew() />
<cfset variables.responseToken.resultCode = xmlSearch(Trim(Right(variables.result2.filecontent, Len(variables.result2.filecontent)-1)),
"//*[ local-name() = 'resultCode' ]"
) />
<cfif IsDefined("variables.responseToken.resultCode[1].XmlText")>
<cfset variables.responseToken.resultCode = variables.responseToken.resultCode[1].XmlText />
</cfif>
<cfset variables.responseToken.code = xmlSearch(Trim(Right(variables.result2.filecontent, Len(variables.result2.filecontent)-1)),
"//*[ local-name() = 'code' ]"
) />
<cfif IsDefined("variables.responseToken.code[1].XmlText")>
<cfset variables.responseToken.code = variables.responseToken.code[1].XmlText />
</cfif>
<cfset variables.responseToken.text = xmlSearch(Trim(Right(variables.result2.filecontent, Len(variables.result2.filecontent)-1)),
"//*[ local-name() = 'text' ]"
) />
<cfif IsDefined("variables.responseToken.text[1].XmlText")>
<cfset variables.responseToken.text = variables.responseToken.text[1].XmlText />
</cfif>
<cfif IsDefined("variables.responseToken.text") AND FindNoCase("Successful", variables.responseToken.text)>
<p style="color: green; font-weight: bold;">Success</p>
<cfset variables.responseToken.token = xmlSearch(Trim(Right(variables.result2.filecontent, Len(variables.result2.filecontent)-1)),
"//*[ local-name() = 'token' ]"
) />
<cfif IsDefined("variables.responseToken.token[1].XmlText")>
<cfset variables.responseToken.token = variables.responseToken.token[1].XmlText />
</cfif>
<cfelse>
<p style="color: red; font-weight: bold;">Failure</p>
</cfif>
<cfdump var="#variables.response2#" />
<cfdump var="#variables.responseToken#" />
<h2>Hosted Page</h2>
<cfif IsDefined("variables.responseToken.token") AND Len(Trim(variables.responseToken.token)) GT 0>
<div>
Open Authorize.net in an iframe to complete transaction
<button id="btnOpenAuthorizeNetIFrame" onclick="">Show Payment Form</button>
</div>
<div id="iframe_holder" class="center-block" style="width:90%;max-width: 1000px">
<iframe id="add_payment" class="embed-responsive-item panel" name="add_payment" width="100%" frameborder="0" scrolling="no" hidden="true">
</iframe>
</div>
<cfoutput>
<form id="send_token" action="" method="post" target="add_payment">
<input type="hidden" name="token" value="#variables.responseToken.token#" />
</form>
</cfoutput>
<script type="text/javascript">
(function () {
if (!window.AuthorizeNetIFrame) window.AuthorizeNetIFrame = {};
AuthorizeNetIFrame.onReceiveCommunication = function (querystr) {
alert('processing 1:'+querystr);
var params = parseQueryString(querystr);
switch (params["action"]) {
case "successfulSave":
break;
case "cancel":
break;
case "resizeWindow":
var w = parseInt(params["width"]);
var h = parseInt(params["height"]);
var ifrm = document.getElementById("add_payment");
ifrm.style.width = w.toString() + "px";
ifrm.style.height = h.toString() + "px";
break;
case "transactResponse":
var ifrm = document.getElementById("add_payment");
ifrm.style.display = 'none';
var formData = { gatewayResponse: params["response"] };
$.ajax({
url: "cart_hosted_async_log.cfm?<cfoutput>#URLTOKEN#</cfoutput>",
type: "POST",
data: formData,
success: function(data, textStatus, jqXHR)
{},
error: function (jqXHR, textStatus, errorThrown)
{}
});
break;
}
};
function parseQueryString(str) {
var vars = [];
var arr = str.split('&');
var pair;
for (var i = 0; i < arr.length; i++) {
pair = arr[i].split('=');
vars.push(pair[0]);
vars[pair[0]] = unescape(pair[1]);
}
return vars;
}
}());
</script>
</cfif>
</body>
</html>
这是 IFrameCommunicator.html 代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Iframe Communicator</title>
<script type="text/javascript">
//<![CDATA[
function callParentFunction(str) {
if (str && str.length > 0
&& window.parent
&& window.parent.parent
&& window.parent.parent.AuthorizeNetIFrame
&& window.parent.parent.AuthorizeNetIFrame.onReceiveCommunication)
{
// Errors indicate a mismatch in domain between the page containing the iframe and this page.
window.parent.parent.AuthorizeNetIFrame.onReceiveCommunication(str);
}
}
function receiveMessage(event) {
if (event && event.data) {
callParentFunction(event.data);
}
}
if (window.addEventListener) {
window.addEventListener("message", receiveMessage, false);
} else if (window.attachEvent) {
window.attachEvent("onmessage", receiveMessage);
}
if (window.location.hash && window.location.hash.length > 1) {
callParentFunction(window.location.hash.substring(1));
}
//]]/>
</script>
</head>
<body>
</body>
</html>
在https://developer.authorize.net/api/reference/features/accept_hosted.html,
在交易响应下是以下注释:
Important: If you host the form in an iframe, you must include the
iframe communicator URL in the hostedPaymentIFrameCommunicatorUrl
parameter of your getHostedPaymentPageRequest API call. To ensure that
you receive a response code, you must also set showReceipt to
false.
粗体是我加的。将 showReceipt
设置为 false
后,我收到了针对我的 Sandbox 帐户的响应。
对于错误:
'User authentication failed due to invalid authentication values.'
我从 Authorize.net 支持人员那里找到了答案。当您的 site/software 通过 API 向 Authorize.Net 发送付款或创建个人资料的请求,而我们无法识别 API 登录 ID 和交易密钥时,就会发生这种情况已在请求中提交。此错误只有三种可能的原因:
您的 site/software 在 https://apitest.authorize.net/xml/v1/request.api -- For live accounts, please ensure your site/software is posting to https://api.authorize.net/xml/v1/request.api 使用测试环境 URL 时正在向真实账户的 API 登录 ID 和交易密钥发布。
您的 site/software 正在使用 https://api.authorize.net/xml/v1/request.api -- For test accounts, please post to https://apitest.authorize.net/xml/v1/request.api 上的实时环境发布到测试帐户的 API 登录 ID 和交易密钥。
您的 site/software 使用了不正确的 API 登录 ID 或交易密钥。如果是这种情况,那么我们建议在 Authorize.Net 门户上验证您的 API 登录 ID,或者在需要时生成新的交易密钥。您也可以使用此网站了解如何 verify/generate 这些:https://support.authorize.net/s/article/What-Are-the-API-Login-ID-and-Transaction-Key
在我的例子中,我发现令牌被发送到 https://test.authorize.net/payment/payment not https://accept.authorize.net/payment/payment。更改它,现在代码可以工作了。
我正在尝试在 Coldfusion 应用程序中实施 Authorize.net Accept Hosted 托管结帐解决方案。
(对于所有 ColdFusion 开发人员,此代码 运行 在 BlueDragon.NET 9 上是一个 CF9 实现。cfscript 堆栈跟踪支持很糟糕,这就是为什么此代码在标签中而不是在 cfscript 中。 )
使用我们的沙盒 authorize.net 帐户,显示 iframe 托管的结帐页面。我可以填写信用卡信息并提交。我收到了收据,来自 authorize.net 的 2 封收据电子邮件,并被发送到确认页面,但 AuthorizeNetIFrame.onReceiveCommunication 中的案例“transactResponse”从未被触发。我在 javascript 函数中放置了一个警报,以查看进入 iframe 的所有查询字符串。
除了用于验证和获取令牌的 coldfusion 代码(这似乎有效),我从 Authorize.net 文档中获得了其余代码。
知道为什么我没有看到 action=transactResponse 查询字符串与来自 authorize.net 信用卡交易的响应一起进入 iframe。
我也使用实时 authorize.net 帐户尝试过此操作,但我在 iframe 支付页面上得到了一个 'User authentication failed due to invalid authentication values.',尽管我可以成功验证并获得 iframe 的令牌。我错过了什么。任何帮助将不胜感激。
代码的敏感部分(即凭据)、电子邮件和地址已被编辑。
这是主要代码文件(包括 iframe):
<!DOCTYPE html>
<html>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
<head>
<title>HostedPayment Test Page</title>
<script src="https://code.jquery.com/jquery-3.6.0.js"
integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk="
crossorigin="anonymous"></script>
<script type="text/javascript">
$(function () {
$("#btnOpenAuthorizeNetIFrame").click(function () {
$("#add_payment").show();
$("#send_token").attr({ "action": "https://test.authorize.net/payment/payment", "target": "add_payment" }).submit();
$(window).scrollTop($('#add_payment').offset().top - 50);
});
});
</script>
</head>
<body>
<cfif NOT IsDefined("url.CFID") or NOT IsDefined("url.CFTOKEN")>
<p style="color: red;">Error: CFID and CFTOKEN required as URL parameters...</p>
<cfabort />
</cfif>
<cfinclude template="../#client.custom_path#/constants.cfm" />
<cfset variables.LOGIN_TOKEN_URL = "https://apitest.authorize.net/xml/v1/request.api" />
<cfset variables.API_LOGIN_ID = "ZZZZZZZZZZZ" />
<cfset variables.TRANSACTION_KEY = "ZZZZZZZZZZZZZZ" />
<h2>Authenticate</h2>
<cfoutput>
<cfsavecontent variable="variables.soapBody">
<authenticateTestRequest xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd">
<merchantAuthentication>
<name>#variables.API_LOGIN_ID#</name>
<transactionKey>#variables.TRANSACTION_KEY#</transactionKey>
</merchantAuthentication>
</authenticateTestRequest>
</cfsavecontent>
</cfoutput>
<cfhttp url="#variables.LOGIN_TOKEN_URL#"
method="post"
result="variables.result1">
<cfhttpparam
type="xml"
value="#Trim( variables.soapBody )#"
/>
</cfhttp>
<cfdump var="#variables.result1#" />
<cfset variables.response1 = XMLParse(Trim(Right(variables.result1.filecontent, Len(variables.result1.filecontent)-1))) />
<cfset variables.response = StructNew() />
<cfset variables.response.resultCode = xmlSearch(Trim(Right(variables.result1.filecontent, Len(variables.result1.filecontent)-1)),
"//*[ local-name() = 'resultCode' ]"
) />
<cfif IsDefined("variables.response.resultCode[1].XmlText")>
<cfset variables.response.resultCode = variables.response.resultCode[1].XmlText />
</cfif>
<cfset variables.response.code = xmlSearch(Trim(Right(variables.result1.filecontent, Len(variables.result1.filecontent)-1)),
"//*[ local-name() = 'code' ]"
) />
<cfif IsDefined("variables.response.code[1].XmlText")>
<cfset variables.response.code = variables.response.code[1].XmlText />
</cfif>
<cfset variables.response.text = xmlSearch(Trim(Right(variables.result1.filecontent, Len(variables.result1.filecontent)-1)),
"//*[ local-name() = 'text' ]"
) />
<cfif IsDefined("variables.response.text[1].XmlText")>
<cfset variables.response.text = variables.response.text[1].XmlText />
</cfif>
<cfif IsDefined("variables.response.text") AND FindNoCase("Successful", variables.response.text)>
<p style="color: green; font-weight: bold;">Success</p>
<cfelse>
<p style="color: red; font-weight: bold;">Failure</p>
</cfif>
<cfdump var="#variables.response#" />
<cfdump var="#variables.response1#" />
<h2>Get token</h2>
<cfoutput>
<cfsavecontent variable="variables.soapBody2">
<getHostedPaymentPageRequest xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd">
<merchantAuthentication>
<name>#variables.API_LOGIN_ID#</name>
<transactionKey>#variables.TRANSACTION_KEY#</transactionKey>
</merchantAuthentication>
<transactionRequest>
<transactionType>authCaptureTransaction</transactionType>
<amount>0.01</amount>
<customer>
<email>ZZZZZZZZ@ZZZZZZZZ.com</email>
</customer>
<billTo>
<firstName>ZZZZZZZZ</firstName>
<lastName>Tester1</lastName>
<company></company>
<address>123 Main Street</address>
<city>ZZZZZZZZ</city>
<state>ZZ</state>
<zip>22222</zip>
<country>US</country>
</billTo>
</transactionRequest>
<hostedPaymentSettings>
<setting>
<settingName>hostedPaymentReturnOptions</settingName>
<settingValue>{"showReceipt": true, "url": "https://ZZZZZZZZ.com/test/hosted_pages/cart_hosted_confirm.cfm", "urlText": "Continue", "cancelUrl": "https://ZZZZZZZZ.com/test/hosted_pages/cart_hosted_cancel.cfm", "cancelUrlText": "Cancel"}</settingValue>
</setting>
<setting>
<settingName>hostedPaymentButtonOptions</settingName>
<settingValue>{"text": "Pay"}</settingValue>
</setting>
<setting>
<settingName>hostedPaymentStyleOptions</settingName>
<settingValue>{"bgColor": "blue"}</settingValue>
</setting>
<setting>
<settingName>hostedPaymentPaymentOptions</settingName>
<settingValue>{"cardCodeRequired": true, "showCreditCard": true, "showBankAccount": false}</settingValue>
</setting>
<setting>
<settingName>hostedPaymentSecurityOptions</settingName>
<settingValue>{"captcha": false}</settingValue>
</setting>
<setting>
<settingName>hostedPaymentShippingAddressOptions</settingName>
<settingValue>{"show": false, "required": false}</settingValue>
</setting>
<setting>
<settingName>hostedPaymentBillingAddressOptions</settingName>
<settingValue>{"show": true, "required":true}</settingValue>
</setting>
<setting>
<settingName>hostedPaymentCustomerOptions</settingName>
<settingValue>{"showEmail": true, "requiredEmail": true, "addPaymentProfile": false}</settingValue>
</setting>
<setting>
<settingName>hostedPaymentOrderOptions</settingName>
<settingValue>{"show": true, "merchantName": "Test Company, LLC"}</settingValue>
</setting>
<setting>
<settingName>hostedPaymentIFrameCommunicatorUrl</settingName>
<settingValue>{"url": "https://ZZZZZZZZ.com/test/hosted_pages/IFrameCommunicator.html"}</settingValue>
</setting>
</hostedPaymentSettings>
</getHostedPaymentPageRequest>
</cfsavecontent>
</cfoutput>
<cfhttp url="#variables.LOGIN_TOKEN_URL#"
method="post"
result="variables.result2">
<cfhttpparam
type="xml"
value="#Trim( variables.soapBody2 )#"
/>
</cfhttp>
<cfdump var="#variables.result2#" />
<cfset variables.response2 = XMLParse(Trim(Right(variables.result2.filecontent, Len(variables.result2.filecontent)-1))) />
<cfset variables.responseToken = StructNew() />
<cfset variables.responseToken.resultCode = xmlSearch(Trim(Right(variables.result2.filecontent, Len(variables.result2.filecontent)-1)),
"//*[ local-name() = 'resultCode' ]"
) />
<cfif IsDefined("variables.responseToken.resultCode[1].XmlText")>
<cfset variables.responseToken.resultCode = variables.responseToken.resultCode[1].XmlText />
</cfif>
<cfset variables.responseToken.code = xmlSearch(Trim(Right(variables.result2.filecontent, Len(variables.result2.filecontent)-1)),
"//*[ local-name() = 'code' ]"
) />
<cfif IsDefined("variables.responseToken.code[1].XmlText")>
<cfset variables.responseToken.code = variables.responseToken.code[1].XmlText />
</cfif>
<cfset variables.responseToken.text = xmlSearch(Trim(Right(variables.result2.filecontent, Len(variables.result2.filecontent)-1)),
"//*[ local-name() = 'text' ]"
) />
<cfif IsDefined("variables.responseToken.text[1].XmlText")>
<cfset variables.responseToken.text = variables.responseToken.text[1].XmlText />
</cfif>
<cfif IsDefined("variables.responseToken.text") AND FindNoCase("Successful", variables.responseToken.text)>
<p style="color: green; font-weight: bold;">Success</p>
<cfset variables.responseToken.token = xmlSearch(Trim(Right(variables.result2.filecontent, Len(variables.result2.filecontent)-1)),
"//*[ local-name() = 'token' ]"
) />
<cfif IsDefined("variables.responseToken.token[1].XmlText")>
<cfset variables.responseToken.token = variables.responseToken.token[1].XmlText />
</cfif>
<cfelse>
<p style="color: red; font-weight: bold;">Failure</p>
</cfif>
<cfdump var="#variables.response2#" />
<cfdump var="#variables.responseToken#" />
<h2>Hosted Page</h2>
<cfif IsDefined("variables.responseToken.token") AND Len(Trim(variables.responseToken.token)) GT 0>
<div>
Open Authorize.net in an iframe to complete transaction
<button id="btnOpenAuthorizeNetIFrame" onclick="">Show Payment Form</button>
</div>
<div id="iframe_holder" class="center-block" style="width:90%;max-width: 1000px">
<iframe id="add_payment" class="embed-responsive-item panel" name="add_payment" width="100%" frameborder="0" scrolling="no" hidden="true">
</iframe>
</div>
<cfoutput>
<form id="send_token" action="" method="post" target="add_payment">
<input type="hidden" name="token" value="#variables.responseToken.token#" />
</form>
</cfoutput>
<script type="text/javascript">
(function () {
if (!window.AuthorizeNetIFrame) window.AuthorizeNetIFrame = {};
AuthorizeNetIFrame.onReceiveCommunication = function (querystr) {
alert('processing 1:'+querystr);
var params = parseQueryString(querystr);
switch (params["action"]) {
case "successfulSave":
break;
case "cancel":
break;
case "resizeWindow":
var w = parseInt(params["width"]);
var h = parseInt(params["height"]);
var ifrm = document.getElementById("add_payment");
ifrm.style.width = w.toString() + "px";
ifrm.style.height = h.toString() + "px";
break;
case "transactResponse":
var ifrm = document.getElementById("add_payment");
ifrm.style.display = 'none';
var formData = { gatewayResponse: params["response"] };
$.ajax({
url: "cart_hosted_async_log.cfm?<cfoutput>#URLTOKEN#</cfoutput>",
type: "POST",
data: formData,
success: function(data, textStatus, jqXHR)
{},
error: function (jqXHR, textStatus, errorThrown)
{}
});
break;
}
};
function parseQueryString(str) {
var vars = [];
var arr = str.split('&');
var pair;
for (var i = 0; i < arr.length; i++) {
pair = arr[i].split('=');
vars.push(pair[0]);
vars[pair[0]] = unescape(pair[1]);
}
return vars;
}
}());
</script>
</cfif>
</body>
</html>
这是 IFrameCommunicator.html 代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Iframe Communicator</title>
<script type="text/javascript">
//<![CDATA[
function callParentFunction(str) {
if (str && str.length > 0
&& window.parent
&& window.parent.parent
&& window.parent.parent.AuthorizeNetIFrame
&& window.parent.parent.AuthorizeNetIFrame.onReceiveCommunication)
{
// Errors indicate a mismatch in domain between the page containing the iframe and this page.
window.parent.parent.AuthorizeNetIFrame.onReceiveCommunication(str);
}
}
function receiveMessage(event) {
if (event && event.data) {
callParentFunction(event.data);
}
}
if (window.addEventListener) {
window.addEventListener("message", receiveMessage, false);
} else if (window.attachEvent) {
window.attachEvent("onmessage", receiveMessage);
}
if (window.location.hash && window.location.hash.length > 1) {
callParentFunction(window.location.hash.substring(1));
}
//]]/>
</script>
</head>
<body>
</body>
</html>
在https://developer.authorize.net/api/reference/features/accept_hosted.html, 在交易响应下是以下注释:
Important: If you host the form in an iframe, you must include the iframe communicator URL in the hostedPaymentIFrameCommunicatorUrl parameter of your getHostedPaymentPageRequest API call. To ensure that you receive a response code, you must also set showReceipt to false.
粗体是我加的。将 showReceipt
设置为 false
后,我收到了针对我的 Sandbox 帐户的响应。
对于错误:
'User authentication failed due to invalid authentication values.'
我从 Authorize.net 支持人员那里找到了答案。当您的 site/software 通过 API 向 Authorize.Net 发送付款或创建个人资料的请求,而我们无法识别 API 登录 ID 和交易密钥时,就会发生这种情况已在请求中提交。此错误只有三种可能的原因:
您的 site/software 在 https://apitest.authorize.net/xml/v1/request.api -- For live accounts, please ensure your site/software is posting to https://api.authorize.net/xml/v1/request.api 使用测试环境 URL 时正在向真实账户的 API 登录 ID 和交易密钥发布。
您的 site/software 正在使用 https://api.authorize.net/xml/v1/request.api -- For test accounts, please post to https://apitest.authorize.net/xml/v1/request.api 上的实时环境发布到测试帐户的 API 登录 ID 和交易密钥。
您的 site/software 使用了不正确的 API 登录 ID 或交易密钥。如果是这种情况,那么我们建议在 Authorize.Net 门户上验证您的 API 登录 ID,或者在需要时生成新的交易密钥。您也可以使用此网站了解如何 verify/generate 这些:https://support.authorize.net/s/article/What-Are-the-API-Login-ID-and-Transaction-Key
在我的例子中,我发现令牌被发送到 https://test.authorize.net/payment/payment not https://accept.authorize.net/payment/payment。更改它,现在代码可以工作了。