Tutorial: Integrating the Authorize.Net AIM API with PHP

Working with the Authorize.Net AIM API in and of itself is very easy to do. Between the integration guide and sample code a good programmer can have a working solution in only minutes. But this code is for demonstration purposes only and isn’t suited for live production sites. A reusable concise solution is needed.

Fortunately I have taken the time to abstract the AIM API into my own class that not only simplifies the code we will need to work with that API but also makes it modular and easy to port from application to application. To begin you will need to download the AuthnetAIM class. You can find it here.

 

This code is written in PHP5. PHP4 has been officially retired by PHP and all of the major open source projects have committed to PHP5. If you aren’t programming in PHP5 yet, you should be. If your host doesn’t support PHP5 yet, find a new host.

 

To begin you will need to include the class using the require() function:

  1. require('AuthnetAIM.class.php');

As with any class/object the first thing we need to do is instantiate it. This can be done as follows:

  1. $payment = new AuthnetAIM('myapilogin', 'mYtRaNsaCTiOnKEy');

Up to three parameters are accepted in constructor with the first two being required. myapilogin is the API login for the account. mYtRaNsaCTiOnKEy is the transaction key generated in the Authorize.Net control panel.

If you have a Authorize.Net developer account you can use it with this script by setting the third parameters to TRUE to be true.

  1. $payment = new AuthnetAIM('myapilogin', 'mYtRaNsaCTiOnKEy', true);

Authorize.Net allows for a lot of information to be passed through their API. Only a few of these are actually required to process a transaction. The following snippet is the minimum amount of code required to successfully process a transaction:

  1. $payment = new AuthnetAIM('myapilogin', 'mYtRaNsaCTiOnKEy');
  2. $payment->setTransaction($creditcard, $expiration, $total);
  3. $payment->process();

First we create our Authorize.Net object and store it in a variable called $payment. We then called the setTransaction() method to set the three required pieces of information for processing a transaction: credit card number, credit card expiration date, and the total amount to be processed. If any of these pieces of information are omitted an exception will be thrown and the transaction will not be processed. Lastly we call the process() method which utilizes the Authorize.Net API to process the transaction and receive the response.

This basic code does not do AVS or CVV verification which, at the very least, means higher rates will be charged for the merchant but it also means they will be missing two important tools for reducing their exposure to fraud. To perform CVV verification we need only to add a fourth parameter to the setTransaction() method. To perform AVS we only need to provide the street address and zip code to Authorize.Net. We can do that using the setParameter() method which allows us to set predetermined parameters to be sent to the Authorize.Net API along with the transaction information (you can find all of the possible parameters in the integration guide):

  1. $payment = new AuthnetAIM('myapilogin', 'mYtRaNsaCTiOnKEy');
  2. $payment->setTransaction($creditcard, $expiration, $total, $cvv);
  3. $payment->setParameter("x_address", $business_address);
  4. $payment->setParameter("x_zip", $business_zipcode);
  5. $payment->process();

We can take it a step further and take advantage of Authorize.Net’s logging of transaction information and send over quite a bit of information through their API. Typically the complete billing address and shipping address, if necessary, are provided. Application specific user ids are also good to provide as they make matching a transaction to a user account that much easier to do.

There are other pieces of information that can be configured or provided to further customize a transaction. Two pieces of information that are a good idea to provide with each transaction is the total amount of tax charged to a sale and any invoice number associated with it. These pieces of information are required to processing business cards and since we cannot tell if a card being processed is in fact a business card it is simply a good idea to provide them with every transaction.

A parameter that can be configured programmatically is the window in which Authorize.Net will prevent a duplicate transaction from being processed. Basically this prevents a user from hitting the refresh button in their browser and processing their sale again. The x_duplicate_window parameter controls how long this window is open and is set in seconds.

Here is a sample transaction that sets the duplicate transaction window to three minutes, records the customer’s IP address, turns off the automatic email generated by Authorize.Net, provides an invoice number and tax amount, sends over complete billing and shipping addresses, and records the user id for this customer:

  1. $payment = new AuthnetAIM('myapilogin', 'mYtRaNsaCTiOnKEy');
  2. $payment->setTransaction($creditcard, $expiration, $total, $cvv, $invoice, $tax);
  3. $payment->setParameter("x_duplicate_window", 180);
  4. $payment->setParameter("x_cust_id", $user_id);
  5. $payment->setParameter("x_customer_ip", $_SERVER['REMOTE_ADDR']);
  6. $payment->setParameter("x_email", $email);
  7. $payment->setParameter("x_email_customer", FALSE);
  8. $payment->setParameter("x_first_name", $billing_firstname);
  9. $payment->setParameter("x_last_name", $billing_lastname);
  10. $payment->setParameter("x_address", $billing_address);
  11. $payment->setParameter("x_city", $billing_city);
  12. $payment->setParameter("x_state", $billing_state);
  13. $payment->setParameter("x_zip", $billing_zipcode);
  14. $payment->setParameter("x_phone", $billing_telephone);
  15. $payment->setParameter("x_ship_to_first_name", $shipping_firstname);
  16. $payment->setParameter("x_ship_to_last_name", $shipping_lastname);
  17. $payment->setParameter("x_ship_to_address", $shipping_address);
  18. $payment->setParameter("x_ship_to_city", $shipping_city);
  19. $payment->setParameter("x_ship_to_state", $shipping_state);
  20. $payment->setParameter("x_ship_to_zip", $shipping_zipcode);
  21. $payment->setParameter("x_description", $product);
  22. $payment->process();

The Authorize.Net API is not limited to processing sales only. All types of transactions can be performed including refunds and authorizations. To do an authorization without charging the credit card we can use the setTransactionType() method to change the transaction type to AUTH_ONLY. setTransactionType() accepts one of six possible values which are AUTH_CAPTURE, AUTH_ONLY, PRIOR_AUTH_CAPTURE, CREDIT, CAPTURE_ONLY, and VOID. AUTH_CAPTURE is the default for sale and is set automatically when you create the $payment object. Below is a sample AUTH_ONLY transaction:

  1. $payment = new AuthnetAIM('myapilogin', 'mYtRaNsaCTiOnKEy');
  2. $payment->setTransaction($creditcard, $expiration, $total, $cvv);
  3. $payment->setTransactionType("AUTH_ONLY");
  4. $payment->process();

Now that we know how to process a transaction, let’s see how we handle the results. Our AuthnetAIM class includes three methods for determining the status of the transaction. isApproved() will return true if the transaction was successful. isDeclined() will return true if the sale was declined. isError() will return true if there was some sort of error processing the transaction.

Using these three methods we can create a flow control structure to handle the response appropriately:

  1. if ($payment->isApproved())
  2. {
  3.     // Get the approval code
  4.     $approval_code  = $payment->getAuthCode();
  5.  
  6.     // Get the results of AVS
  7.     $avs_result     = $payment->getAVSResponse();
  8.  
  9.     // Get the Authorize.Net transaction ID
  10.     $transaction_id = $payment->getTransactionID();
  11.  
  12.     // Do stuff with this. Most likely store it in a database.
  13. }
  14. else if ($payment->isDeclined())
  15. {
  16.     // Get reason for the decline from the bank. This always says,
  17.     // "This credit card has been declined". Not very useful.
  18.     $reason = $payment->getResponseText();
  19.  
  20.     // Politely tell the customer their card was declined
  21.     // and to try a different form of payment
  22. }
  23. else if ($payment->isError())
  24. {
  25.     // Get the error number so we can reference the Authnet
  26.     // documentation and get an error description
  27.     $error_number  = $payment->getResponseSubcode();
  28.     $error_message = $payment->getResponseText();
  29.  
  30.     // Or just echo the message out ourselves
  31.     echo $payment->getResponseMessage();
  32.  
  33.     // Report the error to someone who can investigate it
  34.     // and hopefully fix it
  35.  
  36.     // Notify the user of the error and request they contact
  37.     // us for further assistance
  38. }

For debugging purposes the AuthnetAIM class overloads the __toString() method to display the current state of the $payment object in a clear and easy to read table. If you run the code below you will get two tables displayed on your screen, . The first will show the state of the object before the transaction is processed and the other will show it after.

  1. $payment = new AuthnetAIM('myapilogin', 'mYtRaNsaCTiOnKEy');
  2. $payment->setTransaction($creditcard, $expiration, $total, $cvv);
  3. echo $payment;
  4. $payment->process();
  5. echo $payment;

The AuthnetAIM class takes advantage of exceptions which are new in PHP5. These are only generated when something isn’t configured properly. This can be anything from the API login and transaction key to setting any parameters. Errors generated by Authorize.Net do not throw exceptions. You can use the new try/catch flow control structure to handle any exceptions generated by the class:

  1. try
  2. {
  3.     $payment = new AuthnetAIM('myapilogin', 'mYtRaNsaCTiOnKEy');
  4.     $payment->setTransaction($bad_information);
  5.     $payment->process();
  6. }
  7. catch (AuthnetAIMException $e)
  8. {
  9.     echo 'There was an error processing the transaction. Here is the error message: ';
  10.     echo $e->__toString();
  11. }

Now that we know how to process a sale, handle its response, and handle potential errors, let’s put it all together in one block so we can see it working all at once with a few extras thrown in to show you most of what this class can do:

  1. require('AuthnetAIM.class.php');
  2.  
  3. try
  4. {
  5.     $user_id = 1;
  6.     $email   = 'johnny@example.com';
  7.     $product = 'A test transaction';
  8.     $business_firstname = 'John';
  9.     $business_lastname  = 'Smith';
  10.     $business_address   = '123 Main Street';
  11.     $business_city      = 'Townsville';
  12.     $business_state     = 'NJ';
  13.     $business_zipcode   = '12345';
  14.     $business_telephone = '800-555-1234';
  15.     $shipping_firstname = 'John';
  16.     $shipping_lastname  = 'Smith';
  17.     $shipping_address   = '100 Business Rd';
  18.     $shipping_city      = 'Big City';
  19.     $shipping_state     = 'NY';
  20.     $shipping_zipcode   = '10101';
  21.  
  22.     $creditcard = '4111-1111-1111-1111';
  23.     $expiration = '12-2016';
  24.     $total      = 1.00;
  25.     $cvv        = 123;
  26.     $invoice    = substr(time(), 0, 6);
  27.     $tax        = 0.00;
  28.  
  29.     $payment = new AuthnetAIM('myapilogin', 'mYtRaNsaCTiOnKEy', true);
  30.     $payment->setTransaction($creditcard, $expiration, $total, $cvv, $invoice, $tax);
  31.     $payment->setParameter("x_duplicate_window", 180);
  32.     $payment->setParameter("x_cust_id", $user_id);
  33.     $payment->setParameter("x_customer_ip", $_SERVER['REMOTE_ADDR']);
  34.     $payment->setParameter("x_email", $email);
  35.     $payment->setParameter("x_email_customer", FALSE);
  36.     $payment->setParameter("x_first_name", $business_firstname);
  37.     $payment->setParameter("x_last_name", $business_lastname);
  38.     $payment->setParameter("x_address", $business_address);
  39.     $payment->setParameter("x_city", $business_city);
  40.     $payment->setParameter("x_state", $business_state);
  41.     $payment->setParameter("x_zip", $business_zipcode);
  42.     $payment->setParameter("x_phone", $business_telephone);
  43.     $payment->setParameter("x_ship_to_first_name", $shipping_firstname);
  44.     $payment->setParameter("x_ship_to_last_name", $shipping_lastname);
  45.     $payment->setParameter("x_ship_to_address", $shipping_address);
  46.     $payment->setParameter("x_ship_to_city", $shipping_city);
  47.     $payment->setParameter("x_ship_to_state", $shipping_state);
  48.     $payment->setParameter("x_ship_to_zip", $shipping_zipcode);
  49.     $payment->setParameter("x_description", $product);
  50.     $payment->process();
  51.  
  52.     if ($payment->isApproved())
  53.     {
  54.         // Get info from Authnet to store in the database
  55.         $approval_code  = $payment->getAuthCode();
  56.         $avs_result     = $payment->getAVSResponse();
  57.         $cvv_result     = $payment->getCVVResponse();
  58.         $transaction_id = $payment->getTransactionID();
  59.  
  60.         // Do stuff with this. Most likely store it in a database.
  61.         // Direct the user to a receipt or something similiar.
  62.     }
  63.     else if ($payment->isDeclined())
  64.     {
  65.         // Get reason for the decline from the bank. This always says,
  66.         // "This credit card has been declined". Not very useful.
  67.         $reason = $payment->getResponseText();
  68.  
  69.         // Politely tell the customer their card was declined
  70.         // and to try a different form of payment.
  71.     }
  72.     else if ($payment->isError())
  73.     {
  74.         // Get the error number so we can reference the Authnet
  75.         // documentation and get an error description.
  76.         $error_number  = $payment->getResponseSubcode();
  77.         $error_message = $payment->getResponseText();
  78.  
  79.         // OR
  80.  
  81.         // Capture a detailed error message. No need to refer to the manual
  82.         // with this one as it tells you everything the manual does.
  83.         $full_error_message =  $payment->getResponseMessage();
  84.  
  85.         // We can tell what kind of error it is and handle it appropriately.
  86.         if ($payment->isConfigError())
  87.         {
  88.             // We misconfigured something on our end.
  89.         }
  90.         else if ($payment->isTempError())
  91.         {
  92.             // Some kind of temporary error on Authorize.Net's end. 
  93.             // It should work properly "soon".
  94.         }
  95.         else
  96.         {
  97.             // All other errors.
  98.         }
  99.  
  100.         // Report the error to someone who can investigate it
  101.         // and hopefully fix it
  102.  
  103.         // Notify the user of the error and request they contact
  104.         // us for further assistance
  105.     }
  106. }
  107. catch (AuthnetAIMException $e)
  108. {
  109.     echo 'There was an error processing the transaction. Here is the error message: ';
  110.     echo $e->__toString();
  111. }

If you would like to learn more about how this class was written, be sure to read Integrate the Authorize.Net Payment Gateway with PHP. That article covers how to create a basic class that does everything we cover in this article and is a good primer for abstracting APIs with your own classes.

UPDATE 2009-09-16: I’ve updated this code a bit and have altered the tutorial to better reflect this. I’ve also, obviously, provided the newer code for download and changed the license to be LGPL from GPL.

UPDATE 2009-12-18: Apparently Godaddy.com got rid of their stupid proxy server so there’s no need to account for it. I’ve removed it from the code. I’ve also optimized handling connection errors and make exceptions thrown more informative.

Related Posts:

103 thoughts on “Tutorial: Integrating the Authorize.Net AIM API with PHP

  1. Hello Friend,

    i used this above code , and executed but it did not return anything , screen got blank only, please let me know any issue, and how can i resolve it because i just mentioned login id and transaction key.

    Thanks in advance..

    waiting for your response..

  2. It’s difficult to diagnose any issue without seeing code, but it looks like you have a PHP error in your code somewhere so the PHP interpreter has stopped executing your code. Make sure error reporting is enabled and turned up to show all errors including Notices.

    See this question and answers at Stack Overflow to learn how to enable reporting and get useful error messages from PHP.

  3. Hello Dear,

    How can i use e-transaction in place of using credit card or any other card because in case of credit card or any other card it is risky for customer to give card details.

    Please reply ..

    and thank you very much for my last reply..

Leave a Reply

Your email address will not be published. Required fields are marked *