A few weeks ago I had to interface to Authorize.net’s recurring billing API. This is a new API they released early this year. Prior to this, if you wanted a recurring billing subscription setup, you had to log into their site and set it up manually.

When I went to begin coding I searched high and low for an existing custom tag or cfc, but did not find any. So now that mine is complete, I’ve posted it on RiaForge.

ColdFusion CFC for Authorize.net recurring billing API

There is a README file in the zip archive that has fairly detailed instructions, but here are the basics:

There are three methods: createSubscription(), updateSubscription(), and cancelSubscription().

First you must init the cfc, passing in your loginname, transaction key, and the mode which should be either “live” or “test”. When in test mode, requests are posted to Authorize.net’s special test server.

<cfset PaymentGateway = CreateObject("component","AuthorizeNetRecurring").init(
	loginname = "AuthNetLoginName",
	transactionKey = "YourTransactionKey",
	mode = "live or test")>

<cfinvoke component="#PaymentGateway#" method="createSubscription" returnvariable="result">
	<cfinvokeargument name="startDate" value="#DateFormat(Now(),"yyyy-mm-dd")#">
	<cfinvokeargument name="customerEmail" value="#email#">
	etc....
</cfinvoke>

Each method returns a structure containing the following keys:

Key Description
error true or false. This is set internally based on what was returned from
Authorize.net. Use this to see if the transaction was processed or not.
messagecode Alpha-numeric code returned from Authorize.net.
messagetext Message text returned from Authorize.net. Usually fairly
descriptive. i.e. “The subscription cannot be found.”
resultcode Usually something like “ok” or “error”.
returnedXml The actual XML returned from Authorize.Net. Useful for debugging or
detailed logging.

You can download the Authorize.net recurring billing CFC from RIAForge.

And a “thanks” to my employer, CF WebTools for allowing me to give away this code.

27 Comments

  1. Ian says:

    Thanks for doing this. We have been using CF and Authorize for many years to do regular payments and credits.

    We just recently started using Authorize for subscriptions so this will be great for integration.

  2. rayrad says:

    FYI: If your web server runs on Windows, my company just released a library for Authorize.Net’s recurring billing. It was built in C# on the .NET platform and you can call it as a COM or .NET object (note: if you want to call it through .NET, I believe you need CF8). It supports both AIM and ARB and is fully certified by Authorize.net.

    We provide extensive documentation and code samples to aid users. It does cost $99, but that’s pretty cheap for the functionality it provides. It even has extras like line totaling, supporting MD5 Hash validation (for AIM payments), copying the billing to the shipping address, etc.

    You can get more information at https://www.itdevworks.com/faq.aspx and download a trial version or the documentation from our site.

    Dave Parker
    IT DevWorks, LLC
    http://www.itdevworks.com

  3. Brian says:

    Ryan, is it ok if we use this code in cfpayment with credits? http://cfpayment.riaforge.org.

  4. Ryan Stille says:

    Yes you sure can. I meant to contact that project and point them to my cfc, but I forgot. 🙂

  5. Werbeagentur says:

    Thanks ryan for the great informations and for the download-page.
    Many thanks from Germany, Werbeagentur

  6. Rob says:

    You rock! ‘Nuff said.

  7. Werbeagentur says:

    Again, a great Post!

  8. Typo3 Lambda Media says:

    cool! thanks! go on!!

  9. Larry says:

    I have the Authorize.net recurring billing API CFC working. One question.

    Does authorize.net post anything back to me when the monthy subscription goes thru?
    (Decline, expired, success, etc…)
    If so
    How do I capture this posted data so I can update my database?

  10. Mary Jo Sminkey says:

    @Larry – Just in case anyone else has this question, there is a setting in the AuthNet merchant area for a "silent post" URL, that is the page you would set up to receive the post back for each transaction.

  11. Jegan says:

    Hi Ryan

    Each method returns a structure containing the keys. Could you please tell how can we get these values.
    Please send me sample code at jegan@idynamics.com

  12. Ryan Stille says:

    Jegan, just reference the keys in the returned structure.  Like this:

    <cfset tmp = MyObj.createSubscription(….. all your data here)>

    <cfoutput>the new subscriber ID is #tmp.subscriptionId#, and the refID is #tmp.refId#</cfoutput>

    If you dump the return value you can see everything that gets returned:
    <cfset tmp = MyObj.createSubscription(….. all your data here)>
    <cfdump var=”#tmp#”>

  13. Chris says:

    Thanks for the hard work with the tag. I have tried to use it but don't see the information on the authorize.net servers after I run it. I made sure everything is Live and have connected with the same exact information to the servers when authorizing the card. Have you tested it and seen the information on authorize.net? I'm using hostmysite and they tell me that they aren't blocking anything. Thanks for any replies ahead of time!

  14. Ryan says:

    Chris, you aren't getting any error messages or anything?  What *are* you getting back from Authorize.net?  You should get at least a status code and maybe some other stuff.

  15. Chris says:

    Thanks for the reply. Correct, no error messages. I dont actually think that it is connecting to Authorize.net.

    I worked through some error messages already, now I just get blanks for variables and nothing updates on the authorize.net site. I am even saving the returnedXML.subscriptionId variable into a table and it enters in as an empty variable, but it does exist. Do you think that there is something that hostmysite could be blocking? Have you heard of anyone else having this problem? Thanks again!

  16. Ryan says:

    I doubt Host My Site is blocking anything.  You should dump out the raw return from Authorize.net and see if contains anything.  You are probably right, the connection is probably failing.

  17. Chris says:

    What is the proper variable name for these? ARBCreateSubscriptionRequest.? or returnedxml.? or call #cfhttp.fileContent#? Thanks again, I really appreciate it.

  18. Ryan says:

    Chris I'm not sure what you are asking.  If you want to dump out whats coming back from the http request to Authorize.net, dump cfhttp on line 425.

    <cfdump var="#cfhttp#" />

  19. Chris says:

    Ok, so they weren't actually blocking anything. What happened was there was a cftry in there (I didn't write the code and missed it) and errors weren't showing up.

    It is updating on the authorize.net site!

    One final question! What would I use to grab the subscriptionid? returnedxml.subscriptionid and retStruct.subscriptionid and result.subscriptionid don't work for me!

    I tried your <cfset tmp = MyObj.createSubscription(….. all your data here)>
    but wrote it as <cfset tmp = MyObj.createSubscription> and i got the error "CREATESUBSCRIPTION is undefined in MYOBJ."

    Thanks sooooooo much 🙂

  20. Ryan says:

    Chris, your code doesn't look right, you need to be passing data into the createSubscription() method like

    <cfset myObj.createSubscription(startDate = Form.startDate, customerEmail = Form.email, etc…) />

  21. Chris says:

    I am passing the form variables into the cfc like you show here:

    "
    <cfset PaymentGateway = CreateObject("component","AuthorizeNetRecurring").init(
        loginname = "AuthNetLoginName",
        transactionKey = "YourTransactionKey",
        mode = "live or test")>

    <cfinvoke component="#PaymentGateway#" method="createSubscription" returnvariable="result">
        <cfinvokeargument name="startDate" value="#DateFormat(Now(),"yyyy-mm-dd")#">
        <cfinvokeargument name="customerEmail" value="#email#">
        etc….
    </cfinvoke>  
    "

    Are you just passing variables into the cfc differently? Or is this stuff on the page after the cfc has inititated?

    Thanks!

  22. Chris says:

    Yo, I am pretty sure that I figured out the problem. I'll update you later on the it if it ends up working. Take it easy man.

  23. Abe Stem says:

    Hello Ryan,

    I am gald to have found your programming as it is definitely helping a new CF programmer like me with the project i am working on. I do have a question for you though.

    Is there a way to pass the invoice ID, Amount, and Customer ID through the returnedXML? I would like this information to carry through to an additional page that uses this data to query a database, but cannot see a way to extract those variables from the returned XML… Any thoughts?

    Here is what I have so far, but sure how to get those variables to carry through Authorize:

    Here –>

    Here –>

    Thank you for your time. I know that this is an older project of yours, but I would definitely appreciate any help you can give.

    Abe Stem

  24. Abe Stem says:

    I can email you my code if it would help. i tried to paste it above without success.

  25. Robin says:

    Hi Ryan,

    I’m not clear on how to output the returned keys (results).

    I’m not clear on the variable scope name to be used (i.e., result, returnedXML, or PaymentGateway).

    Using the following:

    Would the returned variables be the following:

    Result Code: #result.resultcode#
    Result Message: #result.message#
    Result Message Code: #result.messagecode#
    Result Message Text: #result.messagetext#
    Result Returned XML: #result.returnedXml#

    Thank you!

  26. Robin says:

    There was another question posted asking about specific variables (i.e., customer id) being submitted and returned with the silent post so that the database can be updated. Is there a way to do this?

    Thank You.

  27. Phil L. says:

    I found a snippet that just gives you the code, might help better understand the CIM integration:
    http://www.sitekickr.com/coda/coldfusion/authorize-net-createcustomerprofilerequest.html

Leave a Reply

You must be logged in to post a comment.