【发布时间】:2021-01-25 11:08:26
【问题描述】:
我在我的应用程序中集成了 authorize.net accept.js 嵌入式 iFrame。在我的 lambda 函数中设置事务响应以获取响应时遇到问题。我在堆栈溢出方面看到过类似的问题,但对我来说还没有解决。
我的后端使用 Nodejs,前端使用 angular7。
我成功地从我的 lambda 函数中获取了令牌,因此我的 iframe 出现在 ui 上。我设置了\"showReceipt\": false 提供取消和继续的 url,因为文档说我必须设置显示收据参数“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,这让我更加困惑,因为它们在某些地方都说了不同的话.以下是我到目前为止完成的步骤:
- 使用所有设置(按照正确的顺序)创建了一个 lambda 托管支付函数以取回令牌。
- 创建了一个托管支付表单来显示 iframe。
- 能够付款 --> 获取收据页面 --> 路由到成功屏幕。
我想要完成的事情:
-
付款后,最初的想法是根据 authorize.net 的响应触发不同的 lambda 函数,而不与 IFrameCommunicator.html 通信,但由于我无法做到这一点,我希望得到响应以启动下一个后端处理。
-
此外,我们不会在我们的服务器中存储任何用户详细信息,并且对创建客户资料不感兴趣,除非这是获得交易响应的必要步骤。如果我可以在我为获取令牌而创建的同一个 lambda 函数中执行此步骤集成,请建议步骤集成,或者我必须为此创建一个不同的步骤集成,何时实施该步骤?
-
我知道 Webhook,但不确定目前我只是尝试实现一个简单的事务时它是否是绝对必要的。
我是新手,找不到很多与此相关的示例来解决我的问题/困惑。如果我能清楚地解释这里的步骤以及我哪里出错了,我将不胜感激。
以下是代码-
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 的 Angular 代码:
<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>
由于时间紧迫,我已经很多天以来一直在苦苦挣扎。如果有人在这里为我提供了很好的见解,那将非常有帮助。如果需要其他信息,请告诉我。提前谢谢!!!
【问题讨论】:
标签: javascript node.js angular authorize.net accept.js