Hi,
I'm struggling with using the hosted version of Auth.net CIM. I'm using a test account right now.
When I call GetHostedProfilePage, I pass hostedProfileIFrameCommunicatorUrl = http://sandbox.phdposters.com/new/contentx/IframeCommunicator.html. The call succeeds, no errors server side, but then...
But when I use Chrome developer tools to look at the HTML loaded from Auth.net's server, I see this line:
var g_iframeCommunicatorUrl = "";
I've tried passing "https" and "http" versions of the URL to GetHostedProfilePage(), neither seems to help. HTTPS will work to sandbox.phdposters.com, but I've been using HTTP instead because the certificate is for phdposters.com, and so it triggers a mismatch when I try to use it with sandbox.phdposters.com. No idea if that's related to the problem.
My server logs confirm that Auth.net is never trying to load http://sandbox.phdposters.com/new/contentx/IframeCommunicator.html
Please help... I've scoured the forums and still can't figure out what I'm doing wrong.
Thanks,
Ian
Solved! Go to Solution.
04-15-2013 09:51 AM
<ns1:hostedProfileSettings> <ns1:setting> <ns1:settingName>hostedProfilePageBorderVisible</ns1:settingName> <ns1:settingValue>false</ns1:settingValue> </ns1:setting> </ns1:hostedProfileSettings> <ns1:hostedProfileSettings> <ns1:setting> <ns1:settingName>hostedProfileIFrameCommunicatorUrl</ns1:settingName> <ns1:settingValue>https://phdposters.com/sandbox/contentx/IframeCommunicator.html</ns1:settingValue> </ns1:setting> </ns1:hostedProfileSettings>
From the cim soap guide pdf. the settings should be something like
<ns1:hostedProfileSettings> <ns1:setting> <ns1:settingName>hostedProfilePageBorderVisible</ns1:settingName> <ns1:settingValue>false</ns1:settingValue> </ns1:setting> <ns1:setting> <ns1:settingName>hostedProfileIFrameCommunicatorUrl</ns1:settingName> <ns1:settingValue>https://phdposters.com/sandbox/contentx/IframeCommunicator.html</ns1:settingValue> </ns1:setting> </ns1:hostedProfileSettings>
04-16-2013 05:46 PM
post your code would help. or debug your GetHostedProfilePage and make sure it got pass to authorize.net
04-15-2013 11:14 AM
OK, here's my code:
def authnet_cim_get_url_token(customer_id): """ Given a pre-existing customer profile ID, get a token that can be used to access the payment entry pages hosted at Authorize.Net. Raises ValueError if something goes wrong. """ client = suds.client.Client("file://"+CONFIG['authnet.cim_wsdl']) params = { 'merchantAuthentication': { 'name': CONFIG['authnet.login_id'], 'transactionKey': CONFIG['authnet.txn_key'] }, 'hostedProfileSettings': [ {'setting': {'settingName':'hostedProfilePageBorderVisible', 'settingValue':'false'}}, # This is *required* for communication between Auth.Net and our page, # especially for getting JavaScript notification when the payment profile # has been added: see http://community.developer.authorize.net/t5/Integration-and-Testing/CIM-hosted-form-option-popup-won... {'setting': {'settingName':'hostedProfileIFrameCommunicatorUrl', 'settingValue':CONFIG['url.authnet_cim.iframe']}} ], 'customerProfileId': customer_id # long int, also OK to pass as string } result = client.service.GetHostedProfilePage(**params) print result # DEBUG if result['resultCode'] == "Ok": return result['token'] else: raise ValueError(str(result))
The response looks successful:
(GetHostedProfilePageResponseType){ resultCode = "Ok" messages = (ArrayOfMessagesTypeMessage){ MessagesTypeMessage[] = (MessagesTypeMessage){ code = "I00001" text = "Successful." }, } token = "RQXhtbytk0xVB0GvPvKbkL2TqgKZbaqT/g2YHOx4DO5bzlXCWB83XDSuT7rRZ4fzxc5Lkv7fDKgDBbjNG/dk7bHS7R8YOaevcAJ858z/qlbeq4onrjlyoH4oLKuzla9i9UIB6t/8jsr5cLQJdAUnt7Prl3xkuJqirlyJ+CBsZ7C1rw2m4R8UlRW1dclAUPn4n5psIgrKJGQkGJQFomqNKz7JPKKbgqoUq76aLBknDzo=" }
I then generate an HTML page, closely following the example code:
<!DOCTYPE html> <html> <head> <title>Order form - PhD Posters</title> <link rel="StyleSheet" href="/sandbox/static/common.css" TYPE="text/css"> <link rel="shortcut icon" href="/sandbox/static/favicon.ico" type="image/vnd.microsoft.icon"> <!-- <meta name="ROBOTS" content="INDEX, FOLLOW"> --> <!-- Google Analytics --> <script type="text/javascript"> var _gaq = _gaq || []; _gaq.push(['_setAccount', 'UA-327385-1']); _gaq.push(['_trackPageview', '/orderform/authnet_cim']); (function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src=('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })(); </script> <script type="text/javascript" src="/sandbox/static/jquery.js"></script> <script type="text/javascript" src="/sandbox/static/jquery.cookie.js"></script> <script type='text/javascript'> $(document).ready(function() { $('#no_js').hide(); $('#has_js').show(); // Set cookie to indicate if we support HTML5 file uploads: if(window.File && window.FileReader && window.FileList && window.Blob && window.FormData) { if(/Firefox\/[45]\.[.0-9]+$/.test(navigator.userAgent)) { // Firefox 4.x and 5.x seem to have all the APIs, but can't actually transmit Blobs over XHR2? // This causes errors on our end, and no doubt frustrates customers... } else { $.cookie("h5file", "1", {path: "/"}); } } }); </script> <link href="contentx/manage.css" rel="stylesheet" type="text/css" /> <!--[if lte IE 6]> <link href="contentx/manageIELTE6.css" rel="stylesheet" type="text/css" /> <![endif]--> <script type="text/javascript" src="contentx/popup.js"></script> <script type="text/javascript"> // Uncomment this line if eCheck is enabled. This does not affect functionality, only the initial sizing of the popup page for add payment. //AuthorizeNetPopup.options.eCheckEnabled = true; // Uncomment these lines to define a function that will be called when the popup is closed. // For example, you may want to refresh your page and/or call the GetCustomerProfile API method from your server. AuthorizeNetPopup.options.onPopupClosed = function() { console.log("onPopupClosed has been called!"); }; // Uncomment this line if you do not have absolutely positioned elements on your page that can obstruct the view of the popup. // This can speed up the processing of the page slightly. AuthorizeNetPopup.options.skipZIndexCheck = true; // Uncomment this line to use test.authorize.net instead of secure.authorize.net. AuthorizeNetPopup.options.useTestEnvironment = true; //]]> </script> </head> <body> <div id='logo_header'> <a href='http://sandbox.phdposters.com/index.php'><img src='/sandbox/static/logo.gif' alt='PhD Posters' border='0'></a> <div><a href='http://sandbox.phdposters.com/index.php'>Cancel Order</a> | <a href='http://sandbox.phdposters.com/faq.php' target='_blank'>FAQ</a></div> </div> <div id='no_js' class='chunk'> <h2>JavaScript is required!</h2> <div class='chunk-content'><div class='alert'> Our order form requires JavaScript to function properly. Please enable JavaScript in your browser, and/or disable browser plugins like NoScript. </div></div> </div> <div id='has_js' style='display:none;'> <div class='chunk'> <div class='form-width'> <p>Customer profile ID: 17575827</p> <p> <button onclick="AuthorizeNetPopup.openManagePopup()">Manage my stuff</button> <button onclick="AuthorizeNetPopup.openAddPaymentPopup()">Add a New Payment Method</button> <button onclick="AuthorizeNetPopup.openEditPaymentPopup('123456')">Edit Payment Method</button> <button onclick="AuthorizeNetPopup.openAddShippingPopup()">Add a New Shipping Address</button> <button onclick="AuthorizeNetPopup.openEditShippingPopup('123456')">Edit Shipping Address</button> </p> </div></div> <form method="post" action="https://secure.authorize.net/hosted/profile/manage" id="formAuthorizeNetPopup" name="formAuthorizeNetPopup" target="iframeAuthorizeNet" style="display:none;"> <input type="hidden" name="Token" value="RQXhtbytk0xVB0GvPvKbkL2TqgKZbaqT/g2YHOx4DO5bzlXCWB83XDSuT7rRZ4fzxc5Lkv7fDKgDBbjNG/dk7bHS7R8YOaevcAJ858z/qlbeq4onrjlyoH4oLKuzla9i9UIB6t/8jsr5cLQJdAUnt7Prl3xkuJqirlyJ+CBsZ7C1rw2m4R8UlRW1dclAUPn4n5psIgrKJGQkGJQFomqNKz7JPKKbgqoUq76aLBknDzo=" /> <input type="hidden" name="PaymentProfileId" value="" /> <input type="hidden" name="ShippingAddressId" value="" /> </form> <div id="divAuthorizeNetPopup" style="display:none;" class="AuthorizeNetPopupGrayFrameTheme"> <div class="AuthorizeNetPopupOuter"> <div class="AuthorizeNetPopupTop"> <div class="AuthorizeNetPopupClose"> <a href="javascript:;" onclick="AuthorizeNetPopup.closePopup();" title="Close"> </a> </div> </div> <div class="AuthorizeNetPopupInner"> <iframe name="iframeAuthorizeNet" id="iframeAuthorizeNet" src="contentx/empty.html" frameborder="0" scrolling="no"></iframe> </div> <div class="AuthorizeNetPopupBottom"> <div class="AuthorizeNetPopupLogo" title="Powered by Authorize.Net"></div> </div> </div> <div class="AuthorizeNetShadow AuthorizeNetShadowT"></div> <div class="AuthorizeNetShadow AuthorizeNetShadowR"></div> <div class="AuthorizeNetShadow AuthorizeNetShadowB"></div> <div class="AuthorizeNetShadow AuthorizeNetShadowL"></div> <div class="AuthorizeNetShadow AuthorizeNetShadowTR"></div> <div class="AuthorizeNetShadow AuthorizeNetShadowBR"></div> <div class="AuthorizeNetShadow AuthorizeNetShadowBL"></div> <div class="AuthorizeNetShadow AuthorizeNetShadowTL"></div> </div> </div> <div class='pagefooter'> <a href='http://sandbox.phdposters.com/contactus.php' target='_blank'>contact us</a> | <a href='http://sandbox.phdposters.com/tos.php' target='_blank'>terms of service</a> | <a href='http://sandbox.phdposters.com/privacy.php' target='_blank'>privacy</a> </div> <!-- INSTRUCTIONS: Put this divAuthorizeNetPopupScreen section right before the closing </body> tag. --> <div id="divAuthorizeNetPopupScreen" style="display:none;"></div> </body> </html>
When I click the "Add a New Payment Method" button, the lightbox pops up, and I fill out the information. Using the Auth.net web site, I can see the (fake) credit card has been added to the CIM profile successfully. But after submitting the card info, the lightbox goes blank (empty, white) but doesn't close by itself. When I look at the HTML sent by Auth.net, I see the following block of JavaScript:
//<![CDATA[ var g_token = "RQXhtbytk0xVB0GvPvKbkL2TqgKZbaqT/g2YHOx4DO5bzlXCWB83XDSuT7rRZ4fzxc5Lkv7fDKgDBbjNG/dk7bHS7R8YOaevcAJ858z/qlbeq4onrjlyoH4oLKuzla9i9UIB6t/8jsr5cLQJdAUnt7Prl3xkuJqirlyJ+CBsZ7C1rw2m4R8UlRW1dclAUPn4n5psIgrKJGQkGJQFomqNKz7JPKKbgqoUq76aLBknDzo="; var g_inProgress = false; var g_CustProf = {"paymentProfiles":null,"shipToList":null,"customerProfileId":"17575827","merchantCustomerId":null,"description":null,"email":null}; var g_EcheckEnabled = true; var g_singleItemMode = true; var g_iframeCommunicatorUrl = ""; function onPageLoad() { if (true) { document.getElementById("spnNoScript").style.display = "none"; var i = g_CustProf.paymentProfiles && g_CustProf.paymentProfiles.length > 0 ? 0 : 999; document.getElementById("divPaymentSection").innerHTML = writePayment(i); g_paymentItemEditInfo.showEditMode(true, i); } sendResizeWindowToMerchant(); } //]]>
I'm puzzled as to why g_iframeCommunicatorUrl = "" when I sent hostedProfileIFrameCommunicatorUrl to GetHostedProfilePage(). Thoughts?
Thanks,
Ian
04-15-2013 07:20 PM
Not that familiar Python, but can you debug on params just before it send?
04-16-2013 04:45 AM
OK, I'm sending (with auth information edited out):
<?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="https://api.authorize.net/soap/v1/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Header/> <ns0:Body> <ns1:GetHostedProfilePage> <ns1:merchantAuthentication> <ns1:name>____</ns1:name> <ns1:transactionKey>____</ns1:transactionKey> </ns1:merchantAuthentication> <ns1:customerProfileId>17596933</ns1:customerProfileId> <ns1:hostedProfileSettings> <ns1:setting> <ns1:settingName>hostedProfilePageBorderVisible</ns1:settingName> <ns1:settingValue>false</ns1:settingValue> </ns1:setting> </ns1:hostedProfileSettings> <ns1:hostedProfileSettings> <ns1:setting> <ns1:settingName>hostedProfileIFrameCommunicatorUrl</ns1:settingName> <ns1:settingValue>https://phdposters.com/sandbox/contentx/IframeCommunicator.html</ns1:settingValue> </ns1:setting> </ns1:hostedProfileSettings> </ns1:GetHostedProfilePage> </ns0:Body> </SOAP-ENV:Envelope>
And I'm receiving:
<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><GetHostedProfilePageResponse xmlns="https://api.authorize.net/soap/v1/"><GetHostedProfilePageResult><resultCode>Ok</resultCode><messages><MessagesTypeMessage><code>I00001</code><text>Successful.</text></MessagesTypeMessage></messages><token>6+BmzlClmpCQu63UzLnlHmcykVhUvNc2vMkvm5xs+IHbYYxjSlwImWZ4A4F9/aV8Kqh0f5uPFWVxp1SKhwvsvu3ZTo9j5pAmyYBSEoshRZ6ITyGvid9rDyRc2rm4ZiaChF/XHDHZL6Z7HjowGeAuy4JmpZEDbUhtbSvJq1BsLwy4LEVkdfIABrRYPpXm1QNtD1QmzvGGjWKOtnYCNpQjXMk7RNh0offcWRGyf7tMQ+s=</token></GetHostedProfilePageResult></GetHostedProfilePageResponse></soap:Body></soap:Envelope>
Jeez, SOAP is ugly. Does that help any?
04-16-2013 05:40 PM
<ns1:hostedProfileSettings> <ns1:setting> <ns1:settingName>hostedProfilePageBorderVisible</ns1:settingName> <ns1:settingValue>false</ns1:settingValue> </ns1:setting> </ns1:hostedProfileSettings> <ns1:hostedProfileSettings> <ns1:setting> <ns1:settingName>hostedProfileIFrameCommunicatorUrl</ns1:settingName> <ns1:settingValue>https://phdposters.com/sandbox/contentx/IframeCommunicator.html</ns1:settingValue> </ns1:setting> </ns1:hostedProfileSettings>
From the cim soap guide pdf. the settings should be something like
<ns1:hostedProfileSettings> <ns1:setting> <ns1:settingName>hostedProfilePageBorderVisible</ns1:settingName> <ns1:settingValue>false</ns1:settingValue> </ns1:setting> <ns1:setting> <ns1:settingName>hostedProfileIFrameCommunicatorUrl</ns1:settingName> <ns1:settingValue>https://phdposters.com/sandbox/contentx/IframeCommunicator.html</ns1:settingValue> </ns1:setting> </ns1:hostedProfileSettings>
04-16-2013 05:46 PM
OK, never mind, I see it now. Good advice to debug the raw XML. Sorry I didn't try it earlier. I still don't understand why nothing threw an error -- I think the XML I was sending before should have failed to validate against the WSDL. I guess neither SUDS nor Auth.net actually checks. Here's the modified Python, for anyone else struggling with SUDS:
def authnet_cim_get_url_token(customer_id): """ Given a pre-existing customer profile ID, get a token that can be used to access the payment entry pages hosted at Authorize.Net. Raises ValueError if something goes wrong. """ client = suds.client.Client("file://"+CONFIG['authnet.cim_wsdl']) params = { 'merchantAuthentication': { 'name': CONFIG['authnet.login_id'], 'transactionKey': CONFIG['authnet.txn_key'] }, 'hostedProfileSettings': {'setting': [ {'settingName':'hostedProfilePageBorderVisible', 'settingValue':'false'}, # This is *required* for communication between Auth.Net and our page, # especially for getting JavaScript notification when the payment profile # has been added: see http://community.developer.authorize.net/t5/Integration-and-Testing/CIM-hosted-form-option-popup-won... {'settingName':'hostedProfileIFrameCommunicatorUrl', 'settingValue':CONFIG['url.authnet_cim.iframe']} ]}, 'customerProfileId': customer_id # long int, also OK to pass as string } result = client.service.GetHostedProfilePage(**params) if result['resultCode'] == "Ok": return result['token'] else: raise ValueError(str(result))
I should know better and use the raw XML interface instead of SOAP... Thanks again for the help.
04-16-2013 05:48 PM
Everything works in the popup as expected. I just can't get the IframeCommunicator.html scripts to load and fire.
Thus, the popup will not close. I am running this in the production environment so the url's are https.
FYI, the Orion folder in my url is a web site running under the invoicesanywhere site. It has it's own application pool.
In webconfig
<addkey="MainWebURL"value="https://www.invoicesanywhere.com/orion/"/>
on my test aspx.vb page:
obj8(0).settingName ="hostedProfileIFrameCommunicatorUrl"
obj8(0).settingValue ="https://www.invoicesanywhere.com/orion/AuthNet/IframeCommunicator.html"
obj8(1).settingName ="hostedProfilePageBorderVisible"
obj8(1).settingValue ="false"
Mixed content is set to Enable
this function is never fired (obviously)
AuthorizeNetPopup.onReceiveCommunication =function (querystr) {
Here is my aspx code:
<%
@PageLanguage="vb"AutoEventWireup="false"CodeBehind="Hosted1.aspx.vb"Inherits="Orion.Hosted1">
<!DOCTYPEhtml>
<htmlxmlns="http://www.w3.org/1999/xhtml">
<headrunat="server">
<title></title>
<linkhref="AuthNet/manage.css"rel="stylesheet"type="text/css"/>
<scripttype="text/javascript"src="AuthNet/popup.js"></script>
<scripttype="text/javascript">
// Uncomment this line to use test.authorize.net instead of secure.authorize.net.
AuthorizeNetPopup.options.useTestEnvironment =true;
</script>
</head>
<body>
<form method="post"action="https://test.authorize.net/hosted/profile/manage"id="formAuthorizeNetPopup"name="formAuthorizeNetPopup"target="iframeAuthorizeNet"style="display:none;">
<inputrunat="server"type="hidden"id="Token" name="Token"/>
</form>
<buttononclick="AuthorizeNetPopup.openManagePopup()">Manage my payment</button>
<divid="divAuthorizeNetPopup"style="display:none;"class="AuthorizeNetPopupGrayFrameTheme">
<divclass="AuthorizeNetPopupOuter">
<divclass="AuthorizeNetPopupTop">
<divclass="AuthorizeNetPopupClose">
<ahref="javascript:;"onclick="AuthorizeNetPopup.closePopup();"title="Close"></a>
</div>
</div>
<divclass="AuthorizeNetPopupInner">
<iframename="iframeAuthorizeNet"id="iframeAuthorizeNet"src="authnet/empty.html"style="border:none; scrollbar-face-color:none"></iframe>
</div>
<divclass="AuthorizeNetPopupBottom">
<divclass="AuthorizeNetPopupLogo"title="Powered by Authorize.Net"></div>
</div>
</div>
<divclass="AuthorizeNetShadow AuthorizeNetShadowT"></div>
<divclass="AuthorizeNetShadow AuthorizeNetShadowR"></div>
<divclass="AuthorizeNetShadow AuthorizeNetShadowB"></div>
<divclass="AuthorizeNetShadow AuthorizeNetShadowL"></div>
<divclass="AuthorizeNetShadow AuthorizeNetShadowTR"></div>
<divclass="AuthorizeNetShadow AuthorizeNetShadowBR"></div>
<divclass="AuthorizeNetShadow AuthorizeNetShadowBL"></div>
<divclass="AuthorizeNetShadow AuthorizeNetShadowTL"></div>
</div>
<divid="divAuthorizeNetPopupScreen"style="display:none;"></div>
</body>
</html>
Anyone have any ideas? I have tried everything I could possibly think of.
06-26-2013 09:00 AM
The most common reason for the iFrameCommunicator failing to function is if you are loading it on a separate domain from your main page. This could be as simple as using www in your iFrameCommunicatorURL, but not typing this when you actually test your page. Even this minor difference is enough for your web browser to prevent comunication.
Unfortunately, the limited debugging ability with javascript makes it harder to diagnose many other issues. Personally, I would make use of a tool such as Firebug to see if it can detect any javascript parsing errors. You could also modify the iFrameCommunicator page itself to take some action just to confirm that the save or cancel signals are being caught.
06-28-2013 01:45 PM