cancel
Showing results for 
Search instead for 
Did you mean: 

Need help on best method to write my own form and interface

Does anyone know if there are any other API methods similar to accept.js where credit card data is contained client side? I’ve experimented with accept.js and would like something with a bit more of my own coding. I’ve built an example using authorize.net’s JSON example but I can’t see how to keep the transactionkey private. I prefer to build my own forms and interfaces. My primary goal is to keep all credit card data client side without exposing my authorize.net credentials. Accept.js uses authData.clientKey and authData.apiLoginID as public credentials. The JSON example uses apiLoginID with the transactionkey (not a public credential). I'm actually new to all this so I welcome any clarifications. Here is my working JSON sandbox test with the transactionkey exposed. Any direction would be appreciated.

 

<html>
<head>
<title>authorize.net</title>

<script type="text/javascript">

function post() {

var data = JSON.stringify( {
  createTransactionRequest: {
    merchantAuthentication: {
      name: '<id>',
      transactionKey: '<key>'
    },
    refId: '123456',
    transactionRequest: {
      transactionType: 'authCaptureTransaction',
      amount: '5',
      payment: {
        creditCard: {
          cardNumber: '5424000000000015',
          expirationDate: '2020-12',
          cardCode: '999'
        }
      },
      poNumber: '683128',
      customer: {
        id: '99999456654'
      },
      customerIP: '192.168.1.1',
      transactionSettings: {
        setting: {
          settingName: 'testRequest',
          settingValue: 'false'
        }
      }
    }
  }
} );

 if (window.XMLHttpRequest) {
     var XHR = new XMLHttpRequest();
 } else {
     var XHR = new ActiveXObject("Microsoft.XMLHTTP");
 }
 XHR.open("POST","https://apitest.authorize.net/xml/v1/request.api",true);
 XHR.setRequestHeader("Content-Type", "application/json");
 XHR.onreadystatechange = function () {
    if (XHR.readyState === 4 && XHR.status === 200) {
        var jsonx = JSON.parse(XHR.responseText);
        alert(jsonx.transactionResponse.responseCode);
        alert(jsonx.transactionResponse.messages[0]['description']);
        alert(jsonx.transactionResponse.transHashSha2);
    }
 };
 XHR.send(data);
}

</script>

</head>
<body>
<div><input type="button" value="submit" onclick="post();"></div>
</body>
</html>
airman81
Contributor
5 REPLIES 5
The only remotely possible way to keep client side data private that I can think of is to load your js script in a separate file on something like s3, and then add settings to your bucket policy (like encryption and http referrer access restricted to your domain) to prevent anyone from seeing it or downloading it. This can be done, I am 99% sure.

What I can tell you is that with the below integration, you would probably be just as well from a compliance perspective if you used a pure server side initiated API call. I would have to look it up to be sure, but I do not think your method lowers compliance scope at all. You could fully customize
In that case, hiding all your credentials.
Renaissance
All Star

What I don’t understand is why a private credential in the JSON example but a variable like authData.clientKey is offered in accept.js. I’m struggling to understand the different techniques.

 

If I understand the flow of accept.js method using my own form is as follows:

 

  • Client Side: post card data to authorize.net
  • Client Side: wait for response
  • Client Side: take response and post non credit card data to server
  • Server Side: take non credit card data and post to authorize.net
  • Server Side: wait for response and finalize

 

I liked the old depreciated “relay response” method which allowed you to send card data from the client with a hash key and validate directly server side. But there must have been security issues with that approach that I don’t understand.

 

I may have to just accept accept.js ;)

 

Any thought are appreciated. Thanks.

airman81
Contributor

@airman81 

 

Part of what you missed is that on the customizable js form, the cc data is tokenized in the browser. That is what moves you from SAQ D to SAQ A-EP. Your method is interesting, and you could pull those SAQs from the PCI document library and see where you fit.

 

You have an obvious problem of exposing your full API credentials. Anyone who wants to be you could.  IDK how many ways there would be to hack any methods you make to prevent access to your js scripts, but if there is at least 1, someone will do it. IDK how much experience you have with this, but I have very small clients who have less than 500 visitors a month, and they will get dozens of attempted attacks in a single day some days.  Had a guy in Chile attempt about 50 SQLI in a row one day.

 

And the problem is that your credentials only have to be swiped 1 time. That's all it takes. That is why the client side accept.js method uses the variable. If you use pure server side API calls its all hidden.  

And we all prefer to do our own interfaces. Problem is it costs a fortune and clients don't want to deal with it. The fully customized interface is SAQ D compliance scope. Pull that SAQ from PCI doc library.  67 pages of bullet points. That is your security protocol. Have to hire certified vulnerability scanners and pen testers quarterly.  That alone will cost you some bucks. And that set of requirements only covers about 4 to 8 of the bullet points. You've still got 66 pages left. 

Part of what you missed is that on the customizable js form, the cc data is tokenized in the browser.

WandaAZ
Member