问题描述
我已经在我的应用程序中集成了authorize.net accept.js嵌入式iFrame。无法在我的lambda函数中设置事务响应以获取响应。我已经在堆栈溢出中看到了类似的问题,但对我来说什么都没有解决。
在后端使用Nodejs,在前端使用angular7。
我从lambda函数成功获取了令牌,因此我的iframe出现在ui上。我已经设置了\"showReceipt\": false
来提供取消和继续的网址,因为文档说我必须设置显示回执参数“ false”才能与ui中的IFrameCommunicator.html进行通信。但是,当我单击“付款”时,它长时间停留在“正在处理...”中。
以下分别是“网络”标签中的请求和响应标头:
* Cookie: __cfruid=deb63d2f12d9690aeea838cf7f31ada6da92bc1c-1602260930
* Host: test.authorize.net
* Origin: https://test.authorize.net
* Referer: https://test.authorize.net/payment/payment
* Sec-Fetch-Dest: empty
* sec-fetch-mode: cors
*
sec-fetch-site: same-origin
{"resultCode":"Ok","messageCode":"Ok","transactionData":{"accountType":"discover","accountNumber":"XXXX0012","transId":"40055282319","responseCode":"4","authorization":"TYIUU7","merchantName":"iMart Inc.","totalAmount":"1999.9","dateTime":"10/09/2020 4:20:27 PM"}}
我确定查看响应是在进行交易,但不确定为什么未与沟通者联系。
我已经阅读了文档中的步骤,并遵循了GitHub示例代码-https://github.com/AuthorizeNet/accept-sample-app,这使我更加困惑,因为它们在某些地方都说不同的话。以下是我到目前为止完成的步骤:
我要完成的工作:
-
付款后,最初的想法是基于authorize.net的响应触发一个不同的lambda函数,而无需与IFrameCommunicator.html进行通信,但是由于我无法做到,所以我想得到一个响应在后端启动下一个过程。
-
此外,我们不会在服务器中存储任何用户详细信息,并且对创建客户资料不感兴趣,除非这是获得交易响应的必要步骤。如果我可以在为获取令牌而创建的同一lambda函数中完成此步骤,请提出步骤集成建议,否则我将为此创建一个不同的lambda函数,并且该步骤何时实施?
-
我了解Webhooks,但是不确定在我只是试图实现一个简单事务时,这是否绝对必要。
我是新手,所以找不到很多与之相关的示例来解决我的问题/困惑。如果我对这里的步骤以及我要去哪里出错有清晰的解释,将不胜感激。
以下是代码-
accept-hosted.js Lambda函数:
merchantAuthenticationType.setName('*****');
merchantAuthenticationType.setTransactionKey('******');
var transactionRequestType = new ApiContracts.TransactionRequestType();
transactionRequestType.setTransactionType(ApiContracts.TransactionTypeEnum.AUTHCAPTURETRANSACTION);
transactionRequestType.setAmount(Total);
var setting1 = new ApiContracts.SettingType();
var setting2 = new ApiContracts.SettingType();
var setting4 = new ApiContracts.SettingType();
var setting5 = new ApiContracts.SettingType();
var setting6 = new ApiContracts.SettingType();
var setting7 = new ApiContracts.SettingType();
var setting8 = new ApiContracts.SettingType();
var setting9 = new ApiContracts.SettingType();
var setting10 = new ApiContracts.SettingType();
var setting11 = new ApiContracts.SettingType();
setting2.setSettingName("hostedPaymentButtonoptions");
setting2.setSettingValue("{\"text\": \"Pay\"}");
setting1.setSettingName("hostedPaymentReturnoptions");
setting1.setSettingValue(
"{\"showReceipt\": false,\"url\": \"https://iMart.com/success.html\",\"urlText\": \"Continue\",\"cancelUrl\": \"https://iMart.com/error.html\",\"cancelUrlText\": \"Cancel\"}");
setting10.setSettingName("hostedPaymentOrderOptions");
setting10.setSettingValue("{\"show\": false,\"merchantName\": \"iMart Inc.\"}");
setting5.setSettingName("hostedPaymentPaymentOptions");
setting5.setSettingValue("{\"cardCoderequired\": true,\"showCreditCard\": true,\"showBankAccount\": false}");
setting7.setSettingName("hostedPaymentShippingAddressOptions");
setting7.setSettingValue("{\"show\": false,\"required\": false}");
setting8.setSettingName("hostedPaymentBillingAddressOptions");
setting8.setSettingValue("{\"show\": false,\"required\": false}");
setting6.setSettingName("hostedPaymentSecurityOptions");
setting6.setSettingValue("{\"captcha\": true}");
setting4.setSettingName("hostedPaymentStyleOptions");
setting4.setSettingValue("{\"bgColor\": \"blue\"}");
setting9.setSettingName("hostedPaymentCustomerOptions");
setting9.setSettingValue("{\"showEmail\": false,\"requiredEmail\": false,\"addPaymentProfile\": true }");
setting11.setSettingName("hostedPaymentIFrameCommunicatorUrl");
setting11.setSettingValue("{\"url\": \"https://iMart.com/IFrameCommunicator.html\"}");
var settingList = [];
settingList.push(setting2);
settingList.push(setting10);
settingList.push(setting5);
settingList.push(setting7);
settingList.push(setting8);
settingList.push(setting6);
settingList.push(setting4);
settingList.push(setting9);
settingList.push(setting11);
settingList.push(setting1);
var alist = new ApiContracts.ArrayOfSetting();
alist.setSetting(settingList);
var firstname = new ApiContracts.UserField();
firstname.setName('First Name');
firstname.setValue(firstName);
var lastname = new ApiContracts.UserField();
lastname.setName('Last Name');
lastname.setValue(lastName);
var userFieldList = [];
userFieldList.push(firstname);
userFieldList.push(lastname);
var userFields = new ApiContracts.TransactionRequestType.UserFields();
userFields.setUserField(userFieldList);
var transactionSetting1 = new ApiContracts.SettingType();
transactionSetting1.setSettingName('duplicateWindow');
transactionSetting1.setSettingValue('120');
var transactionSetting2 = new ApiContracts.SettingType();
transactionSetting2.setSettingName('recurringBilling');
transactionSetting2.setSettingValue('false');
var transactionSetting3 = new ApiContracts.SettingType();
transactionSetting3.setSettingName('emailCustomer');
transactionSetting3.setSettingValue('true');
var transactionSetting4 = new ApiContracts.SettingType();
transactionSetting4.setSettingName('headerEmailReceipt');
transactionSetting3.setSettingValue('You are all set!');
var transactionSetting5 = new ApiContracts.SettingType();
transactionSetting5.setSettingName('footerEmailReceipt');
transactionSetting5.setSettingValue('This is the footer');
var getRequest = new ApiContracts.GetHostedPaymentPageRequest();
getRequest.setMerchantAuthentication(merchantAuthenticationType);
getRequest.setTransactionRequest(transactionRequestType);
getRequest.setHostedPaymentSettings(alist);
var ctrl = new ApiControllers.GetHostedPaymentPageController(getRequest.getJSON());
const basicAuth = encode.encode("*****",'base64');
await axios({
method: 'post',url: 'https://apitest.authorize.net/xml/v1/request.api',headers: {
'Authorization': 'Basic '+basicAuth,'Content-Type': 'application/json'
},data:JSON.stringify(ctrl._request)
}).then(async (data : any)=>{
if(data.data.token) {
callback(null,data.data) ;
} else callErr(data);
});
async function callErr(data: any){
callback(null,res) ;
}
}
IFrameCommunicator.html:
<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.AuthorizeNetPopup
&& window.parent.parent.AuthorizeNetPopup.onReceiveCommunication)
{
// Errors indicate a mismatch in domain between the page containing the iframe and this page.
window.parent.parent.AuthorizeNetPopup.onReceiveCommunication(str);
}
}
function receiveMessage(event) {
if (event && event.data) {
callParentFunction(event.data);
}
}
if (window.addEventListener) {
console.log('addEventListener');
console.log(receiveMessage);
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>
<iframe id="add_payment" class="embed-responsive-item panel" name="add_payment" width="100%" frameborder="0" scrolling="yes">
</iframe>
</div>
<form id="send_token" action="" method="post" target="add_payment" >
<input id="token" type="hidden" name="token" />
</form>
从现在开始的很多天以来,我一直在努力挣扎。如果有人在这里为我提供了很好的见解,那将非常有帮助。如果需要其他信息,请告诉我。预先谢谢你!
解决方法
这是您所有问题的答案,我希望它能起作用:
1)如果您使用的是iFrame,则必须使用iFrameCommunicator
2)成功url仅在将“ showReceipt”设置为true时才能使用,此处您无法自动导航到您的成功页面,这是“继续”按钮的链接,当允许“ showReceipt”时,该按钮就会出现>
3)如果您想触发任何功能或在响应后导航,请在html文件中添加以下代码
<script type="text/javascript">
$(document).ready(function () {
window.CommunicationHandler = {};
function parseQueryString(str) {
var vars = [];
var arr = str.split('&');
var pair;
for (var i = 0; i < arr.length; i++) {
pair = arr[i].split('=');
vars[pair[0]] = unescape(pair[1]);
}
return vars;
}
window.CommunicationHandler.onReceiveCommunication = function (argument) {
console.log('communication handler enter',argument);
var params = parseQueryString(argument.qstr)
switch (params['action']) {
case "resizeWindow":
console.log('resize'); break;
case "successfulSave":
console.log('save'); break;
case "cancel":
console.log('cancel'); break;
case "transactResponse":
sessionStorage.removeItem("HPTokenTime");
console.log('transaction complete');
var transResponse = JSON.parse(params['response']);
console.log('transaction complete1',transResponse);
// window.location.href = '/checkout/complete';
}
}
//send the token
$('#send_hptoken').submit();
});
</script>