Authorize.Net’s Recurring Billing Solutions

Authorize.Net is a payment gateway that provides the infrastructure and security needed to safely and easily connect merchants to credit card processing networks. It offers an API for most situations, making it a popular choice among developers and merchants.

Setting Up Recurring Billing for Clients

One need that online businesses commonly have is the ability to setup recurring billing for their clients. Authorize.Net offers an API dedicated to this task called the Automated Recurring Billing (ARB) API. This API is a convenient solution that removes the need to store credit cards on your server.

To set up a subscription, you provide the API with the subscription start date, interval length, interval unit, total occurrences, amount of subscription, and the billing information. Once the subscription has been successfully set up, Authorize.Net handles the rest. Every time the recurring billing system processes a payment using a free credit card processing tool, it will send transaction information back to a URL you are able to specify in the Merchant Interface. You can then save the information in your database and use it to create a new order if needed. This functionality can save you time and money on development and security costs, but it does have a few limitations that I ran into.

Limitations to Authorize.Net’s Automated Recurring Billing API

The first limitation is that the initial transaction will not be processed until the following day. If you want to give your website visitor access to a service immediately, you must also use the Authorize.Net AIM (Advanced Integration Method) API. The Authorize.Net website says “AIM allows merchants to host their own secure payment form on a website” and is commonly used for processing one time transactions in real time. To combine these two, you would first process the user’s payment with the AIM API; once the transaction is successful, you would then perform the ARB setup setting the start date for the time which you want the second payment to be drafted.   There is another solution that Authorize.Net offers that will save you from having to work with two API’s, which I will discuss in a moment.

The second limitation involves the Silent Post functionality that sends back the transaction information when the transaction is finished processing. In the documentation, they make it clear that subscriptions are not updated in real time. If you have a subscription member whose transaction is declined, Authorize.Net does not cancel their subscription. To solve this problem, you might want to use the subscription cancellation method provided by the ARB API to cancel their subscription with Authorize.Net immediately after the transaction is declined. However, if you do this, the subscription will be cancelled, their update will go through, and it will be reactivated.  You will think that the subscription is cancelled on your end while the user will still be getting billed. This means you would need to schedule a Cron job to perform subscription cancellations at a later time. The ARB API would also not be able to provide you with the ability to update the amount of the subscription or update when the payment is drafted.

Using the Customer Information Manager API for Recurring Billing

It was these limitations that lead me to use their Customer Information Manager (CIM) API as a recurring billing solution. Authorize.Net’s website states the CIM “allows merchants to create customer profiles that are stored on Authorize.Net’s secure servers.” To process a transaction, you provide the API with the customers profile ID and payment profile ID, which tells Authorize which credit card information to use for the transaction. The credit card information is safely stored at Authorize.Net. This gives you complete control over payment timing and amounts, which is great for businesses that “process recurring transactions where the date and/or amount is different each month,” such as utility companies.

This new level of control does, however, give the developer a little more work to do. The merchant’s server will now be responsible for checking when subscriptions are due and processing the payment through the CIM using a Cron Job.  Other than that, this solution is very simple and more straight forward than using the ARB in some situations.  It saves you from the details and limitations of the Silent Post functionality and prevents you from having to use two API’s to accomplish one goal.

Implementing Recurring Billing Solutions Using Authorize.Net API

The best way to implement this solution is through the use of the software development kit (SDK) provided by Authorize.Net. The code below is intended to give you an overview of the process. It leaves out some very important steps, such as validation. The process to create the subscription is as follows:

1. Set your account codes and require the software development kit classes.

define("AUTHORIZENET_API_LOGIN_ID", $login_id);
define("AUTHORIZENET_TRANSACTION_KEY", $transaction_key);
require_once 'anet_php_sdk/AuthorizeNet.php';

2. Create a customer profile object.

$customerProfile = new AuthorizeNetCustomer;

3. Provide required information to the customer profile object.

 $customerProfile->description = $description;
 $customerProfile->merchantCustomerId = $merchant_customer_id;
 $customerProfile->email = $email;

4. Create a payment profile object.

$paymentProfile = new AuthorizeNetPaymentProfile;
$paymentProfile->customerType = "";
$paymentProfile->payment->creditCard->cardNumber = $card_number;
$paymentProfile->payment->creditCard->expirationDate = $expiration_date;
$paymentProfile->payment->creditCard->cardCode = $card_code;
$paymentProfile->billTo->firstName = $first_name;
$paymentProfile->billTo->lastName = $last_name;
$paymentProfile->billTo->phoneNumber = $phone_number;

5. Add the payment profile object to the customer profile object.

$customerProfile->paymentProfiles[] = $paymentProfile;

6. Submit the customer profile object to the API using the createCustomerProfile method.

 $request = new AuthorizeNetCIM;
 $response = $request->createCustomerProfile($customerProfile);

7. If successful, retrieve the customer profile ID and the payment profile ID and create a transaction object.

$customerProfileId = $response->getCustomerProfileId();
$paymentProfileId =  $response->getCustomerPaymentProfileIds();

8. Create the transaction object and supply it with required properties.

 $transaction = new AuthorizeNetTransaction;
 $transaction->amount = $amount;
 $transaction->customerProfileId = $customerProfileId;
 $transaction->customerPaymentProfileId = $paymentProfileId;
 $transaction->order->invoiceNumber = $order_id;
 $transaction->order->description = $description;

9. If you wish to send line item information with the transaction, add them now.

 foreach($items as $item){
 $lineItem              = new AuthorizeNetLineItem;
 $lineItem->itemId      = $item['id'];
 $lineItem->name        = $item['name'];
 $lineItem->description = $item['description'];
 $lineItem->quantity    = "1";
 $lineItem->unitPrice   = $item['price'];
 $lineItem->taxable     = "false";
 $transaction->lineItems[] = $lineItem;

10. Send the transaction object to the API using the createCustomerProfileTransaction method.

$t_request = new AuthorizeNetCIM;
$t_response = $t_request->createCustomerProfileTransaction("AuthCapture", $transaction);

11. Retrieve all of the pertinent response codes and information.

 $transactionResponse = $t_response->getTransactionResponse();
 $response_code = $transactionResponse->response_code;
 $response_subcode = $transactionResponse->response_subcode;
 $response_reason_code = $transactionResponse->response_reason_code;
 $response_reason_text = $transactionResponse->response_reason_text;
 $authorization_code = $transactionResponse->authorization_code;
 $avs_response = $transactionResponse->avs_response;
 $cavv_response = $transactionResponse->cavv_response;
 $transaction_id = $transactionResponse->transaction_id;

12. Use the transaction status (approved, declined, held, or other) to determine what to do next.


 } elseif ($transactionResponse->declined) {

 } elseif ($transactionResponse->held) {

 } else {


//ending the conditional from step 7

Choose a Recurring Billing API to Fit Your Needs

Whether you choose to use the CIM or the ARB API is entirely dependent on what you need to accomplish. The ARB API is nice in some situations where it isn’t necessary to bill the client immediately and there is no need for subscription amounts to fluctuate or dates to change. In situations where this could be necessary, I would recommend the CIM API. It will put the responsibility on the developer to process the payment via an automated script but it offers much more flexibility.

  1. Rob Gray says:

    Great article.

    I was looking for a solution similar to this: I really want a one shot ARB. The user pays for a product and a one time product upgrade at the same time to be billed when the upgrade is available. The first payment executes and the product ships. A month later when the new product comes out, we execute the ARB (one shot subscription) and based on the processing of the credit card again, send the upgrade or an email with a reason it wasn’t shipped (Credit Card declined). I really don’t want to store credit card information for the second transaction so I’m hoping a one shot ARB would work.

    What do you think?

    1. Rodger Yonley says:

      I think the ARB API might do the job for you. As long as the second payment amount is the same as the first. You would need to set the end date for right after the second payment.

  2. Joe says:

    I like your article, thanks for posting. One thing to note, between Step 1 and Step 2, I had to include the the following code needs make it work:

    $request = new AuthorizeNetCIM;

    1. Rodger Yonley says:

      Thanks for pointing that out. I’m glad it was helpful. I added the code into step 6 right before it is needed.

  3. Chris says:

    Helpful! Thanks for a very informative article.

    In the documentation I see an option for ‘hosted forms’. Do you recommend this ? What are the pro/cons of using hosted forms ?

    1. Rodger Yonley says:

      Sorry for the delay. I have not had a chance to look into the hosted forms yet.

  4. Tom Wiseman says:

    Very informative article Rodger. My client is looking for a recurring billing option as well, and with this article under my belt, I believe I now know which direction to go, which happens to be the CIM API.

    However, I’m wondering if it would be better to run a processing script via a CRON job or force the admin to log on to the site and run the script once per month. Are there any downsides to either of these that you are aware of?

    Will you be going over the CIM API in more detail in another BLOG post?

    Thanks again.

    1. Rodger Yonley says:

      Hi Tom,
      Thanks, I’m glad it was helpful! To answer your question, I would say it depends. If you could potentially have subscribers that are going to be billed monthly but at different times of the month then I would say go with a CRON job, otherwise your admin will have to log in every day.
      If you are processing all of the subscriptions once a month on the same day, then you could have your admin log on and run the script.

      The only downside to using a CRON in that scenario that I can think of, is if your server happens to go down the same time the CRON is scheduled to run. If your CRON runs daily its not that big of a problem because you can program it to catch any that have been missed. However, if its scheduled to run monthly then that could be a big problem.

      I had not planned on writing another about the CIM, but I guess its possible. What additional information do you think would be helpful?

  5. Randy says:

    Thanks for a very good article.

    Can you provide an example in Java?

    1. Rodger Yonley says:

      I cannot but also has a Java software development kit that will simplify the process.

Recent Blog Posts in realtime
Google announces the long anticipated Penguin 4.0 update today on the Webmaster Central Blog. Penguin Now Part of the Core Algorithm Penguin joins Panda as part of the core Google algorithm. Gone...
Over the past year, we’ve been evangelizing – sharing the good news about businesses taking control of online data. And we dedicated lots of resources to educating businesses and brands, teaching them...
Have you heard yet that we’re making some changes? One of our brands, Local Site Submit, is rebranding to Advice Local. Preparations for the transition are almost complete and our new, expanded...