Skip to content

Instantly share code, notes, and snippets.

@ruckus
Last active January 25, 2020 14:27
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ruckus/e62d4200deef7e376294 to your computer and use it in GitHub Desktop.
Save ruckus/e62d4200deef7e376294 to your computer and use it in GitHub Desktop.
Example controller for a SOAP Endpoint for Quickbooks Web Connector (QWC)
<?xml version="1.0"?>
<QBWCXML>
<AppName>Your App</AppName>
<AppID></AppID>
<AppURL>https://yourdomain.com/qbxml/action</AppURL>
<AppDescription>A short description of your app</AppDescription>
<AppSupport>http://yourdomain.com</AppSupport>
<UserName>acme</UserName>
<!-- specific to your app as a whole: so generate it once -->
<OwnerID>{57F3B9B1-86F1-4fcc-B1EE-566DE1813D20}</OwnerID>
<!-- specific to customer: so generate it once, for each customer -->
<FileID>{90A44FB5-33D9-4815-AC85-BC87A7E7D1EB}</FileID>
<QBType>QBFS</QBType>
<Scheduler>
<RunEveryNMinutes>30</RunEveryNMinutes>
</Scheduler>
</QBWCXML>
# QBD Integration
gem "wash_out", "0.9.0"
gem 'qbxml', '~> 0.1.5'
class StringArray < WashOut::Type
map "tns:string" => [:string]
end
class QBXMLController < ActionController::Base
include WashOut::SOAP
soap_service namespace: 'http://developer.intuit.com/'
skip_before_filter :_parse_soap_parameters, :_authenticate_wsse, :_map_soap_parameters, :only => :qwc
soap_action 'serverVersion', :to => :server_version,
:return => {'tns:serverVersionResult' => :string},
:response_tag => 'tns:serverVersionResponse'
soap_action 'clientVersion', :to => :client_version,
:args => {:strVersion => :string},
:return => {'tns:clientVersionResult' => :string},
:response_tag => 'tns:clientVersionResponse'
soap_action 'authenticate',
:args => {:strUserName => :string, :strPassword => :string},
:return => {'tns:authenticateResult' => StringArray},
:response_tag => 'tns:authenticateResponse'
soap_action 'sendRequestXML', :to => :send_request,
:args => {:ticket => :string, :strHCPResponse => :string, :strCompanyFilename => :string, :qbXMLCountry => :string, :qbXMLMajorVers => :string, :qbXMLMinorVers => :string},
:return => {'tns:sendRequestXMLResult' => :string},
:response_tag => 'tns:sendRequestXMLResponse'
soap_action 'receiveResponseXML', :to => :receive_response,
:args => {:ticket => :string, :response => :string, :hresult => :string, :message => :string},
:return => {'tns:receiveResponseXMLResult' => :integer},
:response_tag => 'tns:receiveResponseXMLResponse'
soap_action 'closeConnection', :to => :close_connection,
:args => {:ticket => :string},
:return => {'tns:closeConnectionResult' => :string},
:response_tag => 'tns:closeConnectionResponse'
soap_action 'connectionError', :to => :connection_error,
:args => {:ticket => :string, :hresult => :string, :message => :string},
:return => {'tns:connectionErrorResult' => :string},
:response_tag => 'tns:connectionErrorResponse'
soap_action 'getLastError', :to => :get_last_error,
:args => {:ticket => :string},
:return => {'tns:getLastErrorResult' => :string},
:response_tag => 'tns:getLastErrorResponse'
def server_version
render :soap => {"tns:serverVersionResult" => server_version_response}
end
def client_version
render :soap => {"tns:clientVersionResult" => check_client_version}
end
def authenticate
# You're given params[:strUserName] and params[:strPassword]
# to authenticate as needed for your application.
# You need to return at least a 1 element array.
# For authentication failure return a single element array
# with result[0]= "nvu"
if authFailed
result = ["nvu"]
else
# Auth has succeeded: generate a unique session token and return it. Subsequent
# calls from QWC for this session will return this token in the :ticket parameter.
# QWC really wants a 2-element array with the 2nd object an empty string.
result = ["some unique session token", ""]
end
render(:soap => {"tns:authenticateResult" => {"tns:string" => result}})
end
def send_request
# Send a valid QBXML packet back here: example
request_xml = <<-XML
<?xml version="1.0" encoding="utf-8"?>
<?qbxml version="8.0"?>
<QBXML>
<QBXMLMsgsRq onError="stopOnError">
<CustomerQueryRq iterator="Start">
<MaxReturned>25</MaxReturned>
<ActiveStatus>All</ActiveStatus>
<OwnerID>0</OwnerID>
</CustomerQueryRq>
</QBXMLMsgsRq>
</QBXML>
XML
# Ensure that the response XML has no trailing / leading whitespace
# because QB will reject the XML with a vague error of being unable
# to parse the XML stream.
render :soap => {'tns:sendRequestXMLResult' => request_xml.strip}
end
def receive_response
if params[:hresult]
logger.warn "#{params[:hresult]}: #{params[:message]}"
else
# Incoming XML comes in via params[:response] - perform your own
# business logic as necessary
end
progress = 100
render :soap => {'tns:receiveResponseXMLResult' => progress}
end
def close_connection
render :soap => {'tns:closeConnectionResult' => 'OK'}
end
def connection_error
logger.warn "#{params[:hresult]}: #{params[:message]}"
render :soap => {'tns:connectionErrorResult' => 'done'}
end
def get_last_error
session = get_session
result = ""
if session && session.error
result = session.error
end
render :soap => {'tns:getLastErrorResult' => result}
end
protected
def server_version_response
end
def check_client_version
end
end
Foo::Application.routes.draw do
# QBD web connector
get 'qbxml/qwc' => 'qbxml#qwc'
get 'qbxml/action' => 'qbxml#_generate_wsdl'
wash_out :qbxml
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment