In Part 1 of this series we identified our goals (creating a payment form that was usable, accessible, and secure) and began by creating the form we will use to capture payment information. In Part 2 of this series we continued this process by exploring how we will handle the data submitted by that form. In Part 3 of this series we took the data received and sanitized in Part 2 and validated that it was in a format we required. In Part 4 of this series we took the errors we found in Part 3 and displayed them in a user-friendly format to minimize cart abandonment. In this installment we will process the payment using the PHP SDK and handle the response in an appropriate manner.

Picking Up Where We Left Off

In part 4 of this series we helped our users who submitted erroneous information to find where they made an error and correct it. Once a user has submitted their payment without any errors it is time to process their payment. When a payment is submitted there are three potential scenarios that can occur:

The payment is approved

The payment is declined

An error occurs somewhere during the payment process

Each of these three scenarios require us to deliver custom responses to our users. How we handle the information submitted to us also will vary depending on your business needs. Let's look at how you might want to handle each of these scenarios one at a time.

The Payment Is Approved

Once the payment is approved we do not need anything else from our user. At this point we just want to complete the transaction and hand it off to whoever will be doing order fulfillment.

Our responsibilities will be to:

Tell the user that hey have successfully completed the checkout process

Provide them with a receipt and/or payment confirmation

Record the transaction

The Payment Is Declined

If a payment is declined we cannot complete the transaction as we do not have payment yet. However, the user is still present when this happens so all is not lost.

Our responsibilities will be to:

Present the user with the payment form again

Let them know their credit card was declined by their bank

Ask them to try another credit card

An Error Occurs Somewhere During The Payment Process

If an error occurs during the payment process, whether due to connectivity or server issues, things can become a bit complicated. Do we try again? Do we ask the user to try again? How do we handle this from a customer service point of view? Exactly how you want to handle this is a business decision you need to make.

In this example, our responsibilities will be to:

Present the user with the form again

Let them know an error occurred

Let the know their credit card was not charged

Ask the user to try again or

Ask the user to contact customer service to complete their order

Let's Write The Code To Do This

Once we have finished validating our user's data we need to check to see if there where any errors. We can do this by checking to see if there are any values in the $errors array. If there are we know not to process the transaction and display our error message to the user. If there are none we can attempt to process the transaction.

If you haven't done so already you will need to download the PHP SDK as we will use it in our example.

You can see we start of by checking the size of the $errors array and if it is zero we prepare to process the payment. We start by formatting the expiration date in a format the Authorize.Net will accept. In this case we choose to use the four digit year, a dash, and the two digit month. We follow that up by including the config file from the PHP SDK and initializing our the class that uses the AIM API. We set the code to use the development server so we don't incur any fees for our testing and then we provide the parameters needed to process the transaction.

We then process the payment and get the response object which we will use to determine the status of our payment. This is where we have to include some logic to handle the possible outcomes of the transaction. If the transaction is approved we collect the pertinent data returned to us by the merchant account provide: AVS results, CVV results, transaction ID, and authorization number. At this point you probably will want to store the order in the database and send the customer an email receipt for their order. In our example we send the user to a thank you page which probably should also include an order confirmation and printable receipt.

If the transaction is declined we really don't have to do much. We can add the notice to our $errors array and display it to the user when the page reloads.

If the transaction results in an error things can get dicey from a business perspective. In our example handling it with code is no different then a declined transaction except we are displaying a different message. Naturally an error at this point in the payment process to encounter an error is unexpected and definitely unwanted. You almost certainly should include some code to help you troubleshoot the error and attempt to prevent it from happening again. How you choose to do that is up to you.

Our Form Page So Far

Now that we have some more code written, let's see our how our page looks now:

At this point we have a fully functional checkout form that's usable and secure. But that doesn't mean we can't improve upon it. In the remaining posts in this series we are going to make incremental improvements to our form and payment process. We'll begin by preventing a page refresh from resubmitting the form again.

I love this tutorial, but I am confused a bit by the fact that you keep requiring the config.php file instead of the AuthorizeNet.php file that is in the SDK. I don't see any config.php file in the SDK.... Thanks!

1. Processing with ARB and CIM are substantially different in terms of transaction flow. For ARB, you could largely use this form for collecting customer information, and replace the usage of an AuthorizeNetAIM object with an AuthorizeNetARB object. However, this would require you to add additional information describing the payment schedule of the subscription.

The transaction flow for CIM is really too different to be applied with this example. When using CIM, transaction processing is separated into two distinct steps of collecting customer information, and charging the customer.

2. The database in this example is only used if you would like to store the transaction results within your own system. Strictly speaking, it is not necessary.

I've tried to adapt this AIM "test environment" setup to a live, secure setup but keep getting validation errors. The form seems to be working properly but I keep getting "There was an error with your submission", which is the text appearing in the

"if (count($errors))" div at the beginning of the html. I've removed the validation for structure of the expiration date and just want authorize.net to validate it's accuracy. Is that a problem? If I were to post my code, could you please check it and let me know? If so, I'll be happy to post it.