cancel
Showing results for 
Search instead for 
Did you mean: 

Using accept.js in a single page app (react.js)

Hello!   We are looking to use Authorize.NET accept.js to maintain our SAQ-A compliance (we already do this with braintree and stripe).

 

I'm finding it very difficult to work with accept.js based on the documentation and I'm hoping what I wan't is do-able in a non-docmented way!

 

My big problem is this:

 

"IMPORTANT: When using the payment information form, be sure that your page loads the library after the button is defined."

 

The script seems to want to process the DOM as soon as it loads and find the attributes it needs.  This makes it extremely difficult to work with from a single page app perspective because if the user views the payment page, then decides to go back to add something else to the cart, and then goes to pay again... the script is already been loaded but now the form isn't being rendered.

 

What I want to be able to do is have accept.js give me a function to call and pass it the things that are necessary (is test mode, publish key, etc).   This is how it is done in braintree:

 

braintree.dropin.create({
      authorization: 'CLIENT_TOKEN_FROM_SERVER',
      container: '#dropin-container'
    }

and this is how it is done with stripe:

 

// Create an instance of the card Element
var card = elements.create('card', {style: style});

// Add an instance of the card Element into the `card-element` <div>
card.mount('#card-element');

This API style works *beautifully* on the web, because I can load the javascript file once but construct the payment form when I need it.

 

Is there some way to do this with accept.js?  The only way I've been able to come up with is building the form myself and then calling Accept.dispatch, but this would move us from SAQ-A to SAQ-A EP

 

Thanks!

sontek
Member
18 REPLIES 18

Hi @sontek

 

You can use  our Accept.js built-in, mobile-optimized, payment form hosted by Authorize.Net, for a PCI DSS SAQ-A solution.

 

https://developer.authorize.net/api/reference/features/acceptjs.html#Integrating_the_Hosted_Payment_...

 





Send feedback at developer_feedback@authorize.net
Anurag
Moderator Moderator
Moderator

@Anurag Sorry if I wasn't clear, the thing you linked to is the thing I'm trying to use but can't because:

 

- There doesn't seem to be a way to style it

- There doesn't seem to be a way to attach it to a form after load (so single page apps don't work)

 

Think of it like this:

 

- Server side page renders first page

- User clicks "Pay"

- Payment page loads the Accept.js script

- Hosted form from accept.js is rendered

- User clicks "Keep Shopping"

 

at this point, the accept.js javascript file has been loaded, but they are no longer on the payment page.  This is a single page app (SPA) using react.js.

 

Now lets continue:

 

- User clicks "Pay"

 

How do I tell accept.js hosted to attach to the button on the payment page at this point, since the script is already loaded? I can't load the script a second time.

 

I need something like "Accept.attach("#id-of-form",  function(response) { ...})"

 

Does this make sense?

Hello, I'm still having issues with this.    We are considering monkey patching window.onload and dynamically reloading the script with a new script tag every time but we aren't confident that it wouldn't violate our SAQ-A if we start monkey patching the authorize.net script functionality.

Hi @sontek

 

I checked with the team internally and the script should load again when the Pay  button is clicked again . 

 

Is this not happening ?





Send feedback at developer_feedback@authorize.net

@Anurag  Hey.  Yeah, this is not happening, but its just one of many of my issues.

 

Let me try to document the issues more clearly:

 

1. The script doesn't work if the button isn't already on the page, it gives this error:

 

Uncaught TypeError: Cannot read property 'addEventListener' of undefined
at g (AcceptUI.js:1)
at e (AcceptUI.js:1)
at window.AcceptUI (AcceptUI.js:1)
at AcceptUI.js:1

This causes issues because it means I have to show a user a button that isn't functional yet, because the javascript that makes the button function has to be loaded *after* I render the button.  Which means they have to see the button and then download javascript before the button works.

 

2. We would prefer rendering the form inline rather than a modal, your modal doesn't seem to have any aria attributes on it which causes issues for accessibility.  An inline form would allow users who need assistance to more easily work with it.  This would also align more with our design in general but the accessibility issues makes it so we can't overlook it.

 

3. Since the script attaches onLoad, I can't find how to send it what language the user is in.  So even though they are a spanish speaking user, they are still getting an english form from authorize.net

 

4. My original issue.   This is react / single page application.   Which means this script only gets loaded the first time the form is required, even if they change pages and then come back.  We could dynamically force a reload of the script by injecting a new script tag on every render like:

 

new Element("script", {src: "accept.js", type: "text/javascript"});

 

 but that is super inefficent and will make the UI extremely unresponsive since I'll continually render a button that isn't functional until a script is re-downloaded.    Many of our users are mobile users and so having to re-download the same script over and over on their data plan isn't ideal.

 

5. The script doesn't seem to read scroll position at all, so the modal renders off the screen.  If we could render the form inline then this would fix this issue, here is a gif of it:

 

 

@Anurag To help with this conversation, I've created a demo:

 

https://www.webpackbin.com/bins/-L0f2-7FM8vleda4TOZX

 

This demo dynamically loads the script *every time*, which is inefficient, but it mostly works.  You'll see we get lots of errors in the console if you swap between "review" and "pay":

 

Uncaught TypeError: Cannot read property 'addEventListener' of undefined
    at g (VM8036 AcceptUI.js:1)
    at e (VM8036 AcceptUI.js:1)
    at window.AcceptUI (VM8036 AcceptUI.js:1)
    at VM8036 AcceptUI.js:1

but other than that console errors (which we can't deploy with, we'd be alerted that there are production javascript errors), the UI mostly functions.

 

The issues it shows:

 

1. The scroll error, shrink your window so you have to scroll and then click the payment button

2. I have no way to set a response handler.  This script assumes we have a global javascript function but we use modern javascript with ES6/React and don't have any globals.  So we need a way to set a callback that isn't a string data attribute.

 

 

I also don't know how to do my questions from earlier:

 

- How do I make the modal accessible with aria attributes

- How do I set what language I need the form rendered in

- How do I prevent the javascript errors in the console

Hi @sontek

 

Thanks for the details on it . 

The strolling issue team is planning of fixing in the upcoming release . 

I have provided details on the other issues to the team and will keep you posted . 

 

 





Send feedback at developer_feedback@authorize.net

It seems to me that you are loading the acceptUI.js with button,

Can you Please try just to load it on application initialization.

 

We need acceptUI to be loaded with application initialization and it should stay on page.

Shoagraw
Authorize.Net Developer Authorize.Net Developer
Authorize.Net Developer

Also related to responseHandler, I can see you have it inside your class, here what you need to do is 

-- define a response handler at window level [top level]

-- call your inside function from there react Statics can also help you.

 

Thanks,

 

 

 

 

Shoagraw
Authorize.Net Developer Authorize.Net Developer
Authorize.Net Developer