Rails and QuickBooks Integration - Part 2

Make sure you read part 1 of this series if you haven’t already.

Let’s cut to the quick. We have a Rails web app that must integrate with QuickBooks.

We know from reading part 1 that we must become experts at the QuickBooks Web Connector (QBWC). So the first thing we’re going to do is read the QuickBooks Web Connector Programmer’s Guide located in the SDK.

Good. Now read it again.

QBWC Install

Ok… done with the reading. First let’s tackle the initial customer setup. The customer obviously needs to have the QBWC installed. This is easy enough - point them to marketplace.intuit.com/webconnector. Instruct then to download and install. Simple enough…

The QWC File

Next, the customer must subscribe to our service. By subscribe we mean our app provides a QWC file to QBWC containing the customer specific connection data.

Sample QWC file

<?xml version="1.0"?>
<QBWCXML>
   <AppName>WCWebService1</AppName>
   <AppID></AppID>
   <AppURL>http://localhost/WCWebService/WCWebService.asmx</AppURL>
   <AppDescription>A short description for WCWebService1</AppDescription>
   <AppSupport>http://developer.intuit.com</AppSupport>
   <UserName>iqbal1</UserName>
   <OwnerID>{57F3B9B1-86F1-4fcc-B1EE-566DE1813D20}</OwnerID>
   <FileID>{90A44FB5-33D9-4815-AC85-BC87A7E7D1EB}</FileID>
   <QBType>QBFS</QBType>
   <Style>DocWrapped</Style>
   <Scheduler>
      <RunEveryNMinutes>5</RunEveryNMinutes>
   </Scheduler>
</QBWCXML>

While most of these elements are self-explanatory, some might need explanation. Check with the SDK for the exact definition and use of these elements.

So let’s create a controller that can handle serving up this file. We’ll use the generate command and then remove the unwanted view directory.

$ ./script/generate controller Quickbooks
  exists  app/controllers/
  exists  app/helpers/
  create  app/views/quickbooks
  exists  test/functional/
  create  app/controllers/quickbooks_controller.rb
  create  test/functional/quickbooks_controller_test.rb
  create  app/helpers/quickbooks_helper.rb
$ rm -rf app/views/quickbooks 

And let’s quickly add a named route:

routes.rb

map.quickbooks 'apis/quickbooks/:action', :controller => 'quickbooks'

We can now add an action to our Quickbooks controller to generate this QWC file:

quickbooks_controller.rb

class QuickbooksController < ApplicationController

  def qwc
    qwc = <<QWC
<QBWCXML>
   <AppName>My App</AppName>
   <AppID></AppID>
   <AppURL>#{quickbooks_url(:protocol => 'https://', :action => 'api')}</AppURL>
   <AppDescription>My app rocks!</AppDescription>
   <AppSupport>#{Your_App::QB_SUPPORT_SITE_URL}</AppSupport>
   <UserName>foo</UserName>
   <OwnerID>#{Your_App::QB_OWNER_ID}</OwnerID>
   <FileID>{90A44FB5-33D9-4815-AC85-BC87A7E7D1EB}</FileID>
   <QBType>QBFS</QBType>
   <Style>RPC</Style>
   <Scheduler>
      <RunEveryNMinutes>5</RunEveryNMinutes>
   </Scheduler>
</QBWCXML>
QWC
    send_data qwc, :filename => 'my_app.qwc'
  end

end

Notice that we used the named route and specified the HTTPS protocol. This is because the QBWC will only process requests over SSL. This is a good thing as we will be dealing with customer’s financial information. I highly recommend the SSL Requirements plugin to handle ssl requirements in your app.

The named route also specified the ‘api’ action. The simple reason is that later we will use this same controller along with an ActionWebService (AWS) api specification to handle web service requests from the QBWC. AWS will use the ‘api’ action as an endpoint and then delegate to the appropriate action. Don’t worry so much about this right now. It will all be clear soon…

I’m also specifying some constants which can be placed in an environment file.

environment.rb

module Your_App
  QB_SUPPORT_SITE_URL = 'http://qb_support.my_app.com'
  QB_OWNER_ID         = '{57F3B9B1-86F1-4fcc-B1EE-566DE1813D20}'
end

QWC Tests

Add some tests which will likely need to be customized for your app depending on authentication and authorization requirements. Here are some samples:

quickbooks_controller_test.rb

...
class QuickbooksControllerTest < Test::Unit::TestCase
  fixtures :accounts, :users

  ...

  def test_qwc
    login_as :sparky
    get :qwc
    assert_response :success
    assert_template nil
    assert_match %r{https://sparky.localhost.com/apis/quickbooks/api}, @response.body
  end

  def test_qwc_not_logged_in
    get :qwc
    assert_redirected_to login_url
  end
  
end

Initial Quickbooks test setup

Ok time to get ready for our first data exchange. But first let’s make sure we are properly setup:

  1. Install Quickbooks (I used QuickBooks 2006 Premier Edition).
  2. Open Quickbooks and open a company file (I used the sample company file).
  3. Check in new code and deploy.
  4. Download the QWC file and save the file to the desktop.
  5. Tail your production.log on your remote server to see the communication that will take place (Ex: tail -f shared/log/production.log).
  6. Double-click on the QWC file to load it into the QBWC.

You should see that a GET request is issued to your app’s ‘api’ action and then an ActionController::UnknownAction error is thrown. The QBWC will pop up an error box. Click ‘OK’ and then an ‘Authorize New Web Service’ window should appear. Take note that you need to have Quickbooks open and be logged into a company file (the sample company is ok). Click ‘OK’. Another box will pop up asking exactly which data the web service should be able to interact with. Respond according to your needs.

You should now have the QBWC open with your app listed. First, uncheck the Auto-run box. Next, type a password in the password box (this password will be passed along with the username specified in the QWC file with every authentication request).

Now when you want to test communication between the QBWC and your app you can check the box to the left of your app listing and then click the ‘Update Selected’ button. If you try this now you should see your app respond with the same ActionController::UnknownAction error and the QBWC will show a message of ‘Authentication failed’. This is because our controller does not yet respond to the SOAP messages being passed from the QBWC.

What lies ahead…

I want to keep these posts bite-sized for easy consumption. So that will force me to wrap up this installment.

Stay tuned for the next article where we’ll dive into the heart of the integration and discover that both pleasure and pain await us with ActionWebService…

Comment or question via
FYI: This post was migrated over from another blogging engine. If you encounter any issues please let me know on . Thanks.