Hello! Beginner Web Dev here trying to integrate Authroize.net payment system.
I am trying to setup and test Accept Hosted on my site using an iframe/lightbox by following this page. I am able to get the payment form to show up in the iframe and transactions are going through just fine once I click the "Pay" button as I can see it when I log into the sandbox.authorize.net. The issue is I can't receieve the Transaction Response from my site. I need to basically be able to tell from my site if the user clicked on "Pay" and the transaction was Auth/Captured so that I can email my digital products to the user OR if they clicked "Cancel" in which case I don't send them the product.
I am getting these error messages from the console:
'The loading of “https://mysite/store/partials/iFrameCommunicator.html#actionresizeWindow&width427&height925.8” in a frame is denied by “X-Frame-Options“ directive set to “SAMEORIGIN“.'
'Failed to execute ‘postMessage’ on ‘DOMWindow’: The target origin provided (‘mysite’) does not match the recipient window’s origin (‘null’)'
It looked like the issue was with CSP headers being SAMEORIGIN? So I tried to add a CSP Header in my .htcaccess like this but it still didn't work:
<IfModule mod_headers.c> Header set Content-Security-Policy "frame-ancestors 'self' *.mysite https://mysite/ https://test.authorize.net *.authorize.net;"; </IfModule>
I'm using craftCMS nitro and Docker on my local to test everything out.
My server side code for the payment token form:
$req = Craft::$app->getRequest(); $cost = $req->getBodyParam('price'); // define("AUTHORIZENET_LOG_FILE", "phplog"); /* Create a merchantAuthenticationType object with authentication details retrieved from the constants file */ $merchantAuthentication = new AnetAPI\MerchantAuthenticationType(); $merchantAuthentication->setName(getenv("ANET_SANDBOX_ID")); $merchantAuthentication->setTransactionKey(getenv("ANET_SANDBOX_KEY")); // Set the transaction's refId $refId = 'ref' . time(); //create a transaction $transactionRequestType = new AnetAPI\TransactionRequestType(); $transactionRequestType->setTransactionType("authCaptureTransaction"); $transactionRequestType->setAmount($cost); // Set Hosted Form options $setting1 = new AnetAPI\SettingType(); $setting1->setSettingName("hostedPaymentButtonOptions"); $setting1->setSettingValue("{\"text\": \"Pay\"}"); $setting2 = new AnetAPI\SettingType(); $setting2->setSettingName("hostedPaymentOrderOptions"); $setting2->setSettingValue("{\"show\": false}"); $setting3 = new AnetAPI\SettingType(); $setting3->setSettingName("hostedPaymentReturnOptions"); $setting3->setSettingValue("{\"showReceipt\": false, \"urlText\": \"Return\", \"cancelUrl\": \"https://qpr.nitro/store/partials/checkout-pay.twig\", \"cancelUrlText\": \"Cancel\"}"); $setting4 = new AnetAPI\SettingType(); $setting4->setSettingName("hostedPaymentIFrameCommunicatorUrl"); $setting4->setSettingValue("{\"url\": \"https://qpr.nitro/store/partials/iFrameCommunicator.html\"}"); $setting5 = new AnetAPI\SettingType(); $setting5->setSettingName("hostedPaymentPaymentOptions"); $setting5->setSettingValue("{\"cardCodeRequired\": true, \"showCreditCard\": true, \"showBankAccount\": false}"); $setting6 = new AnetAPI\SettingType(); $setting6->setSettingName("hostedPaymentSecurityOptions"); $setting6->setSettingValue("{\"captcha\": true}"); $setting7 = new AnetAPI\SettingType(); $setting7->setSettingName("hostedPaymentShippingAddressOptions"); $setting7->setSettingValue("{\"show\": true, \"required\": true}"); $setting8 = new AnetAPI\SettingType(); $setting8->setSettingName("hostedPaymentCustomerOptions"); $setting8->setSettingValue("{\"showEmail\": true, \"requiredEmail\": true, \"addPaymentProfile\": false}"); // Build transaction request $request = new AnetAPI\GetHostedPaymentPageRequest(); $request->setMerchantAuthentication($merchantAuthentication); $request->setRefId($refId); $request->setTransactionRequest($transactionRequestType); $request->addToHostedPaymentSettings($setting1); $request->addToHostedPaymentSettings($setting2); $request->addToHostedPaymentSettings($setting3); $request->addToHostedPaymentSettings($setting4); $request->addToHostedPaymentSettings($setting5); $request->addToHostedPaymentSettings($setting6); $request->addToHostedPaymentSettings($setting7); $request->addToHostedPaymentSettings($setting8); //execute request $controller = new AnetController\GetHostedPaymentPageController($request); $response = $controller->executeWithApiResponse(\net\authorize\api\constants\ANetEnvironment::SANDBOX); return $this->asJSON($response->getToken());
Front End:
if (!window.AuthorizeNetPopup) window.AuthorizeNetPopup = {}; if (!AuthorizeNetPopup.options) AuthorizeNetPopup.options = { onPopupClosed: null }; AuthorizeNetPopup.openPopup = function () { var popup = document.getElementById("divAuthorizeNetPopup"); var popupScreen = document.getElementById("divAuthorizeNetPopupScreen"); var ifrm = document.getElementById("iframeAuthorizeNet"); var form = document.forms["formAuthorizeNetPopup"]; let paypalCont = document.getElementById("paypalContainer"); let aNetUrl = "/actions/cls-lms/shop/shop-anet-token", total = "{{ totalPrice }}" csrfToken = "{{ csrfToken }}", csrfParam = "{{ csrfParam }}", shopApi = new craftApi(); let payload = { price: total } paypalCont.style.display = "none"; form.action = "https://test.authorize.net/payment/payment"; ifrm.style.width = "442px"; ifrm.style.height = "578px"; shopApi.controllerAjaxRequest(aNetUrl, payload, csrfParam, csrfToken). then(function(response){ $("#popupToken").val(response); setTimeout(form.submit(), 2); }); popup.style.display = ""; popupScreen.style.display = ""; centerPopup(); }; AuthorizeNetPopup.closePopup = function () { document.getElementById("divAuthorizeNetPopupScreen").style.display = "none"; document.getElementById("divAuthorizeNetPopup").style.display = "none"; document.getElementById("iframeAuthorizeNet").src="empty.html"; document.getElementById("btnOpenAuthorizeNetPopup").disabled = false; if (AuthorizeNetPopup.options.onPopupClosed) AuthorizeNetPopup.options.onPopupClosed(); }; AuthorizeNetPopup.openPopup = function () { var popup = document.getElementById("divAuthorizeNetPopup"); var popupScreen = document.getElementById("divAuthorizeNetPopupScreen"); var ifrm = document.getElementById("iframeAuthorizeNet"); var form = document.forms["formAuthorizeNetPopup"]; let paypalCont = document.getElementById("paypalContainer"); let aNetUrl = "/actions/cls-lms/shop/shop-anet-token", total = "{{ totalPrice }}" csrfToken = "{{ csrfToken }}", csrfParam = "{{ csrfParam }}", shopApi = new craftApi(); let payload = { price: total } paypalCont.style.display = "none"; form.action = "https://test.authorize.net/payment/payment"; ifrm.style.width = "442px"; ifrm.style.height = "578px"; shopApi.controllerAjaxRequest(aNetUrl, payload, csrfParam, csrfToken). then(function(response){ $("#popupToken").val(response); setTimeout(form.submit(), 2); }); popup.style.display = ""; popupScreen.style.display = ""; centerPopup(); }; AuthorizeNetPopup.onReceiveCommunication = function (querystr) { var params = parseQueryString(querystr); switch (params["action"]) { case "successfulSave": AuthorizeNetPopup.closePopup(); break; case "cancel": AuthorizeNetPopup.closePopup(); break; case "transactResponse": var response = params["response"]; document.getElementById("token").value = response; AuthorizeNetPopup.closePopup(); break; case "resizeWindow": var w = parseInt(params["width"]); var h = parseInt(params["height"]); var ifrm = document.getElementById("iframeAuthorizeNet"); ifrm.style.width = w.toString() + "px"; ifrm.style.height = h.toString() + "px"; centerPopup(); break; } }; function centerPopup() { var d = document.getElementById("divAuthorizeNetPopup"); d.style.left = "50%"; d.style.top = "50%"; var left = -Math.floor(d.clientWidth / 2); var top = -Math.floor(d.clientHeight / 2); d.style.marginLeft = left.toString() + "px"; d.style.marginTop = top.toString() + "px"; d.style.zIndex = "2"; if (d.offsetLeft < 16) { d.style.left = "16px"; d.style.marginLeft = "0px"; } if (d.offsetTop < 16) { d.style.top = "16px"; d.style.marginTop = "0px"; } } 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; }
12-30-2021 12:58 PM