Introduction Authorize.Net® is unquestionably the most popular payment gateway in use today. In fact, it is synonymous with ecommerce and is often confused as a payment processor. Its vast popularity with shopping carts, it is integrated with every major and minor shopping cart available, make it a natural choice for merchants wishing to begin processing sales online. But what if you are implementing a custom shopping cart solution? You will need to integrate Authorize.Net’s payment gateway into your application yourself. Fortunately this task is less daunting then it sounds. Below we will explore every aspect of processing a transaction in detail and write code that will allow us to seamlessly integrate the Authorize.Net payment gateway into our application. Goals As with any project you undertake, a clear set of goals should be outlined. The goals we have set forth for our project is to write PHP code that: * will integrate with the Authorize.Net API seamlessly We do not want our customers to leave our website or think they are leaving our website at any time. We want a clean, seamless transaction process that presents our business in a professional manner. * is easy to use
We do not want to spend a lot of time integrating the gateway into our website. That time would be better spent promoting the website so we can make money. * is reusable Web developers and aggressive entrepeneurs will open more then one ecommerce store. We definitely do not want to reinvent the wheel when it comes to integrating a payment gateway so we will want to make sure the codee we write can be easily transported from integration to integration. Getting Started Before we get to the technical nitty gritty of integrating the Authorize.Net payment gateway into an ecommerce application, we have to make sure we have everything we need. Some technical requirements will need to be met if we wish for the code we will write to function properly. We should acquire some useful tools and documentation that will help us understand the inner workings of the Authorize.Net API. We also need to make sure we, as developers, have the technical know-how to handle a task of this magnitude. Technical Requirements Before we write a line of code we will need to make sure our server meets the minimum technical specifications for our code to work. You can easily check if your server is properly configured by using PHP’s phpinfo() function. * PHP 5 The code that we will be using in this article will be object-oriented. To ensure it is compatible with future applications it is written in PHP 5. This also offers much greater support for object-oriented programming (OOP) then PHP 4 and since we will want our code to be easily reusable, writing it in an object oriented syntax makes good sense. To download PHP 5 go to the PHP download page. For a detailed overview of what has changed from PHP 4 to PHP 5, see the What’s New in PHP 5 from Zend. * CURL CURL is a command line tool for transferring files with URL syntax, supporting FTP, FTPS, TFTP, HTTP, HTTPS, TELNET, DICT, FILE and LDAP. CURL supports SSL certificates, HTTP POST, HTTP PUT, FTP uploading, HTTP form based upload, proxies, cookies, user+password authentication (Basic, Digest, NTLM, Negotiate, kerberos…), file transfer resume, proxy tunneling and a busload of other useful tricks. PHP supports CURL through the libcurl library. The libcurl library is not enabled by default and also requires the libcurl library to be installed on the server. Libcurl version 7.10.5 or higher is required to work with PHP 5. You can download libcurl from the developer’s website. When recompiling PHP to work with libcurl you must be sure to compile PHP ‘–with-curl’. You can read more about binding PHP with CURL on the PHP website. * OpenSSL The OpenSSL Project is a collaborative effort to develop a robust, commercial-grade, full-featured, and Open Source toolkit implementing the Secure Sockets Layer (SSL v2/v3) and Transport Layer Security (TLS v1) protocols as well as a full-strength general purpose cryptography library. The project is managed by a worldwide community of volunteers that use the Internet to communicate, plan, and develop the OpenSSL toolkit and its related documentation. OpenSSL version 0.9.6 or higher is required to work with PHP 5. You can download OpenSSL from the developer’s website. When recompiling PHP to work with OpenSSL you must be sure to compile PHP ‘–with-openssl’.
Authorize.Net
Since this article is about integrating the Authorize.Net payment gateway into an ecommerce application, it stands to reason that we would have some basic requirements concerning it. Authorize.Net provides developers a set of tools to assist with the integration of their software. Utilizing these tools will make our job easier and less prone to error.
- Request a Test AccountNaturally it is very difficult to develop any application without having all of the necessary components available for testing. A web developer who is integrating the Authorize.Net gateway into an existing merchant account can use their instance of the merchant’s gateway and turn on test mode to test their application. But if you are a web developer who is developing your own software that will need to integrate with Authorize.Net gateway, like a shopping cart, or wish to get into the ecommerce development arena, you will not have an Authorize.Net account to test your code on.Fortunately the developers at Authorize.Net had the foresight to understand that not every developer will have an Authorize.Net account to test on and will not want to wait until they have a customer to start writing their code. (Plus having a testing environment available for developers allows more applications to be certified thus potentially growing their marketshare). For these developers Authorize.Net has a system in place for allowing developers to have fully functional test accounts to test their integration code.You can request a test account by going to http://developer.authorize.net/testaccount/ and completing their short application. It takes about one business day to receive your account credentials which is why I recommend doing this step first. While you wait you can start writing your code using what can be found on step 2…
- Download the Implementation GuideWhile you wait for your test account credentials to be provided to you by Authorize.Net, you should download the documentation which explains how to communicate with their API. Their documentation is in pdf format and can be downloaded here: Advanced Integration Method Integration Guide
. It offers a clear explanation of all of their API calls and should explain what you need to do to communicate successfully. - Sample CodeIf reading boring documentation is not the best way for you learn, Authorize.Net offers yet another way to learn more about their API. You may request sample code to demonstrate how to connect successfully to their API. They offer sample code for ASP (VBScript), ASP.Net (Using C# or VB.NET), Cold Fusion, Java, Perl, and PHP. The code samples work so writing code to work with their API can be as simple as modifying their code.
Assumptions
The scope of this article, integrating the Authorize.Net payment gateway, provides us with a narrow topic on which to focus (which is a good thing). To keep this article focused on the topic at hand we will not delve into basic programming skills and techniques. Assumptions that are made in this article include:
- Validated Basic DataIt will be assumed that you have some basic PHP programming skills with basic to moderate programming experience. A basic part of any application which receives data from a user is to validate that data. This means ensuring that all required data is present as well is a value that is valid for that field. An example would be verifying that a zip code is actually a five digit number and not just “asdf”. To keep the focus on implementing the Authorize.Net gateway it will be assumed that your application has already validated all of the user’s input and that it is safe to use. However, we will cover validating credit card information as it does fall within the scope of this article.If you are unfamiliar with validating data there are plenty of tutorials online. A couple of good ones are offered by HTML Center and Codewalkers.
- Familiar with Object Oriented DevelopmentObject Oriented Development (OOP) offers a developer an opportunity to create a modular application that features reusable code.If you need to learn more about object oriented programming and design you should read An Introduction to Object-Oriented Design and also checkout WikiPedia’s entry for Object-oriented programming.
- Familiar with Regular ExpressionsRegular expressions are a common tool used by many programming languages for matching patterns in strings. Its use in data validation is essential as it can allow for very precise validation of user input. There are a few variations of regular express syntax. This article will use the most common and powerful version: the Perl Compatible Regular Expressions (PCRE). PCRE is used by the most common web development languages such as Perl, PHP, and Java. For a tutorial see PHP’s page on PCRE Syntax and the WikiPedia Entry for regular expressions.
Planning the Transaction
Before we start to tackle processing the credit card payment programmatically, we should have an understanding of how the customer data flows from the beginning of the process (they submit the form) to the end of the process (they are informed of the success of their transaction). This will not only give us a better understanding of how an online payment works, but will also allow us to plan for contingencies like a processing error or declined transaction. Below we will follow customer data from submission through completion.
- Capture Customer InformationThe transaction process begins with the submission of the customer data including their credit card information. At this point you should validate it and, if there are any errors, return the user to the checkout page and ask them to correct any errors. If the information is correct you will need to prepare it so it will be in the format Authorize.Net is expecting (you may ask the customer for the information in one format that is easy for them to understand, but that may not be compatible with the parameters Authorize.Net is expecting).What we’ll need to do:
- Receive customer submitted data
- Validate all customer submitted data
- Inform the customer of any errors
- Ensure all data is in proper format for submission to the Authorize.Net API
- Send Data to Authorize.NetOnce you have validated the data submitted by the customer and have ensured it is in the proper format Authorize.Net is expecting you will need to send it to them via their API. Authorize.Net then passes the transaction information on to the processing bank associated with the merchant account linked to this instance of the gateway. The processing bank will send a response back to Authorize.Net including whether the transaction was approved and the results of AVS.What we’ll need to do:
- Connect to the Authorize.Net API
- Send the transaction data
- React to the ResponseUpon successful communication with the processing bank Authorize.Net will return a response to your application. There are three possible responses that we will need to deal with:
- Approval/SuccessThe transaction was approved by the processing bank. The merchant will be credited with their funds in a couple of business days and the customer will see the charge on their next credit card statement.
- DeclineThe transaction was declined by the processing bank. For reasons known only to the processing bank, meaning you cannot find out why the transaction was declined, this sale was declined. The merchant will not get paid and the customer will not be charged.
- ErrorSomewhere between your application sending the transaction data to Authorize.Net and your application receiving the data back an error occurred. The transaction was not processed and cannot be considered approved or declined.
Each result will require a different response by your application:
- Approval/SuccessAt the very least your application should display a message indicating the transaction was successful. Ideally your application will present the customer with a printable receipt that they can keep for their records and a confirmation email will be sent as well.
- DeclineBecause the transaction was not successful we essentially can consider it to be an error. It would be no different then if the customer entered incorrect information into the order form. The customer should be informed of the results of the transaction and be offered another opportunity to pay using a different credit card.Tip: You may want to store the credit card information into a session variable and compare it to the new credit card information submitted by the customer. If they match you should flag it as an error without ever sending it to the gateway to be processed. Since the odds of it being declined twice is very high, almost 100%, you can save money by not incurring a transaction fee for the new declined transaction.
- ErrorThere are a variety of reasons an error can occur. Since most of them are out of our control and beyond the scope of this article, we’ll only concern ourselves with how we might handle them. Basically we have two options:
- Try AgainTemporary connection errors and other various errors happen from time-to-time and there is no reason one won’t occur while trying to process a transaction. Just like any other computer error there is no harm in trying again. And considering a sale is at stake it makes sense that we will try again. Trying again is as simple as re-sending the transaction information back to Authorize.Net.
- Inform the customer of the errorRepeated processing errors is an indication that a transaction will not be successful. This does not mean the sale will necessarily be declined, but unfortunately something beyond your control is preventing the transaction from being processed properly. At this point all you can do is inform the customer of the error and invite them to make payment in an alternate way (e.g. Paypal, or by telephone).
What we’ll need to do:
- Receive the response from Authorize.Net
- React to the response based on the results of the transaction
Building our Class
Now that we have an understanding of how a transaction will flow we can build our class around it. We should read through the Advanced Integration Method Integration Guide
before we begin so we understand what Authorize.Net will be expecting from us.
Naming the Class
Naturally any good class name will indicate what the objects that class will create represents. For our class we will use the nickname for Authorize.Net in the credit card processing industry: Authnet.
class Authnet { // ... }
Class Properties
Immediately after declaring our class we will need to declare the properties we will need for storing our objects properties. All of our properties will be private as we do not want our scripts to be accessing any of these values without going through a method. The first two properties we will declare are our Authorize.Net login and transaction key:
private $login = "ertdev6345"; private $transkey = "SR2dsf54dEn7vFLQ"; The login is used to login into the merchant’s control panel as well as identifying the merchant to Authorize.Net’s API. The transaction key is a random sequence of characters that acts like a password for API transactions. It is a security measure that prevents the merchant from putting their true account password into their scripts in an effort to help keep them safe.
Speaking of safe, that is the very reason we will hardcode this information into our class as opposed to making them parameters of the constructor. By placing this information directly in our class we can keep it out of our webpage’s code. If the server experiences an error and were to suddenly display our source code, this sensitive information would not be available to the general public. It also allows us to place this class outside of our web root so it cannot be displayed by a web browser.
The Authorize.Net login will be provided by Authorize.Net upon the accounts creation. You can get your transaction key by following these steps:
- Login into your account at Authorize.Net
- Click on ‘Settings’
- Click on ‘Transaction Key’
- Enter the answer to your secret question
- Click on the checkbox to disable your old transaction key
The next three properties will determine if our transaction was successful (approved), declined, or an error occurred. You’ll notice that $approved and $declined are both set to false while $error is set to true. This is because it is better to assume there is an error and either try again or abort the process then to assume a sale was approved only to find out later it wasn’t (and the merchant already shipped their order).
private $approved = false; private $declined = false; private $error = true; The main function of the Authorize.Net API is to pass data back and forth to complete a transaction. The next two properties store the data we will be passing to Authorize.Net and the data we will be receiving respectively. The $params parameter is an array that will hold the parameters that we be passing to the Authorize.Net API. The $results parameter is an array that will hold the parameters that we be receiving from the Authorize.Net API (after a little bit of processing that is).
private $params = array(); private $results = array(); Since we cannot send arrays to the Authorize.Net API nor can we receive them, we will need a place to store our parameters in a format that Authorize.Net is expecting as well as a place to receive their response. The $fields parameter will store our properly formatted parameters for us (this will be done in a method described later in this article) . The $response parameter will store the raw data of the return response from the Authorize.Net API.
private $fields; private $response; Finally, this last parameter probably can be done without, but for the sake of easier testing I have decided to include it in our class. This member will simply store a boolean value to determine whether we are currently testing our integration or processing live sales. Authorize.Net offers a special URL that is to be used for testing an integration of their API. Setting this member to TRUE will cause our Authnet object to use that URL for all transactions until we set it to false. (We will see this in action in our _construct method).
private $test;
Constructor
New in PHP 5 is the __construct() function for creating an instance of an class. This function creates the object and can assign properties to it by assigning values to properties of the class. Inside our constructor we will be assigning values to properties that we will not be changing during the course of using our object. Let’s look at what our __construct() function will look like and then break it down:
public function __construct($test = false) { $this->test = trim($test); if ($this->test) { $this->url = "https://test.authorize.net/gateway/transact.dll"; } else { $this->url = "https://secure.authorize.net/gateway/transact.dll"; } $this->params['x_delim_data'] = “TRUE”; $this->params['x_delim_char'] = “|”; $this->params['x_relay_response'] = “FALSE”; $this->params['x_url'] = “FALSE”; $this->params['x_version'] = “3.1″; $this->params['x_method'] = “CC”; $this->params['x_type'] = “AUTH_CAPTURE”; $this->params['x_login'] = $this->login; $this->params['x_tran_key'] = $this->transkey; } Let’s start with the constructor declaration:
public function __construct($test = false) We’ve made our constructor function public so our application can access it to create an object. We also have one default parameter. This parameter is optional as we have provided a default value for it if one is not supplied during the creation of a new object.
$this->test = trim($test); if ($this->test == true) { $this->url = "https://test.authorize.net/gateway/transact.dll"; } else { $this->url = "https://secure.authorize.net/gateway/transact.dll"; } You can see the parameter for the constructor is assigned to the parameter $test. If we pass a value of TRUE as the parameter during the creation of our object we will tell that object to use the test URL for the Authorize.Net API. The if/else statement below it chooses the appropriate URL to use for our test transactions.
The next portion of our constructor makes use the $params array we declared earlier in our class. It assigns values to some parameters the Authorize.Net API will be expecting.
$this->params['x_delim_data'] = “TRUE”; $this->params['x_delim_char'] = “|”; $this->params['x_relay_response'] = “FALSE”; $this->params['x_url'] = “FALSE”; $this->params['x_version'] = “3.1″; These five values collectively tell Authorize.Net how we intend to use their API. Since they have little value to our overall understanding of how to use their API we will avoid going into them in great detail. You can read more about what each of these parameters do in their implementation guide.
$this->params['x_method'] = “CC”; $this->params['x_type'] = “AUTH_CAPTURE”; The next two parameters tell Authorize.Net what kind of transaction we are running. The ‘x_method’ parameter tells Authorize.Net that this will be a credit card transaction (you can process eCheck transactions if the gateway has been established with that functionality). The ‘x_type’ parameter tells Authorize.Net that we wish to authorize and capture this transaction.
Authorizing but not charging a credit card
When credit cards are processed it actually is a two stage process. The first stage acquires and authorization number from the card issuing bank. The funds for that transaction are frozen and associated with that authorization number. The second stage if the actual capture of that sale where the funds are deducted from the customer’s balance. The vast majority of Internet transactions perform both stages at once. But this is not always the case. It is possible that a merchant may want to freeze the funds on a credit card but not actually charge the customer until they ship the order. This is called an ‘authorization only’ transaction. In these cases the merchant is provided with the authorization number and uses this authorization number at a future date to claim those funds.
$this->params['x_login'] = $this->login; $this->params['x_tran_key'] = $this->transkey; These last two parameters are our login and transaction key for the API. Obviously without these our access to the API will be denied.
Methods
Now that we have established what the properties for our class will be we will need to create some methods that will allow us to interact with them as well as to do the work our class is designed for.
public function transaction($cardnum, $expiration, $amount, $cvv = "", $invoice = "", $tax = "") { $this->params['x_card_num'] = trim($cardnum); $this->params['x_exp_date'] = trim($expiration); $this->params['x_amount'] = trim($amount); $this->params['x_po_num'] = trim($invoice); $this->params['x_tax'] = trim($tax); $this->params['x_card_code'] = trim($cvv); } The transaction() method assigns values to some of the properties that we did not have values for when we first created our object. These properties contain the necessary information to process the customer’s credit card. This includes the credit card number, expiration date, and amount of the transaction.
We also have three optional parameters that are not required to process our transaction but under certain circumstances will be good to have. Certain types of credit cards require additional parameters to be sent to the processing bank during a transaction. For example, business cards require an invoice number (also called a purchase order number) and the tax amount for the sale to be submitted with each transaction. If they are not, that sale will downgrade to a much higher processing rate for the merchant.
Tip: There is no way to check to see if a credit card is a business card without physically viewing the card (even then you cannot always tell). If keeping merchant accounts fees to a minimum is important to the merchant, always submit an invoice number and tax amount with every transaction. It will never hurt the transactions that do not require this information and will prevent the ones that do from downgrading to a higher rate.
The CVV2 number is a security measure designed to help reduce fraud in card not present transactions. Some credit card issuing banks will decline a transaction if the CVV2 number is incorrect. Authorize.Net can even be set to automatically decline any transaction that fails a CVV2 check. Even though this field is optional in our class, there is no reason not to send this information with every transaction.
public function process($retries = 3) { $this->prepareParameters(); $ch = curl_init($this->url); $count = 0; while ($count < $retries) { curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, rtrim($this->fields, "& ")); $this->response = curl_exec($ch); $this->parseResults(); if ($this->getResultResponseFull() == "Approved") { $this->approved = true; $this->declined = false; $this->error = false; break; } else if ($this->getResultResponseFull() == "Declined") { $this->approved = false; $this->declined = true; $this->error = false; break; } $count++; } curl_close($ch); } This method is the meat and potatoes of our class. It sends the transaction information and receives the response from the Authorize.Net API. It takes one parameter, $retries which has a default value of 3. This is the number of attempts that we will make to contact Authorize.Net and process a transaction. Earlier we had mentioned that this was one possible solution to dealing with errors when communicating with the Authorize.Net API. Here we have decided that three attempts are enough. If it does not connect after three attempts, it probably isn’t going to work in a reasonable amount of time and we should fall back to another solution (like inviting the customer to call in their order).
Our next line of code: $this->prepareParameters() calls a private method that as the name would suggest prepares our parameters to be sent to the Authorize.Net API. We’ll cover this method shortly.
To connect to the Authorize.Net API we have chosen to the built in CURL library. It makes interacting with remote servers easy. This line $ch = curl_init($this->url) initializes a new session and return a CURL handle for use with the other CURL functions.
Before we contact the Authorize.Net API we need to keep track of how many attempts we make before we give up. We do this by with this line: $count = 0.
curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, rtrim($this->fields, "& ")); $this->response = curl_exec($ch); These four lines of code do the hard work for communicating with the Authorize.Net API. The first line tells CURL to include header information in its output. The second line tells CURL to store the response as a string instead of outputting it to the browser. The third line provides CURL with the string to send to the Authorize.Net API which for us is our parameter string created by $this->prepareParameters(). The fourth line sends the request to the API and receives and stores the response.
To know whether our transaction was successful or not, and more, we need to parse the results. Our private method parseResults() does this for us. We will cover this method below.
if ($this->getResultResponseFull() == "Approved") { $this->approved = true; $this->declined = false; $this->error = false; break; } else if ($this->getResultResponseFull() == "Declined") { $this->approved = false; $this->declined = true; $this->error = false; break; } $count++; Now that we have our results we need to determine whether our transaction was successful, declined, or experienced an error. Using the getResultResponseFull() method (covered later) we can find the status of our transaction. If the transaction is “Approved” or “Declined” we set our status properies approriately. We will use the break statement to end our while loop since we do not need to connect to the API any longer. If the transaction is neither “Approved” nor “Declined” we can assume an error occurred. In this case we will increment our counter and try again.
private function prepareParameters() { foreach($this->params as $key => $value) { $this->fields .= "$key=" . urlencode($value) . "&"; } } Before we can send our transaction information to Authorize.Net we need to make sure that information is in a format they are expecting. prepareParameters() takes the values in this array and separates each key/value pair with a pipe. It then spearates each set of parameters with an ampersand (&). We store the results in $this->fields to be sent when we process the transaction.
private function parseResults() { $this->results = explode("|", $this->response); } When we receive the response from the Authorize.Net API we will need to convert it into a format that we find easy to use (just like we had to format our parameters to their specifications). Fortunately this is as easy as splitting a pipe-delimited string. In our constructor we told the Authorize.Net API that we will be using a pipe (”|”) as our delimiting character ($this->params['x_delim_char'] = “|”) so we know we need to split the values by looking for it. We store the results in the $this->results array for later accessing.
public function setParameter($param, $value) { $param = trim($param); $value = trim($value); $this->params[$param] = $value; } The Authorize.Net API can accept over 80 parameters when submitting a transaction. Only a few are required but many are handy to use for various reasons ranging from enhanced security to better record keeping. Our array $this->params stores these fields for us. We can add fields to this array using the setParameter() method. The first parameter of this function is the name of the parameter you wish to send. You can refer to the Advanced Integration Method Integration Guide
to see what parameters are available for use. The second parameter to our method is the value you wish to set.
public function getResultResponse() { return $this->results[0]; }When a transaction is processed and Authorize.Net returns the results of that transaction, it sends 73 fields back containing various pieces of information about the transaction. These 73 fields are all contained in the $this->results array created by the parseResults() method. The first field contains a numerical indicator of the results of our transaction. Our method getResultResponse() returns that number directly to our script. If you choose to use this method you will receive one of the following numbers:
public function getResultResponseFull() { $response = array(”", “Approved”, “Declined”, “Error”); return $response[$this->results[0]]; }
- 1 - Indicates an Approval
- 2 - Indicates a Decline
- 3 - Indicates an Error
To make displaying this easier, and also making our script possibly easier to read, we can use getResultResponseFull() to output a human-readable result of our transaction. We simply put the human-readable results into an array and use the response code as our array key.
public function isApproved() { return $this->approved; }These three methods are just accessor methods that allow our scripts to access private properties of our class. In these three cases they allow a script do determine the status of a transaction. The names of the methods will make it very clear in your script what you are trying to accomplish (checking the status of the transaction) and will promote readability which makes maintaining your script much easier.
public function isDeclined() { return $this->declined; }
public function isError() { return $this->error; }
public function getResponseText() { return $this->results[3]; }Just like we have created accessor methods for the results of the transaction, we can create accessor methods to access the other 72 fields returned by the Authorize.Net API. The four chosen for this article are important enough to be listed here are:
public function getAuthCode() { return $this->results[4]; }
public function getAVSResponse() { return $this->results[5]; }
public function getTransactionID() { return $this->results[6]; }
- getResponseText()If an error occurs or a transaction is declined, this field will contain text explaining what happened. If it is approved it will simply say, “This transaction has been approved.”.
- getAuthCode()This is the six-digit approval code provided by the processing bak for the transaction. This is good to have for any transaction and vital for AUTH_ONLY transactions.
- getAVSResponse()This is a one character response indicating the results of AVS. The results of AVS can be very useful in determining whether a transaction may be fraudulant or not. Here are the important AVS codes to know:
- X or Y - Both the numeric address and the Zip code match the card issuing bank’s database.
- A - Address matches but the Zip code does not.
- W or Z - Zip code matches but numeric address does not.
- N - Neither the zip code or street address matches.
- U - The issuing bank doesn’t support AVS.
- G - An international credit card. AVS is not supported.
- getTransactionID()This is the transaction ID assigned to this transaction by Authorize.Net. When researching this transaction on their server this will be handy to have.
Before We Process the Transaction
Although at the beginning of this article we stated that we will assume that you know how to validate data submitted by the customer. This much is still true. However, you may not necessarily know how to validate credit card specific information as you have never encountered it before. Below we provide techinques for validating the essential elements of a credit card.
Credit Card Number
Credit card numbers are never longer then 16 digits. The INPUT form field used to collect this data should have a MAXLENGTH of 16 (maxlength=’16′) set to prevent users from entering more digits then is allowed for any credit card issuer.
- VisaVisa credit cards are always 16 digits long and start with a four (4). Users may enter this in any of the following formats:
- XXXX-XXXX-XXXX-XXXX
- XXXX XXXX XXXX XXXX
- XXXXXXXXXXXXXXXX
Here is our code to validate a Visa credit card:
if (preg_match('/^4\d{3}[ \-]?\d{4}[ \-]?\d{4}[ \-]?\d{4}$/i’, $visa_number))
{
// Visa number is correct
}
else
{
// Visa number is incorrect
} - MasterCardMasterCard credit cards are always 16 digits long and start with a five (5). Users may enter this in any of the following formats:
- XXXX-XXXX-XXXX-XXXX
- XXXX XXXX XXXX XXXX
- XXXXXXXXXXXXXXXX
Here is our code to validate a MasterCard credit card:
if (preg_match('/^5\d{3}[ \-]?\d{4}[ \-]?\d{4}[ \-]?\d{4}$/i’, $mastercard_number))
{
// MasterCard number is correct
}
else
{
// MasterCard number is incorrect
} - American ExpressAmerican Express credit cards are always 15 digits long and start with three (3). Users may enter this in any of the following formats:
- XXXX-XXXXXX-XXXXX
- XXXX XXXXXX XXXXX
- XXXXXXXXXXXXXXX
Here is our code to validate a American Express credit card:
if (preg_match('/^3\d{3}[ \-]?\d{6}[ \-]?\d{5}$/i’, $amex_number))
{
// American Express number is correct
}
else
{
// American Express number is incorrect
} - Discover CardDiscover Card credit cards are always 16 digits long and start with 6011. Users may enter this in any of the following formats:
- XXXX-XXXX-XXXX-XXXX
- XXXX XXXX XXXX XXXX
- XXXXXXXXXXXXXXXX
Here is our code to validate a Discover Card credit card:
if (preg_match('/^6011[ \-]?\d{4}[ \-]?\d{4}[ \-]?\d{4}$/i’, $discover_cc_number))
{
// Discover Card number is correct
}
else
{
// Discover Card number is incorrect
}
So how do we wrap this all together into something coherent that can be practically applied to a website? We will take the credit card number and look at the first number of the credit card number. We will then validate it based on whether it is a 3, 4, 5, or 6. If it isn’t any of the four we’ll just tell the user to try again.
$cc_number = trim($_POST['cc_number']); $first_number = substr($cc_number, 0, 1);Verifying that a credit card has the correct number of digits and starts with the correct number is a good start to verifying a credit card number. But it is still fairly easy to work around. Any 16-digit number starting with a 4, 5, or 6 will pass this check. To help eliminate erroneous credit card numbers from being submitted there is one more check that can be performed. All of the major credit card institutions use a checksum to validate their credit cards. Each digit of the credit card is multiplied by 1 or 2. The last digit of the multiplication is added for each number in the credit card. If the resulting number is divisible by 10 it is a valid credit card number.
switch ($first_number) { case 3: if (preg_match(’/^3\d{3}[ \-]?\d{6}[ \-]?\d{5}$/’, $cc_number)) { // American Express number is correct. Process the credit card. } else { // error } break; case 4: if (preg_match(’/^4\d{3}[ \-]?\d{4}[ \-]?\d{4}[ \-]?\d{4}$/’, $cc_number)) { // Visa number is correct. Process the credit card. } else { // error } break; case 5: if (preg_match(’/^5\d{3}[ \-]?\d{4}[ \-]?\d{4}[ \-]?\d{4}$/’, $cc_number)) { // MasterCard number is correct. Process the credit card. } else { // error } break; case 6: if (preg_match(’/^6011[ \-]?\d{4}[ \-]?\d{4}[ \-]?\d{4}$/’, $cc_number)) { // Discover Card number is correct. Process the credit card. } else { // error } break; default: // error }
Here is the PHP code:
// The credit card number
$cc_number = "4000123498762345";
// Our starting checksum
$checksum = 0;
// Alternating value of 1 or 2
$j = 1;
// Process each digit one by one starting at the right
for ($i = strlen($cc_number) - 1; $i >= 0; $i–)
{
// Extract the next digit and multiply by 1 or 2 on alternative digits.
$calc = substr($cc_number, $i, 1) * $j;
//
// If the result is in two digits add 1 to the checksum total
if ($calc > 9)
{
$checksum = $checksum + 1;
$calc = $calc - 10;
}
// Add the units element to the checksum total
$checksum += $calc;
//
// Switch the value of j
if ($j == 1)
{
$j = 2;
}
else
{
$j = 1;
}
}
// If checksum is divisible by 10 the credit card number is valid
if ($checksum % 10 == 0)
{
// It’s a valid credit card number
}
else
{
// It’s not valid
}
How can you tell if a credit card is legitimate?
After reading how to validate a credit card number you may think if a credit card passes validation that it is a legitimate credit card. This is not the case. Obviously a credit card in an improper format is not legitimate. But a credit card number may be in proper format and still be illegitimate.
So, how do you verify a credit card number is legitimate? The only way is to verify the legitimacy of a credit card is to authorize a sale. This requires using the payment gateway to send a transaction to the processing bank. The best way to do this is to do an AUTH ONLY transaction. This is similar to a sale transaction but does not charge the customer. It only freezes the funds on the customer’s credit card for a short period of time (no more then 30 days) and they are completely unaware of it as it does not appear on their statement. This makes it ideal for verifying their credit card is legitimate.
So, to verify a credit card is legitimate without actually charging, do an AUTH ONLY transaction for $1.00 and see if it is approved. If it is, the credit card is legitimate.
Expiration Date
The expiration date is not very difficult to validate compared to the credit card number and CVV2 number (see below). You really only have two issues to be concerned about:
- The expiration date is a four digit numberAuthorize.Net expects you to submit a four digit number as the expiration date for the credit card. The format they are expecting is MMYY. If the month is a single digit number (e.g. 1-9 for January through September) you must prefix it with a zero. The year is the last two numbers of the year. So, if the credit card expires in the year 2010 then you would drop the ‘20′ and keep the ‘10′. So, a credit card that expires in August 2010 would have an expiration date of ‘0810′.An easy way to do this is to use two SELECT menus in your HTML. One for the month, one for the year the card is set to expire. That way you can have the form send you the date in the format you prefer and all you need to do is concatenate the two values:
$expiration_date = $_POST['expire_month'] . $_POST['expire_year'];
- The expiration date is not a date in the pastNaturally an expiration date should be a future date. Any date from the past should automatically flag the credit card as being invalid. The current month is considered a future date as a date is not considered expired until the full month is over. That means if a credit card has an expiration date of September 2010, its implied expiration date is September 30, 2010 at 23:59:59. We will compare the current year with the expiration date’s year. If it is sooner then this year, the date is invalid. If the year is the same as this year we will check the month to see if it has passed as well. If it hasn’t, we have a valid expiration date.
$current_month = date("m"); $current_year = date("y"); if ($_POST['expire_year'] < $current_year) { // Invalid date } else { // Check if the same year, // if so, make sure month is current or later if ($_POST['expire_year'] == $current_year) { if ($_POST['expire_month'] < $current_month) { // Invalid date } else { // Valid date } } }
CVV2
CVV2 is a credit card security measure aimed at reducing fraud for card not present transactions. It is a three or four digit number that is only present on the credit card. Theoretically, this is used to verify that the credit card being used in a purchase in the in the possession of the purchaser at the time of the transaction making the sale more secure.
This code can be found in varying places on a credit card and is called different names by each of the major credit card companies:
- VisaVisa places their three digit code, which they call “Card Validation Code” (CVC2) on the back of the credit card in the signature panel. Usually at the very top-right most corner.
- MasterCardMasterCard places their three digit code, which they call “Card Verification Value” (CVV2) on the back of the credit card in the signature panel. Usually at the very top-right most corner.
- American ExpressAmerican Express places their four digit number, which they call “Card Identification Number” (CID) on the front of the credit card, usually toward the end of the credit card number.
- Discover CardDiscover Card places their three digit number, called “Cardmember ID”, on the back of the credit card in the signature panel. Usually at the very top-right most corner.
When accepting credit cards through a website, collecting the CVV2 number is essential. In the ecommerce world it is an important indicator as to the potential for fraud for a transaction. But as we’ve seen above, a CVV2 value may be three or four digits depending on which credit card a customer is using. So how do we validate it? By checking to see which credit card the customer is using and then looking for the correct amount of digits. We’ll find out which credit card the customer is using by looking at the first number of the credit card. We’ll specifically look for American Express cards as they are the odd balls and have a four digits CVV2 number. Visa, MasterCard, and Discover Card each have a three digit CVV2 number.
We’ll take the first digit of the credit card number and then check to see if it is a three. If it is a three, check to see if the CVV2 code is four digits long. Otherwise, check to see if the CVV2 code is three digits long. Here’s some simple PHP code that does this:
// The credit card number $cc_number = $_POST['cc_number'];
// The CVV2 number $cvv2 = $_POST['cc_cvv'];
// Extract the first number of the credit card $first_number = substr($cc_number, 0, 1);
// If the first number is a ‘3 it’s an American Express Card // And we need to verify the CVV2 number is four digits long // otherwise check to see if it is three digits long
if ($first_number == 3) { if (!preg_match("/^\d{4}$/", $cvv2)) { // It's an American Express card but its // CVV2 code is not four digits long. } } else { if (!preg_match("/^\d{3}$/", $cvv2)) { // It's not three digits long. } }
Using our Class
Now that we have a clear understanding of how the Authorize.Net API works, how we can use it, and how a transaction occurs, we can tie it all together into a cohesive unit.
Processing the Transaction
Thanks to our class handling almost all of the work integrating it into a script is very simple to do. Let’s look at a basic framework that uses our class and then break it down:
$payment = new Authnet(true); $payment->transaction($creditcard, $expiration, $total); $payment->process(); if ($payment -> isApproved()) { // Display a printable receipt } else if ($payment -> isDeclined()) { $reason = $payment -> getResponseText(); // As for another form of payment } else { // Ask the merchant to call us } The first line of code $payment = new Authnet(true) creates an instance our Authnet object and initializes all of the properties in the constructor. $payment->transaction($creditcard, $expiration, $total) assigns the credit card number, expiration date, and amount of the transaction we wish to process. $payment->process() sends the transaction to Authorize.Net for processing and returns the results to our object. All we need to do from here is find out if the transaction was approved, declined, or resulted in an error. A simple if/else statement handles this nicely.
You’ll notice that if our transaction is declined we use the getResponseText() method to find out why. This will be handy to let our customer know why their card was declined.
And that’s it! Believe it or not that’s all it takes to process a credit card transaction through Authorize.Net’s API. But there are a couple of shortcomings to our code:
- We do not do AVS
- We do not verify the CVV2 number
Fortunately, ensuring that both of these are done is very easy to do with our class:
$payment = new Authnet(true); $payment->transaction($creditcard, $expiration, $total, $cvv); $payment->setParameter("x_address", $business_address); $payment->setParameter("x_zip", $business_zipcode); $payment->process(); To make sure that we verify the CVV2 number we simply as it as the fourth parameter to our transaction() method. Performing AVS is slightly more involved but still very simple to do. We use the setParameter() method to add the street address and zip code to our list of parameters we will send to Authorize.Net. Now we have helped to reduce our risk of fraud and we only added two lines to our code!
Inducing a Declined Transaction
The test account offered by Authorize.Net will automatically approve all transactions by default. While this is important for testing your application’s response to approved transaction, it doesn’t help us test our application’s handling of declined transactions or errors. Fortunately forcing Authorize.Net to decline a transaction is easy to. Authorize.Net allows a merchant to have transactions be declined even if they were originally approved by the processing bank if AVS does not meet the merchant’s criteria for an acceptable response. We can take advantage of this to force our transactions to decline by creating a situation where AVS will fail to meet our own criteria.
To change our test account’s AVS settings follow these steps:
- Log into your test account
- Click on “Settings” (under “Account”)
- Click on “Address Verification Service” (under “Basic Fraud Settings”)
- Check the checkbox that says, “Reject if… Address information is not provided for AVS check (B)”
- Press the “Submit” button
Now to have a transaction declined we need only to submit a transaction without the street address and zip code (as we did in our first example of using our class). Without these two pieces of information our test account will automatically decline the transaction.
Inducing an Error
Just as we need to create the circumstances for our test transactions to be declined, we will need to do that same to produce an error. Fortunately this is just as easy to accomplish and we can do it by munging our own code. Simply changing the URL we use for contacting the Authorize.Net API we can cause our transaction to fail. In the example below we simply change the test URL to be oops.Authorize.Net:
if ($this->test == true) { $this->url = "https://oops.authorize.net/gateway/transact.dll"; }
Conclusion
We have covered a lot of ground in this article. We started by analyzing the transaction process from start to finish and identifying all possible branches to the transaction flow. From there we built upon the knowledge we gained from reading the Authorize.Net Advanced Integration Method Integration Guide
to construct a class to encapsulate our interaction with the Authorize.Net API. After validating unique transaction data we used our new class to easily process a transaction utilizing the Authorize.Net gateway.
At a glance our task may have seemed difficult to complete. Most developers, and merchants for that matter, know very little about credit card processing in general much less how to do it online. But after breaking it down and looking at the process step-by-step you can see it is not as complex as it first appears. Combined with our new class, processing transactions online has become much simpler and straight forward. Hopefully the task of processing transactions online will now become a regular part of your development portfolio.
Improving the Class
The code we have written in this class is fully functional and should give you everything you need to create a working processing script to interact with the Authorize.Net API. But that does not mean it is necessarily complete or well-written. Below are some suggestions for improving the class.
- Make it a static classWhen processing a transaction only one Authnet object needs to be created. To prevent multiple instances of it from existing we can force it to be a static class. To do this we will create a static variable that will keep track of how many instances of the Authnet object we have created. (Static variables are unique to a class as opposed to being unique to an object. This means every Authnet object we create will share the value of this variable including when another Authnet object changes that value). We can then check the value of this static variable when we attempt to create a new Authnet object. If there are no existing Authnet objects (i.e. the static variable has a value of zero) we will go ahead and create our object and increment the value of our static variable. If the value of the static variable is one (or more), we will not create our object and cause an error.
static $instances = 0;
public function __construct($test = false) { if (self::$instances == 0) { // Institiate Object
// Increment our static variable self::$instances++; } else { return false; } } - Changing the transaction typeThe vast majority of online merchants wish to have their credit card transactions processed in real time. But not all merchants wish to do this. Merchants with delayed delivery times or very strict fraud prevention methodologies in place will prefer to process their transactions at a later time. But that does not mean they cannot take advantage of this class. We can add a method that changes the transaction type to any acceptable type. This includes doing an AUTH_ONLY transaction. The mothod might look like this:
public function setTransactionType($type) { $this->params['x_type'] = strtoupper(trim($type)); } - Create more accessor methodsAlthough there are a total of 73 fields returned by the Authorize.Net API the code in this article only provides methods to access five of them. That leave 68 fields that we cannot access. It would be a simple task to create accessor methods to access each field using a descriptive name for each.
Further Discussion
Although the scope of this article was limited to the integration of the Authorize.Net gateway into your ecommerce application, it doesn’t mean we can’t point you in the right direction for related topics that might affect your application. Below are a few related topics that you should be aware of and some resources to help you understand how they might affect your project.
Electronic Commerce Indicator
Any transactions that originate online, that is the customer enters their payment information into an online form, must identify itself as such. Even if the transaction is not processed in real time it still must identify itself as originating online. This is called the Electronic Commerce Indicator (ECI). Authorize.Net is ECI compliant. To learn more about ECI read the entry in our merchant account blog entry, called the Electronic Commerce Indicator.
Storing Credit Card Numbers
It is possible that your application may store credit card numbers on the web server. Although this is legal and acceptable to the major card issuers, storing credit card numbers on your server is a ricky proposition. The recent security breaches that have comprimised tens of thousands of credit cards only highlight the risk and potential consequences of failing to store this information properly.
If you must store your customers’ credit card information on the server there are guidelines that should be followed to ensure the highest possible level of security is applied. Visa has created a standard for storing credit card information called the Payment Card Industry (PCI) Data Security Standard. It is part of Visa’s larger security initiative called Cardholder Information Security Program (CISP). You can read more about the PCI Data Security Standard in our article Visa’s PCI Data Security Standard Explained.
SSL Certificate
Naturally, part of developing a responsible, safe, and secure shopping experience for your customers includes having a SSL certificate installed on your web server. There are a variety of SSL providers available to choose from. Here are some of the more popular: Godaddy, Comodo, Thawte, and Verisign.
Source Code
Would you like a nice clean copy of the class created in this article? You can download a copy here: Authorize.Net AIM PHP
Looking for a more polished version of this script that is ready to go out of the box? You can download a copy of it here: Authorize.Net Integration Script (PHP) (Sorry, no documentation for it yet).
Discuss This Article
Want to discuss this article? Have questions about the content? Be sure to use our merchant account forums.
No user commented in " Integrate the Authorize.Net payment gateway seamlessly into your ecommerce website "
Follow-up comment rss or Leave a Trackback