Tax Provider Integration : Avalara

For general questions and discussions specific to the AbleCommerce 7.0 Asp.Net product.
jrobgood
Lieutenant (LT)
Lieutenant (LT)
Posts: 56
Joined: Wed Nov 14, 2007 2:27 am

Tax Provider Integration : Avalara

Post by jrobgood » Tue Nov 27, 2007 3:16 pm

We also would like to integrate with a third-party tax provider. If the AC dev team can point us in the right direction in the source code that would be excellent.

Thanks!
Last edited by jrobgood on Tue Jul 22, 2008 10:10 am, edited 1 time in total.

User avatar
Logan Rhodehamel
Developer
Developer
Posts: 4116
Joined: Wed Dec 10, 2003 5:26 pm

Post by Logan Rhodehamel » Tue Nov 27, 2007 4:59 pm

Here's a brief overview.

1) Create a class that inherits from CommerceBuilder.Taxes.Providers.TaxProviderBase. This is an abstract class that forms the base of the provider.

2) Implement the required members of the base class. Visual Studio can create method stubs for you.

Calculate This method takes a basket object as input. From there, you can get the billing and shipping addresses as well as line items. What you need to do is determine the tax to charge - then add line items to the basket (BasketItem class) for each line item. The method returns the total tax that was added to the basket.

Commit This method takes an order object as input and commits any taxes that were charged. This may not be required by your integration. Some providers may need to know what taxes were actually charged in order to produce accurate reports on tax liability.

Cancel This method takes a basket object as input. WHen called, it cancels any tax charges currently in progress. Your integration may or may not require this. Some providers may use this to reset the calculations for a particular order in progress.

3) Once your class is implemented and compiled, you need to register it with the store. Since we did not include our tax providers, there is no web based interface to do this. The simplest choice, if available, is to add a record to the database in the ac_TaxGateways table:

TaxGatewayId = auto number ID

StoreId = ID of your store, probably 1

Name = Name of your gateway

ClassId = .NET Class ID used to create an instance of your gateway. For examples, you can look in ac_PaymentGateways (assuming you have a gateway configured).

ConfigData = If you need to provide configuration data it can be stored here in a url encoded string. For example, key1=value&key2=value. The values in the field will be accessible in your integration by using the GetConfigData() method. If you are producing an integration only for yourselves, you don't need to worry about this as any configuration should be hard coded instead.

Hope this helps. Feel free to ask questions... We can answer until we have a formal doc and example. (We only have CCH integration completed and I can't release source for that as is...)
Cheers,
Logan
Image.com

If I do not respond to an unsolicited private message, it's not because I'm ignoring you. It's because the answer to your question is valuable to others. Try the new topic button.

brian.sutherland
Ensign (ENS)
Ensign (ENS)
Posts: 14
Joined: Wed Dec 05, 2007 12:41 am

Post by brian.sutherland » Wed Dec 19, 2007 2:04 am

Hey Logan, thanks for the quick response on the original message.

We've finally gotten to the point where we are about to roll this sucker out, and I was able to implement some of what you explained, but I have a couple of questions still.

Our tax provider has some carry over from Calculate to Commit (it's basically the OrderID). For Calculate, since it takes a basket object, I was using basketId, and for Commit, since it takes an order, I was using OrderId. Is this correct? I unfortunately don't have a debugger on our server where we have AC installed, so I can't look at it myself on here, and I was unsuccessful in finding a data dictionary showing any coorelation between baskets and orders.

When looking at our web server, I cracked open SQLServer management studio, opened up SQLExpress, but I didn't see any DB's installed. Is there a default name that I should be seeing in here? I could just be tired and not seeing things straight here, but the site is working, so I know we have data in there.

Thanks in advance, and I'm sure I'll have another question before this is all said and done.

User avatar
Logan Rhodehamel
Developer
Developer
Posts: 4116
Joined: Wed Dec 10, 2003 5:26 pm

Post by Logan Rhodehamel » Wed Dec 19, 2007 10:03 am

brian.sutherland wrote:Our tax provider has some carry over from Calculate to Commit (it's basically the OrderID). For Calculate, since it takes a basket object, I was using basketId, and for Commit, since it takes an order, I was using OrderId. Is this correct? I unfortunately don't have a debugger on our server where we have AC installed, so I can't look at it myself on here, and I was unsuccessful in finding a data dictionary showing any coorelation between baskets and orders.
Let me think about that one. You need to correlate the basket to the final order, in order to commit the transaction. Is that correct?
brian.sutherland wrote:When looking at our web server, I cracked open SQLServer management studio, opened up SQLExpress, but I didn't see any DB's installed. Is there a default name that I should be seeing in here? I could just be tired and not seeing things straight here, but the site is working, so I know we have data in there.
I am guessing you installed using the included SQL express database? If so this is called a 'user instance' and the database is not linked up to studio in the traditional way. There are a lot of examples online of how to link up to your data:

http://blogs.msdn.com/sqlexpress/archiv ... tudio.aspx

There is also a way to attach the database to SQL Server so that it will be treated like a traditional database.
Cheers,
Logan
Image.com

If I do not respond to an unsolicited private message, it's not because I'm ignoring you. It's because the answer to your question is valuable to others. Try the new topic button.

brian.sutherland
Ensign (ENS)
Ensign (ENS)
Posts: 14
Joined: Wed Dec 05, 2007 12:41 am

Post by brian.sutherland » Thu Dec 20, 2007 1:07 am

For the first part, yes, I think you have it. When you calculate, you need to pass in an ID number, that ends up saving that record to their server. When you commit, you need that same number in order to then "finalize" that record that was saved off in the calculate call. Likewise, with cancel, you pass in that same number too. I didn't see anything that stood out to me that I could use in both the basket object and in the order object. With your hesitation there, unfortunately maybe I stumbled across something that's gonna cause us a problem.

Thanks for the msdn article. I'll dig into this next, and try to start adding those other records that are needed to get this tax class integrated into our AC site.


You know, I just thought of something that may work...
I could use the calculate with different parameters on their side, which actually doesn't save a record, just gives back the value. Then, inside of commit, I could call calculate with the value that will save the record, then immediately call commit after, which would prevent us from having to have that value floating across both objects. Unless you can see something else that would work, I think this will be the way we have to end up going with it.

User avatar
Logan Rhodehamel
Developer
Developer
Posts: 4116
Joined: Wed Dec 10, 2003 5:26 pm

Post by Logan Rhodehamel » Thu Dec 20, 2007 9:08 am

brian.sutherland wrote:With your hesitation there, unfortunately maybe I stumbled across something that's gonna cause us a problem.
But we may have the same concern for our own integrations. We made a change to our database architecture - previously there was something in place to deal with this.

I will check this out today.
Cheers,
Logan
Image.com

If I do not respond to an unsolicited private message, it's not because I'm ignoring you. It's because the answer to your question is valuable to others. Try the new topic button.

brian.sutherland
Ensign (ENS)
Ensign (ENS)
Posts: 14
Joined: Wed Dec 05, 2007 12:41 am

Post by brian.sutherland » Mon Dec 24, 2007 2:45 am

Alright, I neede a little more hand holding here, because the user instance doesn't seem to want to play nicely with me...

I downloaded SSEUtil, which, as I understand it, will allow me to change the heart_beat state of the instnaces to alive rather than dead.

When I log into MY account on the server, I see 2 lines... (names have been changed to protect the innocent)
1. NT AUTHORITY\NETWORK SERVICE \\.\pipe\blah1\tsql\query dead
2. MYDOMAIN\myusername \\.\pipe\blah2\tsql\query alive

As you can see, using SSEUtil, I was able to get mine to alive. However, when I look through the databases, I only see master, model (read only), msdb, and tempdb after I connect to my pipe in the object explorer.

So I was lucky enough to have the admin password shared with me from my customer, (which is where they installed the AC package from). I ran it, and this time, I see 3 entries...

1. NT AUTHORITY\NETWORK SERVICE \\.\pipe\blah1\tsql\query dead
2. MYDOMAIN\adminaccount \\.\pipe\blah3\tsql\query alive
3. MYDOMAIN\myusername \\.\pipe\blah2\tsql\query alive

Again, I was able to use SSEUtil to activate the adminaccount pipe here, but I looking through that, again, I'm coming up with nothing. So I'm now pretty sure NT AUTHORITY is the sucker I need to get started, but I havent' been able to get that to work, and don't want to waste more time than I already have this weekend and not ask for some help here.

I tried passing in the username in sseutil, with the following command
sseutil -child 'NT AUTHORITY\NETWORK SERVICE', and with the -user flag as well, but I get nothing.

Any hand holding you can provide on this would be extremly helpful. The deadline has pretty much passed, and this is pretty much the last piece I need to get in there, so if there are any other docs or things I need to know about, I'm all ears. Thanks in advance.

~Brian

brian.sutherland
Ensign (ENS)
Ensign (ENS)
Posts: 14
Joined: Wed Dec 05, 2007 12:41 am

Post by brian.sutherland » Mon Dec 31, 2007 1:28 pm

Just checking in to make sure I didn't slip through the cracks. I still haven't had any success adding those values into the db.

User avatar
Logan Rhodehamel
Developer
Developer
Posts: 4116
Joined: Wed Dec 10, 2003 5:26 pm

Post by Logan Rhodehamel » Wed Jan 02, 2008 3:46 pm

I have never had to use SSEUtil to turn the user instance on. Instead, just make a web request to the site that is using the database. The user instance will then be turned on.

Then run this query against the master database on the server:

SELECT owning_principal_name, instance_pipe_name, heart_beat FROM sys.dm_os_child_instances

Find the user instance that is showing as "alive" and connect to that one from object explorer.
Cheers,
Logan
Image.com

If I do not respond to an unsolicited private message, it's not because I'm ignoring you. It's because the answer to your question is valuable to others. Try the new topic button.

brian.sutherland
Ensign (ENS)
Ensign (ENS)
Posts: 14
Joined: Wed Dec 05, 2007 12:41 am

Post by brian.sutherland » Thu Jan 03, 2008 12:52 am

OK, good deal. I was able to get it running doing your method rather than trying to fire it up with SSEUtil.

Now, just to be clear on the values to put in...

TaxGatewayId: auto numbered, I do nothing for it.

StoreId: 1, since that is the store value

Name: something like AvalaraGateway

ClassId: I saw that the PaymentGateway was named CommerceBuilder.Payments.Providers.GiftCertificatePaymentProvider, CommerceBuilder

I have a namespace of AvalaraTaxProvider
and the class declaration of public class MyTaxClass : CommerceBuilder.Taxes.Providers.TaxProviderBase

The output is a dll called AvalaraTaxProvider.dll

I'm a little confused as to what I should make the ClassId

ConfigData: I have none, so it should be good.

Looks like we're in the home stretch here, so if there is anything else that I didn't think of, please let me know.

User avatar
Logan Rhodehamel
Developer
Developer
Posts: 4116
Joined: Wed Dec 10, 2003 5:26 pm

Post by Logan Rhodehamel » Thu Jan 03, 2008 10:26 am

I'm a little confused as to what I should make the ClassId
I think something like

AvalaraTaxProvider.MyTaxClass, AvalaraTaxProvider
Cheers,
Logan
Image.com

If I do not respond to an unsolicited private message, it's not because I'm ignoring you. It's because the answer to your question is valuable to others. Try the new topic button.

brian.sutherland
Ensign (ENS)
Ensign (ENS)
Posts: 14
Joined: Wed Dec 05, 2007 12:41 am

Post by brian.sutherland » Sun Jan 06, 2008 3:30 pm

Logan, you've been a life saver, thanks a bunch.

It's now in there, and being called, but it's not updating the order with the tax.

The tax provider is getting the correct values in there, but it's not reflected in the checkout process. I made sure the product was set to taxable, but I don't see a way to have that point to a custom tax provider. I have the rule and tax code set, but it's now just adding the value I put in tax rule that I created.

So close to having this wrapped up. Thanks a bunch for all the help you've provided so far.

User avatar
Logan Rhodehamel
Developer
Developer
Posts: 4116
Joined: Wed Dec 10, 2003 5:26 pm

Post by Logan Rhodehamel » Tue Jan 08, 2008 9:11 am

Tax calculators are a bit different from shipping and payment in the sense that they are expected to add items to the basket. I didn't realize this - I haven't worked on tax gateways in a long time.

Within our CertiTAX integration, calls to the "Calculate" method go something like this:

send CertiTAX request
receive CertiTAX response
check response for taxes
add tax line items to basket
return total tax added to basket

The last step uses this code:

Code: Select all

        private void CreateTaxLineItem(Basket basket, int shipmentId, string authorityName, string certiTaxTransactionId, LSDecimal amount)
        {
            BasketItem taxLineItem = new BasketItem();
            taxLineItem.BasketId = basket.BasketId;
            taxLineItem.OrderItemType = OrderItemType.Tax;
            taxLineItem.BasketShipmentId = shipmentId;
            taxLineItem.Name = authorityName;
            taxLineItem.Sku = string.Format("CT:" + certiTaxTransactionId);
            taxLineItem.Price = amount;
            taxLineItem.Quantity = 1;
            taxLineItem.Save();
            basket.Items.Add(taxLineItem);
        }
The parameter "shipmentId" may or may not apply to your integration. In the case of CertiTAX, some taxes are dependent on either the shipping origin or destination address. So we may associate a tax to a particular shipment. Setting this to 0 means the tax applies to the order as a whole and is not dependent on one of these addresses.

The authority name is what CertiTAX calls the tax jurisdiction. Like it might return "Clark County" or something like that.

You can modify this code as needed. I think this is the piece you are missing - instead you are thinking we will add tax line items based on the value you return.

Also, you should not need to set a tax rule for this to work. Tax rules are only used by the built in AbleCommerce tax engine.
Cheers,
Logan
Image.com

If I do not respond to an unsolicited private message, it's not because I'm ignoring you. It's because the answer to your question is valuable to others. Try the new topic button.

User avatar
Logan Rhodehamel
Developer
Developer
Posts: 4116
Joined: Wed Dec 10, 2003 5:26 pm

Post by Logan Rhodehamel » Tue Jan 08, 2008 9:14 am

Also, notice that we use the SKU field to track the CertiTAX transaction ID. We use this during hte "Commit" phase, by searching through the order items to locate any Tax item types having a SKU that begins with "CT:". I don't know if this matters to you, but it's a field that can be used to store a little piece of arbitrary info.
Cheers,
Logan
Image.com

If I do not respond to an unsolicited private message, it's not because I'm ignoring you. It's because the answer to your question is valuable to others. Try the new topic button.

brian.sutherland
Ensign (ENS)
Ensign (ENS)
Posts: 14
Joined: Wed Dec 05, 2007 12:41 am

Post by brian.sutherland » Tue Jan 08, 2008 10:20 am

OK, I think I got it...

So in my call to calculate, I'm going to add the value that is returned in their response, to the basket object that was passed in to my Calculate method.

I'll give that a shot tonight and let you know how it goes. Thanks a bunch.

brian.sutherland
Ensign (ENS)
Ensign (ENS)
Posts: 14
Joined: Wed Dec 05, 2007 12:41 am

Post by brian.sutherland » Sun Jan 13, 2008 2:40 am

Everything is hooked up now, and looking to be running good, except for the fact that Calculate is called when I add an item to my basket when the AddToBasketButton_Click is launched. (it could be elsewhere, but this is the event that fires off). Because I don't yet have the shipping address, my webservice cant calculate the tax properly, and I get an exception. I've stubbed it out for now, but I see this is going to be a problem. What I am doing now in the meantime is to just call the calculate code when the commit is called, which then gives me back the correct tax, I throw it into the order.Items, and it's working good that way. However, I don't have a way to show the user what the total price is before they actually hit the purchase button, so that's not ideal.

Any ideas on this? I'm hoping I just missed where the call was being made.

brian.sutherland
Ensign (ENS)
Ensign (ENS)
Posts: 14
Joined: Wed Dec 05, 2007 12:41 am

Post by brian.sutherland » Tue Jan 15, 2008 9:09 pm

I ended up catching the exception that was being thrown, and returning 0 for those calls.

After the address is put in, it seems the calculate call is called again, which since we then have the address, it's able to calculate it.

So I have it working, but had to add a few extra checks in there (I'm actually checking the SKU for the string "TAX" becasue that's what I was putting in there)

If this seems way off, let me know and I'll do it properly if there is something I'm missing here.

Thanks a bunch.

mianders
Ensign (ENS)
Ensign (ENS)
Posts: 15
Joined: Wed Feb 27, 2008 8:37 am
Contact:

Has anyone completed this integration

Post by mianders » Mon Mar 10, 2008 9:21 am

If so, then would you be willing to share the code. We are trying to perform that same integration.

jrobgood
Lieutenant (LT)
Lieutenant (LT)
Posts: 56
Joined: Wed Nov 14, 2007 2:27 am

Avalara Provider service

Post by jrobgood » Sun Mar 16, 2008 11:41 pm

OK, here's the code that Brian built for us, sharing as promised. No warranty of usability, data protection, liability, your mileage may vary, etc etc.

http://files.brand-up.com/get/AvalaraTaxProvider.zip
Link updated 7/20/2008
Last edited by jrobgood on Sun Jul 20, 2008 2:34 pm, edited 1 time in total.

mianders
Ensign (ENS)
Ensign (ENS)
Posts: 15
Joined: Wed Feb 27, 2008 8:37 am
Contact:

Re: Avalara intergration

Post by mianders » Fri May 09, 2008 5:30 pm

I cannot get the download links to work. Can you repost the files. I need to get sales tax running on my site as soon as possible.

ajseltzer
Ensign (ENS)
Ensign (ENS)
Posts: 2
Joined: Wed Jul 09, 2008 12:46 am

Re: Avalara intergration

Post by ajseltzer » Mon Jul 14, 2008 12:32 pm

Does anyone have access to the tester application? I cannot seem to download it.

trozzi
Lieutenant Commander (LCDR)
Lieutenant Commander (LCDR)
Posts: 104
Joined: Wed Oct 05, 2005 4:44 pm
Contact:

Re: Avalara intergration

Post by trozzi » Mon Jul 21, 2008 8:01 pm

I see the solution for the classId of "AvalaraTaxProvider.MyTaxClass, AvalaraTaxProvider".

Does the second AvalaraTaxProvider reference the namespace or the name of the .dll?

Thanks
Thomas

keats76
Commander (CMDR)
Commander (CMDR)
Posts: 117
Joined: Sat Dec 15, 2007 4:45 pm

Re: Avalara intergration

Post by keats76 » Tue Jul 22, 2008 7:19 am

Anyone have an idea of the annual licensing costs for Alavara and a small order volume installation of AC7 (<1000 /yr)?

Their site doesn't make it very clear. Also, when they say "per transaction" does that mean per actual sale, or per web service call for tax lookup?

Thanks!
Mike

jrobgood
Lieutenant (LT)
Lieutenant (LT)
Posts: 56
Joined: Wed Nov 14, 2007 2:27 am

Re: Avalara intergration

Post by jrobgood » Tue Jul 22, 2008 10:03 am

keats76 wrote:Anyone have an idea of the annual licensing costs for Alavara and a small order volume installation of AC7 (<1000 /yr)?

Their site doesn't make it very clear. Also, when they say "per transaction" does that mean per actual sale, or per web service call for tax lookup?

Thanks!
Mike
Avalara. It costs us about $1800 a year including filing taxes in a few states.

Transactions aren't booked into their system until it's completed on the AC7 cart, so it keeps an accurate log of tax liability for us.

-Rob.

brian.sutherland
Ensign (ENS)
Ensign (ENS)
Posts: 14
Joined: Wed Dec 05, 2007 12:41 am

Re: Avalara integration

Post by brian.sutherland » Thu Jul 24, 2008 2:16 am

After being away from this project for a while, I'm now back to try to help out a little. We've updated to the latest version of AbleCommerce, changed around our Avalara to be a class within the appcode folder rather than a seperate dll, to try to clean things up, but are now having some problems.

We get a NullReferenceException when basket.Recalculate() is called. I'm thinking we have something wrong in the registration of our class. It seems a few of the things have changed since I last saw them, and I need one more (hopefully) little push to get it rolling again.
Before, we were told...
TaxGatewayId = auto number ID
StoreId = ID of your store, probably 1
Name = Name of your gateway
ClassId = .NET Class ID used to create an instance of your gateway. For examples, you can look in ac_PaymentGateways (assuming you have a gateway configured).

I had created my own gateway before (AvalaraGateway), but now we are using Authorize.Net. Should I put in "Authorize.Net" for that value?

Our classID is now namespace.classname, so it's AvalaraTaxProvider.MyTaxClass. (this is in the appcode folder, using the TaxProvider.cs file)

Is there anything obvious I'm missing here? This feels like the lamest post ever, getting everyting done already, then having to circle back and ask some of the things again, but there seem to have been a number of chagnes since I last used it (it was in beta then, too), and I'm hoping there are some easy lines that will connect this thing back up both on the server and in my head again.

Thanks a bunch.

Post Reply