The WooCommerce integrations for Authorize.Net we’ve built at SkyVerge are used by tens of thousands of merchants every year to process online payments. Over the six-year timespan in which we’ve maintained these integrations, we’ve worked with several iterations of the Authorize.Net APIs, from the query string-based legacy APIs to the latest version of the Accept suite. The latest Accept suite improvements have helped us unify legacy integrations and offer seamless, PCI compliant payment forms for our merchants.

We’ve recently adding support for Accept.js with UI to our integrations, and wanted to share our experience in implementing several different versions of the Accept suite, and what we learned in working with each Accept suite feature.

Migrating to Accept Suite

Round one: Adding Accept.js support

We initially added support for Accept.js to our ANet AIM extension in July of 2016, and later ported the same implementation over to our CIM extension in September of the same year. In both extensions, we added a couple of settings to use the new feature:

● A toggle to enable Accept.js - this allowed existing customers to continue with their current setup, in case they hadn’t generated a Public Client Key

● Input for a Public Client Key

At this point, we opted not to make Accept.js available by default since it required additional action by the merchant to enable it for their account. However, that’s no longer the case — keep reading to see what we’ve done with our latest update.  If you’re looking to add Accept.js support, this step is no longer even necessary.

The bulk of the work at the time was on the client-side in generating the opaqueData for the payment nonce. Fortunately, this implementation was very smooth following the documentation provided by Authorize.Net, so we were able to create a very simple flow for all merchants:

● If the merchant has not yet configured a Public Client Key, continue using the built-in form to send payment information server-side.

● Once the merchant sets the Client Key, adjust our transaction submission handlers:

  • Get the opaqueData by sending the payment information via JS in the browser.
  • Now use this opaqueData in the payment node for the request XML, rather than including card details (as you would otherwise when creating a transaction).

Since the rest of the transaction request was the same, this was a very easy change for us to make in a backwards-compatible way. If you haven’t implemented Accept.js at all, this is a very simple and quick win in helping to meet SAQ A-EP levels of PCI compliance.

What should you be aware of in your own implementations? It depends on whether you’re building for a hosted or self-hosted platform. WooCommerce is self-hosted, so the user can also run their own software, other plugins, or customizations alongside our code. As a result, debugging can be tricky since (a) other code can influence or block our API requests, or (b) other JavaScript can interfere with generating the payment nonce or retrieving opaqueData from Authorize.Net.

If other code may be running alongside your implementation, be sure to add additional logging to help you identify the breakdown in process (for us, having detailed logs tends to help more than searching through console errors on some sites). Since there are now multiple steps for creating a transaction, it’s helpful to know which step experienced a breakdown to further troubleshoot issues.

In WooCommerce, we’re able to log API requests and responses when debug logging is enabled. This is incredibly helpful for our support team to diagnose issues, so that there is a record of the data sent and received between the site and Authorize.Net. This is typically only done for server-side communication, so for Accept.js, we needed to be able to have a record of the same types of events so that our support team could verify that the client-side scripts were behaving as expected. Since WordPress sites can have their own themes, it’s not uncommon for a poorly written them to interfere with other JavaScript on the site.

So, we implemented AJAX logging to send the Accept.js request and response, minus any sensitive payment details, to the server to be logged in the same way as traditional API requests:

This helps our support team see where a breakdown happens when attempting a transaction: do we see issues before the opaqueData can be generated, between generating this and attempting to create a transaction, or is the issue while creating a transaction?

Round Two: Unifying our Integrations

Until now, we’ve offered three distinct WooCommerce extensions for accepting payments through Authorize.Net:

● Authorize.Net AIM - Accept payments directly or via Accept.js

● Authorize.Net CIM - The same feature-set as AIM, but with the addition of card tokenization for saving cards using the CIM API. This integration also offers support for WooCommerce Subscriptions and Pre-Orders modules.

● Authorize.Net SIM - Originally integrated with the SIM hosted (off-site) form, and later added support for Accept Hosted as an iframe payment form.

These extensions allowed merchants to choose a solution based on their needs: if they wanted a direct inline payment form on their checkout page, AIM or CIM did the trick, and if they also wanted card storage, then CIM it is. And if they wanted much-reduced PCI compliance scope, SIM / Accept Hosted allowed them to get up and running quickly with secure payment forms. 

When we’d originally upgraded to the Accept suite, tokenizing cards wasn’t available with Accept Hosted, so users would need to choose between meeting SAQ-A compliance or leveraging saved payment profiles and inline payment forms. Once Accept Hosted added support for payment profiles, a choice still existed: use an iframed payment form or an inline form. There was no approach that let users have everything.

While there were historically tradeoffs between different Authorize.Net APIs, this is no longer an issue! Using Accept.js with UI, we’re able to offer a solution that meets SAQ A levels of compliance, offers inline and seamless checkout, and supports using payment profiles.

So in January of this year, we set out to unify our different Authorize.Net integrations into a single, complete solution. We can offer inline checkout for backwards-compatibility (which uses Accept.js) by default, or lightbox checkout, which uses Accept.js with UI.

The result is a single, complete solution for all of the options Authorize.Net’s APIs and SDKs have to offer. This means a well-built plugin with focused support, and a single codebase for quicker feature addition and iteration. And because we allow merchants to set how they want their payment forms to behave, they have the same degree of choice as with the previous three extensions.

They can keep the form inline, with credit card fields generated by the site and allowing for greater control over the form’s appearance, or switch to the lightbox for enhanced PCI compliance. Either way, both forms result in the same opaque data so handling payments server-side remains the same.

If you’re upgrading an integration of your own, the lightbox checkout is definitely the way to go. While it requires a bit more handling to process the response of the lightbox form, it provides increased security and the request to create a transaction remains the same. In our integration, this was a pretty nominal change to make since we already supported Accept.js.

In our next post, we’ll discuss other optimizations we made while unifying our integrations, and how we were able to make these upgrades 100% backwards-compatible for our users.