Rails and QuickBooks Integration - Part 4

Make sure you read part 1, part 2, and part 3 of this series if you haven’t already.

The Full Monty

In part 3 we tested the simple case of having no pending requests for the QuickBooks Web Connector (QBWC) which results in the exercise of only authenticate() and closeConnection(). But I know you were craving more…

To test the full send/receive stack we need to return a qbXML request from sendRequestXML(). QBWC will forward this qbXML request to QuickBooks and then return the result by calling our receiveResponseXML(). Let’s put together a sample request that returns all customer names.


class QuickbooksController < ApplicationController
  ssl_required :api, :qwc
  before_filter :set_soap_header, :except => :qwc

  def authenticate(username, password)
    ['85B41BEE-5CD9-427a-A61B-83964F1EB426', '']


  def sendRequestXML(ticket, hpc_response, company_file_name, country, qbxml_major_version, qbxml_minor_version)
    qbxml = <<-REQUEST
    <?xml version="1.0"?>
    <?qbxml version="4.0"?>
      <QBXMLMsgsRq onError="stopOnError">
        <CustomerQueryRq requestID="1">

  def receiveResponseXML(ticket, response, hresult, message)
    xml = REXML::Document.new(response)
    statusCode = REXML::XPath.first(xml, '//CustomerQueryRs[1]' ).attributes['statusCode']

    if statusCode == 0.to_s
      REXML::XPath.each(xml, '//FullName' ){ |e| logger.info "Customer: #{e.text}" }
      logger.info "Unable to receive the customer list...status code: #{statusCode}"



  def closeConnection(ticket)


    def set_soap_header
      if request.env['HTTP_SOAPACTION'].blank? || request.env['HTTP_SOAPACTION'] == %Q("")
        xml = REXML::Document.new(request.raw_post)
        element = REXML::XPath.first(xml, '/soap:Envelope/soap:Body/*')
        request.env['HTTP_SOAPACTION'] = element.name if element
    def clean_qbxml(qbxml)
      qbxml.gsub(/>\n\s+</, '><').strip

First, authenticate returns an empty string. This instructs QBWC to use the current company file. You can check the current company file name by checking the strHCPResponse xml passed to the sendRequestXML() call.

Secondly, we issue a simple qbXML request to QBWC. I like to use here documents («- notation) to keep xml readable. But QBWC will barf on the newlines and whitespace so we have to throw in a quick helper (clean_qbxml) to do our dirty work.

Finally, our receiveResponseXML() simply logs the customer names and returns 100 which signals that we have no future pending requests. QWBC then calls closeConnection() and exits.

Next steps

This has been a wild ride but now we’re home free. The basics of the QBWC communication cycle are understood. QBWC 1.5 should come out soon to improve on the rough edges. Now all that remains is to sit down and determine exactly how your app should sync with QuickBooks. That’s what I’m doing now. If I discover any helpful tidbits as I work through my integration I’ll be sure to post another article. Otherwise I hope these posts were helpful and I wish you luck in your integration quest!

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.